프론트앤드/프로젝트

[포스코x코딩온] Cosmopolitan | 1~6일차 진행 상황

영최 2023. 5. 8. 02:47
728x90

✅ 1 ~3 일차 : 주제 선정

우리 조는 칵테일을 소개하는 사이트를 주제로 선정했다.

페이지 구현 예시는 아래와 같다.

페이지 구성[1/2]
페이지 구성[2/2]

✅ 4 일차 

 

처음에 react-slick 기능으로 구현하려고 했는데 내부의 카드를 사용할 때 부트스랩이랑 호환이 잘 안되었다.

react-slick 만든 태그 중에 클래스 이름이 없는 태그가 있어서 css 적용이 안되었기 때문이다.

 

그래서 스와이퍼로 변경하였고 

해당 코드는 아래와 같다.

import {Swiper, SwiperSlide} from "swiper/react";
import {EffectCoverflow, Navigation, Mousewheel} from "swiper";
import "swiper/css";
import "swiper/css/effect-coverflow";
import "swiper/css/pagination";
import "swiper/css/navigation";
import "swiper/css/scrollbar";

import "../Styles/CocktailDetail.scss";
import CocktailDetailCard from "../Components/CocktailDetailCard";

const CocktailDetail = () => {
  return (
    <div className="CocktailDetail">
      <Swiper
        effect={"coverflow"}
        grabCursor={true}
        centeredSlides={true}
        slidesPerView={4}
        coverflowEffect={{
          rotate: 10, // 회전각도
          stretch: 0,
          depth: 100, // 깊이감도
          modifier: 2, //
          slideShadows: true, //선택한 부분 밝게 나머지는 그늘지게 해준다.
        }}
        navigation={true} // 네비게이션 버튼
        mousewheel={true} // 마우스 휠
        modules={[EffectCoverflow, Navigation, Mousewheel]} // 모듈추가
        className="mySwiper"
      >
        <div className="container">
          <SwiperSlide>
            <CocktailDetailCard />
          </SwiperSlide>
          <SwiperSlide>
            <CocktailDetailCard />
          </SwiperSlide>
          <SwiperSlide>
            <CocktailDetailCard />
          </SwiperSlide>
        </div>
      </Swiper>
    </div>
  );
};
export default CocktailDetail;

여기서 주의할 점은 사용하려는 모든 swiper css를 다 import 해와야한다. 

이때 자꾸 기능이 제대로 안되서 애먹었는데 이유가 바로 import안해줘서였다.

 

이부분

import "swiper/css";
import "swiper/css/effect-coverflow";
import "swiper/css/pagination";
import "swiper/css/navigation";
import "swiper/css/scrollbar";

 

✅ 5 일차

 

아코디언 기능을 완성했다. 이부분은 아래 코드처럼 구현했다.

우선 부모 컴포넌트에서 state로 showinfos 목록을 관리하고 버튼을 누르면 부모 컴포넌트의

함수가 작동되서 업데이트 되도록 했다. 그래야 목록이 부모 컴포넌트에서 관리되고,

최종적으로 버튼이 클릭되었는지 유무에 따라 내용을 위로 올려야하기 때문이다.

 

아래 아코디언 코드가 복잡해서 필요한 부분만 넣었다.

 

자식 컴포넌트

import {useState} from "react";
import {AiOutlineMinus, AiOutlinePlus} from "react-icons/ai";
const CocktailDetailCardMenu = ({showItem, updateShowInfos, cocktailInfo}) => {
  const [showInfo, setShowInfo] = useState(showItem);

  const onshowEventHandlerClick = () => {
    const {show, ...rest} = showInfo;
    const newshowInfo = {
      show: !showInfo.show,
      ...rest,
    };
    setShowInfo(newshowInfo);
    updateShowInfos(newshowInfo);
  };
    
  return (
    <ListGroup.Item>
      <button className="btn" onClick={onshowEventHandlerClick}>
        {/* showInfo가 true라면 -표시 , false라면 +표시 */}
        {showInfo.show ? <AiOutlineMinus /> : <AiOutlinePlus />}
      </button>
      {showInfo.show && (
        <p>
          +클릭시 보여줄 내용
        </p>
      )}
    </ListGroup.Item>
  );
};
export default CocktailDetailCardMenu;

 

부모 컴포넌트

import {useState} from "react";
import Card from "react-bootstrap/Card";
import ListGroup from "react-bootstrap/ListGroup";
import "../styles/CocktailDetailCard.scss";
import CocktailDetailCardMenu from "./CocktailDetailCardMenu";
const KitchenSinkExample = ({item}) => {
  const [cocktailItem, setCocktailItem] = useState(item);
  // info를 클릭시에 볼수있도록 버튼 만들기
  const [showInfos, setShowInfos] = useState([
    {id: 1, title: "glass", show: false},
    {id: 2, title: "ingredient", show: false},
    {id: 3, title: "instruction", show: false},
  ]);
  const updateShowInfos = newshowInfo => {
    const exshowInfo = showInfos.filter(item => item.id !== newshowInfo.id);
    setShowInfos(
      [...exshowInfo, newshowInfo].sort(function (a, b) {
        return a.id - b.id; //아이디 기준 정렬
      }),
    );
  };
  return (
    <Card className="Card">
      <Card.Body>
        <ListGroup className="list-group-flush">
          {showInfos.map(showItem => {
            return (
              <CocktailDetailCardMenu
                className="CocktailDetailCardMenu"
                key={showItem.id}
                showItem={showItem}
                updateShowInfos={updateShowInfos}
                cocktailInfo={item}
              />
            );
          })}
        </ListGroup>
      </Card.Body>
    </Card>
  );
};

export default KitchenSinkExample;

 

✅ 6 일차

 

6일차에는 별점 기능을 추가하고, 아코디언 버튼 클릭시 화면이 어두워지도록 했다.

별점 기능 추가는

npm i react-simple-star-rating

를 이용했고, 관련 문서는 https://www.npmjs.com/package/react-simple-star-rating이다.

구현은 아래처럼 구현했다.

import React, { useState } from 'react'
import { Rating } from 'react-simple-star-rating'

export function MyComponent() {
  const [rating, setRating] = useState(0)

  // Catch Rating value
  const handleRating = (rate: number) => {
    setRating(rate)
  }


  return (
    <div className='App'>
      {/* set initial value */}
      <Rating onClick={handleRating} initialValue={0} />
    </div>
  )
}

 

배경이 어두워지게 만드는 건 backgroundColor의 linear-gradient속성을 이용했다. 

<Card
      className="Card"
      style={
        isShowTrue !== -1
          ? {
              backgroundImage: `linear-gradient(rgba(0, 0, 0, 0.6),rgba(0, 0, 0, 0.6)), url(${item.imagelink})`,
            }
          : {}
      }
    >
728x90