본문 바로가기

React

Detail :UI_FloatingButton 스타일 적용

import React, { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { useParams } from "react-router-dom";
import { fetchFundingDetail } from "../../../apis/funding";
import Navbar from "../../../components/Navbar";
import { useDispatch, useSelector } from "react-redux";
import { userLogout } from "../../../redux/authSlice";
import {
    MainContainer,
    LeftContainer,
    Logo,
    P,
    Button,
    RightContainer,
    NavbarDiv,
    NavigateBtn,
    NavigateDiv,
    SponsorTotal,
    Body,
    BannerImgDiv,
    BannerImg,
    IllustImg,
    TitleDiv,
    FundingDiv,
    SponserDiv,
    SponsorimgDiv,
    SponserComment,
    SponsorCommentDiv,
    FundingImgDiv,
    SponsorImg,
    FundingImg,
    ProgressBar,
    Progress,
    BetweenDiv,
    TogetherDiv,
    FloatingButton,
} from './FundingDetailStyles';

// 펀딩 상세 페이지 컴포넌트
const FundingDetail = () => {
    const navigate = useNavigate(); // React Router의 네비게이션 기능을 사용하기 위한 hook
    const { id } = useParams(); // URL 매개변수(id)를 가져옴
    const isLoggedIn = useSelector((state) => state.auth.isLoggedIn); // 추가된 코드
    const dispatch = useDispatch(); // 추가된 코드

    // 펀딩 상세 정보를 담는 상태 변수 초기화
    const [detailData, setDetailData] = useState({
        // 초기 상태를 명세서에 따라 설정
        // FundingCreate에서 받아올 Data 초기값
        itemImage: '',
        itemName: '',
        targetAmount: 0,
        publicFlag: false, // 공개, 비공개 여부
        showName: '',
        title: '',
        content: '',
        endDate: '',
        // FundignDetail에 출력되는 Data 초기값
        itemLink: '',
        currentAmount: 0,
        dday: '',
        status: false,
        achievementRate: 0,
        ownerFlag: false, // true면 수정 페이지 버튼 보여지게
        modifiedAt: '', // 수정 날짜
        // 후원자 이름 추가
        // 후원자 댓글 추가
    });

    const [sponsorDonation, setSponsorDonation] = useState({
        donation5000: 5000,
        donation10000: 10000,
        donation20000: 20000,
        donation30000: 30000,
        donationInput: '직접입력',
    });

    //
    const handledonation5000Change = () => {
        navigate(`/fundingpay/${id}?donation=${sponsorDonation.donation5000}&showName=${detailData.showName}`);
    };

    const handledonation10000Change = () => {
        navigate(`/fundingpay/${id}?donation=${sponsorDonation.donation10000}&showName=${detailData.showName}`);
    };

    useEffect(() => {
        // API를 호출하여 펀딩 상세 정보를 가져오는 함수 정의
        const fetchData = async () => {
            try {
                if (!id) {
                    // 유효한 id가 없으면 데이터를 요청하지 않음
                    return;
                }
                // 펀딩 ID를 설정하여 특정 펀딩의 상세 정보 가져오기
                // const fundingid = 1; // 예: 펀딩 ID가 1인 경우
                const data = await fetchFundingDetail(id);
                setDetailData(data); // 가져온 데이터를 상태 변수에 설정
            } catch (error) {
                if (error.response) {
                    const statusCode = error.response.status;
                    const errorMessage = error.response.data.message;
                    if (statusCode === 400) {
                        alert(errorMessage);
                    }
                }
            }
        };
        // 컴포넌트가 마운트될 때 API 호출 함수 실행
        fetchData();
    }, [id]); // 빈 배열을 전달하여 한 번만 실행하도록 설정

    // 추가된 코드
    const handleLogoutClick = () => {
        dispatch(userLogout()); // 로그아웃 액션 디스패치
        navigate('/');
    };

    return (
        <MainContainer>
            <LeftContainer>
                <Logo>Giftipie</Logo>
                <P pt="25px" fs="16px" fw="800" pb="5px" color="white">
                    기프티파이에서
                </P>
                <P fs="16px" fw="800" pb="5px" color="white">
                    정말 원하는 선물을
                </P>
                <P fs="16px" fw="800" color="white">
                    주고 받아요
                </P>
                <Button onClick={() => navigate('/')} mt="20px" w="180px" h="50px" fs="16px" bc="#FF7C7C">
                    펀딩 시작하기
                </Button>
            </LeftContainer>

            <RightContainer>
                {/* 추가된 코드 */}
                <NavbarDiv>
                    <Navbar isLoggedIn={isLoggedIn} handleLogoutClick={handleLogoutClick} />
                </NavbarDiv>

                <Body>
                    <TitleDiv>
                        <P pt="20px" fs="13px" fw="800" color="gray">
                            {detailData.status}
                        </P>
                        <P pt="10px" fs="20px" fw="900" color="white">
                            {detailData.title}
                        </P>
                        <P pt="10px" pb="10px" fs="13px" fw="800" color="white">
                            {detailData.showName}
                        </P>
                    </TitleDiv>
                    <BannerImgDiv>
                        <IllustImg src="/imgs/Icon/right-pangpang.png" alt="img" />
                        <BannerImg src={detailData.itemImage} alt="image" />
                        <IllustImg src="/imgs/Icon/left-pangpang.png" alt="img" />
                    </BannerImgDiv>
                    <NavigateDiv>
                        <NavigateBtn onClick={() => navigate(`/fundingModify/${id}`)}>🖍 수정하기</NavigateBtn>
                    </NavigateDiv>
                    <TogetherDiv bc="white">
                        <BetweenDiv pt="20px">
                            <P pt="5px" fs="13px" fw="900">
                                {detailData.itemName}
                            </P>
                        </BetweenDiv>

                        <ProgressBar>
                            <Progress width={(65 / 100) * 100} />
                        </ProgressBar>

                        <BetweenDiv>
                            <P fs="20px" fw="900" color="#FF7C7C">
                                {detailData.achievementRate}%
                            </P>
                            <P pl="60px" fs="13px" fw="800" color="gray">
                                현재&nbsp;{detailData.currentAmount}원
                            </P>
                            <P pl="30px" fs="13px" fw="800" color="gray">
                                {detailData.targetAmount}원
                            </P>
                        </BetweenDiv>

                        <BetweenDiv>
                            <P pt="20px" fs="13px" fw="800" color="gray">
                                {detailData.dday}
                            </P>
                            <P pt="20px" pb="20px" fs="13px" fw="800" color="gray">
                                {detailData.endDate}
                            </P>
                        </BetweenDiv>
                    </TogetherDiv>
                    <FundingDiv>
                        <P pt="20px" pl="23px" pb="20px" fs="16px" fw="900">
                            후원자
                        </P>

                        <BetweenDiv>
                            <SponsorImg src="/imgs/Character/iu.jpg" alt="image" />
                            <SponserComment mt="10px">
                                <P pl="5px" fs="13px" fw="800">
                                    후원자 보여줄 이름
                                </P>
                                <SponsorCommentDiv mt="5px">{detailData.content}</SponsorCommentDiv>
                            </SponserComment>
                        </BetweenDiv>

                        <SponserDiv>
                            <SponsorImg src="/imgs/Character/songjoongy.jpg" alt="image" />
                            <SponserComment mt="10px">
                                <P pl="5px" fs="13px" fw="800">
                                    후원자 보여줄 이름
                                </P>
                                <SponsorCommentDiv mt="5px">줄이어폰 그만써~ 생일축하해!!</SponsorCommentDiv>
                            </SponserComment>
                        </SponserDiv>

                        <SponserDiv>
                            <SponsorImg src="/imgs/Character/junjihyun.jpg" alt="img" />
                            <SponserComment mt="10px">
                                <P pl="5px" fs="13px" fw="800">
                                    후원자 보여줄 이름
                                </P>
                                <SponsorCommentDiv mt="5px">생일 축하 축하~!!!</SponsorCommentDiv>
                            </SponserComment>
                        </SponserDiv>
                        <SponsorTotal>
                            <P onClick={() => navigate('/fundingsponsordetail')} pt="40px" pb="20px" fs="14px" fw="800">
                                전체보기 ▶
                            </P>
                        </SponsorTotal>
                    </FundingDiv>
                    <FundingDiv p="20px">
                        <P pt="20px" pl="10px" fs="16px" fw="900">
                            펀딩 참여하기
                        </P>

                        <Button onClick={handledonation5000Change} mt="30px" w="100%" h="60px" bc="lightgray">
                            <SponsorimgDiv>
                                <FundingImgDiv>
                                    <FundingImg src="/imgs/Gift/coffee.png" alt="image" h="38px" ml="25px" />
                                </FundingImgDiv>
                                <BetweenDiv>
                                    <P pt="5px" fs="14px" fw="800">
                                        커피 한잔 선물하기
                                    </P>
                                    <P pt="5px" fs="14px" fw="700">
                                        {sponsorDonation.donation5000}원
                                    </P>
                                </BetweenDiv>
                            </SponsorimgDiv>
                        </Button>

                        <Button onClick={handledonation10000Change} mt="10px" w="100%" h="60px" bc="lightgray">
                            <SponsorimgDiv>
                                <FundingImgDiv>
                                    <FundingImg src="/imgs/Gift/icecream.png" alt="image" h="50px" ml="10px" />
                                </FundingImgDiv>
                                <BetweenDiv>
                                    <P pb="6px" fs="14px" fw="800">
                                        아이스크림 선물하기
                                    </P>
                                    <P pb="6px" fs="14px" fw="700">
                                        {sponsorDonation.donation10000}원
                                    </P>
                                </BetweenDiv>
                            </SponsorimgDiv>
                        </Button>

                        <Button onClick={() => navigate('/fundingpay')} mt="10px" w="100%" h="60px" bc="lightgray">
                            <BetweenDiv>
                                {/* <FundingImg src="/imgs/Gift/coffee.png" alt="image" h="40px"/> */}
                                <P pt="3px" fs="14px" fw="800">
                                    이 펀딩 끝내러 왔다
                                </P>
                                <P pt="3px" fs="14px" fw="700">
                                    {detailData.currentAmount}원
                                </P>
                            </BetweenDiv>
                        </Button>

                        <Button onClick={() => navigate('/fundingpay')} mt="10px" w="100%" h="60px" bc="lightgray">
                            <BetweenDiv>
                                {/* <FundingImg src="/imgs/Gift/coffee.png" alt="image" h="40px"/> */}
                                <P pt="3px" fs="14px" fw="800">
                                    원하는 만큼 선물하기
                                </P>
                                <P pt="3px" fs="14px" fw="700">
                                    {sponsorDonation.donationInput}
                                </P>
                            </BetweenDiv>
                        </Button>
                    </FundingDiv>

                    <Button
                        onClick={() => navigate('/fundingpay')}
                        w="100%"
                        h="60px"
                        color="black"
                        fs="20px"
                        bc="#FF7C7C"
                        as={FloatingButton} // FloatingButton 스타일을 적용
                    >
                        선물하기
                    </Button>
                </Body>
            </RightContainer>
        </MainContainer>
    );
};

export default FundingDetail;
import styled from "styled-components";
import theme from "../../../styles/theme";

// 전체 컨테이너
export const MainContainer = styled.div`
  display: flex;
  justify-content: center;
  max-width: 1200px;
  min-height: 100vh;
  margin: 0 auto;
  flex-wrap: wrap;
`;

// 왼쪽 컨테이너
export const LeftContainer = styled.div`
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  width: 500px;
  height: 100vh;
  margin-right: 100px;

  @media (max-width: 1024px) {
    display: none;
  }
`;

export const Logo = styled.h1`
  font-size: 30px;
  font-weight: 700;
  color: white;
`;

export const P = styled.p`
  padding-top: ${(props) => props.pt};
  padding-bottom: ${(props) => props.pb};
  padding-left: ${(props) => props.pl};
  padding-right: ${(props) => props.pr};
  font-size: ${(props) => props.fs};
  font-weight: ${(props) => props.fw};
  color: ${(props) => props.color};
  align-items: center;
  &:hover {
    cursor: pointer;
  }
`;

export const Button = styled.button`
  justify-content: center;
  align-items: center;
  width: ${(props) => props.w};
  height: ${(props) => props.h};
  padding: 10px;
  background-color: ${(props) => props.bc};
  border-radius: 7px;
  color: ${(props) => props.color};
  font-size: ${(props) => props.fs};
  font-weight: 600;
  margin-top: ${(props) => props.mt};
  margin-bottom: ${(props) => props.mb};
  padding-left: ${(props) => props.pl};
  padding-right: ${(props) => props.pr};
  &:hover {
    color: white;
    background-color: #FF7C7C;
    cursor: pointer;
  }
`;

export const SponsorCommentDiv = styled.div`
  border-radius: 7px;
  padding: 10px;
  justify-content: center;
  align-items: center;
  background-color: #FFE6C1;
  margin-top: ${(props) => props.mt};
  width: 100%;
  font-size: 13px;
  font-weight: 600;
`

// 오른쪽 컨테이너
export const RightContainer = styled.div`
  position: relative;
  width: -webkit-fill-available; /* 사용 가능한 너비로 채움 */
  max-width: 390px; /* 최대 너비를 390px로 제한 */
  margin: 0 auto; /* 가운데 정렬을 위해 margin을 auto로 설정 */
  /* border: 1px solid lightgray; */
  height: 100vh;
  overflow-y: scroll;
  &::-webkit-scrollbar {
    display: none;
  }

  @media screen and (max-width: 390px) {
    max-width: 100%; /* 최대 너비를 100%로 설정하여 가득 차게 함 */
  }
`;

// 네브바 영역
export const NavbarDiv = styled.div`
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  height: 70px;
`;

// 바디 영역
export const Body = styled.div`
  font-size: 24px;
  font-weight: 800;
  height: auto;
`;

export const BannerImgDiv = styled.div`
  text-align: center;
  margin-bottom: 10px;
`;

export const BannerImg = styled.img`
  width: 100%;
  max-width: 150px;
  height: 100%;
  max-height: 150px;
  border-radius: 20px;
`;

export const IllustImg = styled.img`
  width: 100%;
  max-width: 90px;
  height: 100%;
  max-height: 90px;
  margin: 10px;
`;
export const NavigateDiv = styled.div`
  text-align: right;
  margin-right: 22px;
`
export const NavigateBtn = styled.button`
  font-size: 13px;
  font-weight: 600;
  color: white;
  margin-bottom: 7px;
  
`;

export const TitleDiv = styled.div`
  display: flex;
  flex-direction: column; 
  justify-content: center;
  align-items: center;
  width: 100%;
`;

export const FundingDiv = styled.div`
  background-color: white;
  border-radius: 20px;
  border: 0.3px solid lightgray;
  width: -webkit-fill-available; /* 사용 가능한 너비로 채움 */
  max-width: 390px; /* 최대 너비를 390px로 제한 */
  margin: 0 auto; /* 가운데 정렬을 위해 margin을 auto로 설정 */
  margin-bottom: 15px;
  padding: ${(props) => props.p};

  @media screen and (max-width: 390px) {
    max-width: 100%; /* 최대 너비를 100%로 설정하여 가득 차게 함 */
  }
`;

export const FundingNewline = styled.div`
  width: 100%;
  height: 12px;
`;

export const ProgressBar = styled.div`
  width: 85%;
  height: 15px;
  background-color: #dedede;
  border-radius: 12px;
  font-weight: 600;
  font-size: 0.8rem;
  margin: 10px 30px 10px 30px;
  text-align: center;
  overflow: hidden;
  padding-left: ${(props) => props.pl};
  padding-right: ${(props) => props.pr};
`;

export const Progress = styled.div`
  width: ${(props) => props.width}%;
  height: 15px;
  padding: 0;
  text-align: center;
  background-color: ${theme.primary};
  border-radius: 15px;
  /* color: #111; */
  padding-left: ${(props) => props.pl};
  padding-right: ${(props) => props.pr};
`;

export const BetweenDiv = styled.div`
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  width: -webkit-fill-available; /* 사용 가능한 너비로 채움 */
  max-width: 390px; /* 최대 너비를 390px로 제한 */
  margin: 0 auto; /* 가운데 정렬을 위해 margin을 auto로 설정 */
  /* padding: 0px 33px 0px 33px; */
  padding: 0px 33px 0px 33px;
  padding-top: ${(props) => props.pt};

  @media screen and (max-width: 390px) {
    max-width: 100%; /* 최대 너비를 100%로 설정하여 가득 차게 함 */
  }
`;

export const TogetherDiv = styled.div`
  background-color: ${(props) => props.bc};
  border-radius: 20px;
  border: 0.3px solid lightgray;
  box-shadow: 0px 5px 0px 0px lightgray;
  width: -webkit-fill-available; /* 사용 가능한 너비로 채움 */
  max-width: 390px; /* 최대 너비를 390px로 제한 */
  margin: 0 auto; /* 가운데 정렬을 위해 margin을 auto로 설정 */
  margin-bottom: 15px;

  @media screen and (max-width: 390px) {
    max-width: 100%; /* 최대 너비를 100%로 설정하여 가득 차게 함 */
  }
`;

export const SponserDiv = styled.div`
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  padding: 0px 33px 0px 33px;
`;

export const SponserComment = styled.div`
  margin-top: ${(props) => props.mt};
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: start;
  width: 100%;
`;

export const SponsorImg = styled.img`
  width: 50px;
  height: 50px;
  border-radius: 100px;
  margin: 10px;
`;

export const SponsorTotal = styled.div`
  text-align: center;
`;

export const FundingImgDiv = styled.div`
  height: 50px;
  width: 50px;
`;

export const FundingImg = styled.img`
  height: ${(props) => props.h};
  margin-left: ${(props) => props.ml};
  margin-bottom: ${(props) => props.mb};
  margin-bottom: 1px;
`;

export const SponsorimgDiv = styled.div`
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
`;

export const FloatingButton = styled.button`
  position: fixed;
  bottom: 0;
  left: 50%; /* 뷰포트의 가운데로 이동 */
  transform: translateX(-50%); /* 가운데 정렬 */
  margin-bottom: 30px;
  width: 220px; /* 버튼의 너비 조정 */
  height: 50px; /* 버튼의 높이 조정 */
  border-radius: 25px; /* 버튼의 모양을 둥글게 만듭니다. */
  background-color: #FF7C7C; /* 버튼의 배경색을 지정합니다. */
  color: white; /* 버튼 텍스트의 색상을 지정합니다. */
  font-size: 16px; /* 버튼 텍스트의 크기를 지정합니다. */
  font-weight: bold; /* 버튼 텍스트의 굵기를 지정합니다. */
  border: none; /* 버튼의 테두리를 없앱니다. */
  cursor: pointer; /* 버튼에 마우스를 올리면 커서를 포인터로 변경합니다. */
  z-index: 1000; /* 다른 요소 위에 버튼을 표시합니다. */
`;