Skip to content

Commit

Permalink
Merge pull request #45 from K-Hackathon-Fledge/develop
Browse files Browse the repository at this point in the history
[DEPLOY] 진행 내역 공유를 위한 1차 배포
  • Loading branch information
seokkkkkk authored Aug 9, 2024
2 parents f7deb5e + 33452b2 commit 2067be0
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 104 deletions.
32 changes: 24 additions & 8 deletions src/apis/sponsor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,10 @@ export const getPagingPost = async (
}
};

export const getDeadlinePost = async (page: number) => {
export const getDeadlinePost = async () => {
try {
const res = await axios.get(
`/api/v1/public/supports/deadline?paging=${page}`,
{
headers: {
"Content-Type": "application/json",
},
}
const res = await axiosInstance.get(
`/api/v1/public/supports/deadline-approaching`
);
return res.data.data;
} catch (error) {
Expand Down Expand Up @@ -203,3 +198,24 @@ export const getCanaryInfo = async (memberId: number) => {
}
}
};

export const deleteSupportPost = async (
supportId: string,
accesstoken: string
) => {
try {
const res = await axiosInstance.delete(`/api/v1/supports/${supportId}`, {
headers: {
Authorization: `Bearer ${accesstoken}`,
},
});
return res.data;
} catch (error) {
console.log(error);
if (axios.isAxiosError<CommonError>(error) && error.response) {
const errorCode = error.response.data.errorCode;
const message = error.response.data.message;
console.log(`${errorCode}: ${message}`);
}
}
};
50 changes: 7 additions & 43 deletions src/components/Sponsor/DeadlinePosts.tsx
Original file line number Diff line number Diff line change
@@ -1,62 +1,26 @@
import { useQuery } from "@tanstack/react-query";
import React, { useEffect, useState } from "react";
import React from "react";
import { getDeadlinePost } from "../../apis/sponsor";
import Slider from "./Slider";
import { SponsorBannerData } from "../../@types/sponsor";

import tw from "twin.macro";
import styled from "styled-components";
import NoBanner from "../../assets/images/no_banner.png";
function DeadlinePosts() {
const [currentPage, setCurrentPage] = useState(0);
const [combinedPosts, setCombinedPosts] = useState<SponsorBannerData[]>([]);

const {
data: PostData,
isLoading: isLoadingCurrent,
isLoading,
error,
} = useQuery({
queryKey: ["getDeadlinePosts", currentPage],
queryFn: () => getDeadlinePost(currentPage),
});

const { data: previousPosts, isLoading: isLoadingPrevious } = useQuery({
queryKey: ["getDeadlinePosts", currentPage],
queryFn: () => getDeadlinePost(currentPage - 1),
enabled: currentPage > 0,
});

const { data: nextPosts, isLoading: isLoadingNext } = useQuery({
queryKey: ["getDeadlinePosts", currentPage],
queryFn: () => getDeadlinePost(currentPage + 1),
enabled: PostData && PostData.totalPages > currentPage,
queryKey: ["getDeadlinePosts"],
queryFn: () => getDeadlinePost(),
});

useEffect(() => {
if (PostData || previousPosts || nextPosts) {
setCombinedPosts([
...(previousPosts?.supportPosts || []),
...(PostData?.supportPosts || []),
...(nextPosts?.supportPosts || []),
]);
}
}, [previousPosts, PostData, nextPosts]);

if (isLoadingCurrent || isLoadingPrevious || isLoadingNext) {
return <div>Loading...</div>; // 로딩 상태 표시
}

if (error) {
return <div>Error loading posts</div>; // 에러 상태 표시
}
if (combinedPosts.length > 0) {
return (
<Slider
totalPages={PostData.totalPages}
currentPage={currentPage}
setCurrentPage={setCurrentPage}
items={combinedPosts}
/>
);
if (!isLoading && PostData.length > 0) {
return <Slider items={PostData} />;
} else {
return (
<NoPostWrapper>
Expand Down
49 changes: 20 additions & 29 deletions src/components/Sponsor/Slider.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from "react";
import React, { useCallback, useState } from "react";
import tw from "twin.macro";
import styled from "styled-components";
import BannerItem from "./BannerItem";
Expand All @@ -7,41 +7,30 @@ import RightArrowIcon from "../../assets/icons/right-arrow";
import { SponsorBannerData } from "../../@types/sponsor";

type SliderProps = {
totalPages: number;
currentPage: number;
items: SponsorBannerData[];
setCurrentPage: (page: number) => void;
};
function Slider({
totalPages,
currentPage,
items,
setCurrentPage,
}: SliderProps) {
const [translateX, setTranslateX] = useState(0);
const handleNext = () => {
if (totalPages > currentPage + 1) {
setCurrentPage(currentPage + 1);
}
};
function Slider({ items }: SliderProps) {
const [currentIndex, setCurrentIndex] = useState(0);
const itemsToShow = 4; // 한 번에 보여줄 배너 수

const handlePrev = () => {
if (currentPage > 0) {
setCurrentPage(currentPage - 1);
}
};
// 전체 아이템을 페이지 단위로 나누기
const totalPages = Math.ceil(items.length / itemsToShow);

useEffect(() => {
setTranslateX(-currentPage * 100); // 페이지 변경 시 위치 업데이트
}, [currentPage]);
const handlePrevClick = useCallback(() => {
setCurrentIndex((prevIndex) => Math.max(prevIndex - 1, 0));
}, []);

const handleNextClick = useCallback(() => {
setCurrentIndex((prevIndex) => Math.min(prevIndex + 1, totalPages - 1));
}, [totalPages]);

return (
<Wrapper>
<Button onClick={handlePrev} disabled={currentPage === 0}>
<Button onClick={handlePrevClick} disabled={currentIndex === 0}>
<LeftArrowIcon width={25} height={51} />
</Button>
<SliderContainer>
<ItemBox translateX={translateX}>
<ItemBox translateX={-currentIndex * 100}>
{items.map((data: SponsorBannerData, index: number) => (
<BannerItem
key={index}
Expand All @@ -54,7 +43,10 @@ function Slider({
))}
</ItemBox>
</SliderContainer>
<Button onClick={handleNext} disabled={currentPage === totalPages - 1}>
<Button
onClick={handleNextClick}
disabled={currentIndex >= totalPages - 1}
>
<RightArrowIcon width={25} height={51} />
</Button>
</Wrapper>
Expand All @@ -72,9 +64,8 @@ const SliderContainer = styled.div`
`;

const ItemBox = styled.div<{ translateX: number }>`
${tw`flex items-center `}
${tw`flex items-center transition-transform duration-300 ease-in-out`}
transform: translateX(${(props) => props.translateX}%);
transition: transform 0.5s ease-in-out;
gap: 20px;
`;

Expand Down
78 changes: 78 additions & 0 deletions src/components/SponsorDetail/DeleteModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import React, { useState } from "react";
import styled from "styled-components";
import tw from "twin.macro";
import { deleteSupportPost } from "../../apis/sponsor";
import useAuthStore from "../../storage/useAuthStore";
import { useNavigate, useParams } from "react-router-dom";
function DeleteModal({ onClose }: { onClose: () => void }) {
const { supportId } = useParams() as { supportId: string };
const accessToken = useAuthStore((state) => state.accessToken!);

const [isFinished, setIsFinished] = useState(false);

const navigate = useNavigate();
const handleDelete = async () => {
const res = await deleteSupportPost(supportId, accessToken);

if (res.success) {
setIsFinished(true);
}
};
return (
<Overlay onClick={onClose}>
{!isFinished ? (
<Wrapper onClick={(e) => e.stopPropagation()}>
<span className="bold-36">정말로 게시물을 삭제할까요?</span>
<span className="medium-20">
게시물을 삭제하면 그동안 모인 후원금도 받을 수 없게 됩니다.
</span>
<ButtonWrapper className="w-[247px]">
<Button onClick={onClose}>뒤로가기</Button>
<Button delete onClick={handleDelete}>
삭제하기
</Button>
</ButtonWrapper>
</Wrapper>
) : (
<Wrapper>
<span className="bold-36">게시물 삭제가 완료되었습니다. </span>
<ButtonWrapper>
<Button onClick={() => navigate("/sponsor")}>닫기</Button>
</ButtonWrapper>
</Wrapper>
)}
</Overlay>
);
}

export default DeleteModal;

const Overlay = styled.div`
${tw`
w-full h-full bg-[black] bg-opacity-50
fixed top-[50%] left-[50%] transform translate-x-[-50%] translate-y-[-50%]
flex justify-center items-center
z-[2]
`}
`;
const Wrapper = styled.div`
${tw`w-[636px] h-[294px] [border-radius: 16px] bg-background flex flex-col m-auto items-center justify-center font-sans`}
.bold-36 {
${tw`font-bold text-bold-36 text-fontColor1`}
}
.medium-20 {
${tw`font-medium text-medium-20 text-fontColor3 mt-4`}
}
`;
const ButtonWrapper = styled.div`
${tw`flex flex-row justify-between mt-7`}
`;

const Button = styled.button<{ delete?: boolean }>`
${tw` px-4 py-2 rounded-full font-bold text-bold-20`}
${({ delete: isDelete }) =>
isDelete
? tw`bg-subColor text-white`
: tw`text-subColor border-2 border-subColor`}
`;
59 changes: 35 additions & 24 deletions src/components/SponsorDetail/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,52 @@
import React from "react";
import React, { useState } from "react";
import styled from "styled-components";
import tw from "twin.macro";

import DefaultProfile from "../../assets/images/profile.png";
import { useQuery } from "@tanstack/react-query";
import { getCanaryInfo } from "../../apis/sponsor";
import useAuthStore from "../../storage/useAuthStore";
import DeleteModal from "./DeleteModal";
type HeaderProps = {
memberId: number;
};
function Header({ memberId }: HeaderProps) {
const [isOpenDelete, setIsOpenDelete] = useState(false);
const currentUserId = useAuthStore((state) => state.userData.id);
const { data, isLoading, error } = useQuery({
queryKey: ["getCanaryInfo"],
queryFn: () => getCanaryInfo(memberId),
});
// const { data, isLoading, error } = useQuery({
// queryKey: ["getCanaryInfo"],
// queryFn: () => getCanaryInfo(memberId),
// });
return (
<Container>
<RowBox>
<img src={DefaultProfile} className="profile-img" alt="프로필 이미지" />
<ColBox className="ml-5">
<span className="nickname">카드값줘체리</span>
<RowBox>
<span className="bold-span">후원 인증률 100% </span>
<span className="medium-span"> 6/6 인증</span>
</RowBox>
</ColBox>
</RowBox>
{memberId !== currentUserId! ? (
<StyledBtn main>후원하기</StyledBtn>
) : (
<RowBox className="w-[250px]">
<StyledBtn main={false}>수정하기</StyledBtn>
<StyledBtn main>삭제하기</StyledBtn>
<>
<Container>
<RowBox>
<img
src={DefaultProfile}
className="profile-img"
alt="프로필 이미지"
/>
<ColBox className="ml-5">
<span className="nickname">카드값줘체리</span>
<RowBox>
<span className="bold-span">후원 인증률 100% </span>
<span className="medium-span"> 6/6 인증</span>
</RowBox>
</ColBox>
</RowBox>
)}
</Container>
{memberId !== currentUserId! ? (
<StyledBtn main>후원하기</StyledBtn>
) : (
<RowBox className="w-[250px]">
<StyledBtn main={false}>수정하기</StyledBtn>
<StyledBtn main onClick={() => setIsOpenDelete(!isOpenDelete)}>
삭제하기
</StyledBtn>
</RowBox>
)}
</Container>
{isOpenDelete && <DeleteModal onClose={() => setIsOpenDelete(false)} />}
</>
);
}

Expand Down

0 comments on commit 2067be0

Please sign in to comment.