From 426d2e04140d960edf816cfa0bc097ba56a7befd Mon Sep 17 00:00:00 2001 From: SKY-PEY Date: Wed, 24 Jan 2024 01:33:45 +0900 Subject: [PATCH 01/14] Fix: add function checked by default --- src/pages/Vote/VoteMemo/VoteMemo.tsx | 34 +++++++++++++++++++--------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/pages/Vote/VoteMemo/VoteMemo.tsx b/src/pages/Vote/VoteMemo/VoteMemo.tsx index c4af8a7d..49339ae8 100644 --- a/src/pages/Vote/VoteMemo/VoteMemo.tsx +++ b/src/pages/Vote/VoteMemo/VoteMemo.tsx @@ -5,6 +5,7 @@ import {useRecoilState} from 'recoil'; import styles from './VoteMemo.module.scss'; +import useGetSelectedArray from '@/hooks/useGetSelectedArray'; import {useGetVotesInfo} from '@/hooks/Votes/vote'; import BottomSlide from '@/components/BottomSlide/BottomSlide'; @@ -15,30 +16,41 @@ import MemoContent from '@/components/VoteMemo/MemoContent'; import {isBottomSlideOpenState} from '@/recoil/vote/bottomSlide'; import {selectedTaglineState} from '@/recoil/vote/voteMemo'; +import {TaglineType} from '@/types/vote'; + const VoteMemo = () => { const {id: voteId} = useParams(); const {data: voteInfo} = useGetVotesInfo(Number(voteId)); // const navigate = useNavigate(); const [isBTOpen, setIsBTOpen] = useRecoilState(isBottomSlideOpenState); const [selectedTagline, setSelectedTagline] = useRecoilState(selectedTaglineState); + const {toggleItemInNewArray} = useGetSelectedArray(selectedTaglineState); + + const getExistingTaglines = localStorage.getItem('recoil-persist'); + + const setInitializeTagline = () => { + setSelectedTagline(voteInfo.candidates.map(({placeInfo}) => ({placeId: placeInfo.placeId, tagline: ''}))); + }; + + const setExistingTagline = () => { + const existingTaglines: TaglineType[] = getExistingTaglines && JSON.parse(getExistingTaglines).selectedTaglineState; - const existingTaglines = localStorage.getItem('recoil-persist'); + const nonExistPlaceIds = voteInfo.candidates + .map(({placeInfo}) => placeInfo.placeId) + .filter((placeId) => !existingTaglines.some((tagline) => tagline.placeId === placeId)); - const initializeTaglineState = () => { - const initialTaglines = voteInfo.candidates.map((candidate) => ({ - placeId: candidate.placeInfo.placeId, - tagline: '', - })); - setSelectedTagline(initialTaglines); + nonExistPlaceIds.map((placeId) => ({placeId, tagline: ''})).forEach((tagline) => toggleItemInNewArray(tagline)); }; useEffect(() => { - if (!existingTaglines) { - initializeTaglineState(); + if (getExistingTaglines) { + setExistingTagline(); + } else { + setInitializeTagline(); } }, []); - const addNewCandidates = () => { + const handleAddCandidates = () => { console.log('최종 내용 : ', selectedTagline); localStorage.removeItem('recoil-persist'); //navigate(`/votes/${voteInfo.id}`) @@ -49,7 +61,7 @@ const VoteMemo = () => { setIsBTOpen(true)} /> - From 2cea4f45d704911fd5ed9f00b7b7004469dd8629 Mon Sep 17 00:00:00 2001 From: SKY-PEY Date: Wed, 24 Jan 2024 01:34:20 +0900 Subject: [PATCH 02/14] Design: edit title styles --- .../Vote/VoteContent/CandidateCard/CandidateCard.module.scss | 4 ++-- .../Vote/VoteContent/CandidateCard/CandidateCard.tsx | 4 +++- src/components/VoteMemo/MemoItem/MemoItem.module.scss | 3 ++- src/mocks/handlers/vote.ts | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/components/Vote/VoteContent/CandidateCard/CandidateCard.module.scss b/src/components/Vote/VoteContent/CandidateCard/CandidateCard.module.scss index 3171b07f..8e28e42b 100644 --- a/src/components/Vote/VoteContent/CandidateCard/CandidateCard.module.scss +++ b/src/components/Vote/VoteContent/CandidateCard/CandidateCard.module.scss @@ -9,7 +9,6 @@ padding-right: 16px; border-radius: 16px; - // border: 2px solid $neutral200; box-shadow: $shadow200; background-color: $neutral0; @@ -62,14 +61,15 @@ display: flex; align-items: center; justify-content: space-between; + gap: 12px; &__contextBox { display: flex; flex-direction: column; - // gap: 8px; &__name { text-align: start; + white-space: pre-wrap; @include typography(titleSmall); color: $neutral900; } diff --git a/src/components/Vote/VoteContent/CandidateCard/CandidateCard.tsx b/src/components/Vote/VoteContent/CandidateCard/CandidateCard.tsx index 36cec270..f9570946 100644 --- a/src/components/Vote/VoteContent/CandidateCard/CandidateCard.tsx +++ b/src/components/Vote/VoteContent/CandidateCard/CandidateCard.tsx @@ -21,6 +21,8 @@ const CandidateCard = ({onBottomSlideOpen, candidate, showResults, index, isMapS const placeInfo = candidate.placeInfo; + //순위 받아서 색주기, 인덱스 말고 + const getRankClassName = (index: number) => { switch (index) { case 1: @@ -80,7 +82,7 @@ const CandidateCard = ({onBottomSlideOpen, candidate, showResults, index, isMapS // onClick={navigate로 넣기} disabled={isCandidateSelecting} > - {placeInfo.placeName.length >= 10 ? placeInfo.placeName.slice(0, 10) + ' ⋯' : placeInfo.placeName} + {placeInfo.placeName}
diff --git a/src/components/VoteMemo/MemoItem/MemoItem.module.scss b/src/components/VoteMemo/MemoItem/MemoItem.module.scss index 71c344b7..be8b7bcf 100644 --- a/src/components/VoteMemo/MemoItem/MemoItem.module.scss +++ b/src/components/VoteMemo/MemoItem/MemoItem.module.scss @@ -1,4 +1,4 @@ -@use "@/sass" as *; +@use '@/sass' as *; .container { width: 100%; @@ -42,6 +42,7 @@ &__name { @include typography(titleSmall); color: $neutral900; + white-space: pre-wrap; } &__category { @include typography(captionSmall); diff --git a/src/mocks/handlers/vote.ts b/src/mocks/handlers/vote.ts index e4774c9c..08a96063 100644 --- a/src/mocks/handlers/vote.ts +++ b/src/mocks/handlers/vote.ts @@ -18,7 +18,7 @@ const candidateData = [ id: 111, placeInfo: { placeId: 11111, - placeName: '기역호텔12345678', + placeName: '기역호텔12345 dddddd dddd ddddd ddddd678', category: '숙박', location: '서울', placeImageURL: 'https://m.eejmall.com/web/product/big/201708/211_shop1_627935.jpg', From 7b38d1686916bbaa2dbcd2e6448d491f2a2b48ee Mon Sep 17 00:00:00 2001 From: SKY-PEY Date: Wed, 24 Jan 2024 12:06:45 +0900 Subject: [PATCH 03/14] Feat: add calculate rank --- src/hooks/Votes/useRankCalculator.ts | 44 ++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 src/hooks/Votes/useRankCalculator.ts diff --git a/src/hooks/Votes/useRankCalculator.ts b/src/hooks/Votes/useRankCalculator.ts new file mode 100644 index 00000000..b1cb265e --- /dev/null +++ b/src/hooks/Votes/useRankCalculator.ts @@ -0,0 +1,44 @@ +import {useState} from 'react'; + +interface RankResult { + value: number; + rank: number; +} + +interface UseRankCalculator { + result: {[index: string]: RankResult}; + calculateRanks: (votes: number[]) => void; +} + +const useRankCalculator = (): UseRankCalculator => { + const [result, setResult] = useState<{[index: string]: RankResult}>({}); + + const calculateRanks = (votes: number[]): void => { + const uniqueVotes = [...new Set(votes)]; + uniqueVotes.sort((a, b) => b - a); + + const ranks: {[index: string]: RankResult} = {}; + + for (let i = 0; i < uniqueVotes.length; i++) { + const currentRank = i + 1; + const currentValue = uniqueVotes[i]; + + const duplicateIndices = votes.reduce((acc, vote, index) => { + if (vote === currentValue) { + acc.push(index); + } + return acc; + }, [] as number[]); + + duplicateIndices.forEach((index) => { + ranks[index.toString()] = {value: currentValue, rank: currentRank}; + }); + } + + setResult(ranks); + }; + + return {result, calculateRanks}; +}; + +export default useRankCalculator; From 23f8a6f43cc1e33bcb7e4043b70fbe48d04a818c Mon Sep 17 00:00:00 2001 From: SKY-PEY Date: Wed, 24 Jan 2024 14:55:45 +0900 Subject: [PATCH 04/14] Design: add design title --- src/components/Vote/VoteContent/CandidateCard/CandidateCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Vote/VoteContent/CandidateCard/CandidateCard.tsx b/src/components/Vote/VoteContent/CandidateCard/CandidateCard.tsx index f9570946..c06fcd42 100644 --- a/src/components/Vote/VoteContent/CandidateCard/CandidateCard.tsx +++ b/src/components/Vote/VoteContent/CandidateCard/CandidateCard.tsx @@ -82,7 +82,7 @@ const CandidateCard = ({onBottomSlideOpen, candidate, showResults, index, isMapS // onClick={navigate로 넣기} disabled={isCandidateSelecting} > - {placeInfo.placeName} + {placeInfo.placeName.length >= 12 ? placeInfo.placeName.slice(0, 10) + ' ⋯' : placeInfo.placeName}
From d0a77089276ea04a7419217ab42ed9cb042969a3 Mon Sep 17 00:00:00 2001 From: SKY-PEY Date: Wed, 24 Jan 2024 15:49:10 +0900 Subject: [PATCH 05/14] Design: change a common mapPin design --- .../CandidatesMapBody/CandidatesMapBody.tsx | 4 +-- ...r.module.scss => MapPinCommon.module.scss} | 2 ++ .../CandidatesMap/MapPins/MapPinCommon.tsx | 11 +++++++ .../CandidatesMap/MapPins/MapPinNumber.tsx | 11 ------- .../MapZoomIn/RouteMapBody/RouteMapBody.tsx | 4 +-- src/components/Route/MapInTrip/MapInTrip.tsx | 33 +++++++------------ src/main.tsx | 32 +++++++++--------- 7 files changed, 44 insertions(+), 53 deletions(-) rename src/components/CandidatesMap/MapPins/{MapPinNumber.module.scss => MapPinCommon.module.scss} (91%) create mode 100644 src/components/CandidatesMap/MapPins/MapPinCommon.tsx delete mode 100644 src/components/CandidatesMap/MapPins/MapPinNumber.tsx diff --git a/src/components/CandidatesMap/CandidatesMapBody/CandidatesMapBody.tsx b/src/components/CandidatesMap/CandidatesMapBody/CandidatesMapBody.tsx index 19efc636..cc41d231 100644 --- a/src/components/CandidatesMap/CandidatesMapBody/CandidatesMapBody.tsx +++ b/src/components/CandidatesMap/CandidatesMapBody/CandidatesMapBody.tsx @@ -6,7 +6,7 @@ import styles from './CandidatesMapBody.module.scss'; import CandidatesSlide from '../CandidatesSlide/CandidatesSlide'; import MapPinActive from '../MapPins/MapPinActive'; -import MapPinNumber from '../MapPins/MapPinNumber'; +import MapPinCommon from '../MapPins/MapPinCommon'; import {CandidatesInfo, Latlng} from '@/types/vote'; @@ -37,7 +37,7 @@ const CandidatesMapBody = ({candidates}: {candidates: CandidatesInfo[]}) => { className={`pin ${selectedPinIndex === i ? 'active' : ''}`} onClick={() => handleMapMarkerClick(candidate.placeInfo.latlng, i)} > - {selectedPinIndex === i ? : } + {selectedPinIndex === i ? : }
))} diff --git a/src/components/CandidatesMap/MapPins/MapPinNumber.module.scss b/src/components/CandidatesMap/MapPins/MapPinCommon.module.scss similarity index 91% rename from src/components/CandidatesMap/MapPins/MapPinNumber.module.scss rename to src/components/CandidatesMap/MapPins/MapPinCommon.module.scss index 417c45b5..f02d2e82 100644 --- a/src/components/CandidatesMap/MapPins/MapPinNumber.module.scss +++ b/src/components/CandidatesMap/MapPins/MapPinCommon.module.scss @@ -3,6 +3,8 @@ .container { width: 32px; height: 32px; + + border: 2px solid #fff; border-radius: 50%; background-color: $secondary400; display: flex; diff --git a/src/components/CandidatesMap/MapPins/MapPinCommon.tsx b/src/components/CandidatesMap/MapPins/MapPinCommon.tsx new file mode 100644 index 00000000..be2f5b38 --- /dev/null +++ b/src/components/CandidatesMap/MapPins/MapPinCommon.tsx @@ -0,0 +1,11 @@ +import styles from './MapPinCommon.module.scss'; + +const MapPinCommon = ({number}: {number: number}) => { + return ( +
+

{number}

+
+ ); +}; + +export default MapPinCommon; diff --git a/src/components/CandidatesMap/MapPins/MapPinNumber.tsx b/src/components/CandidatesMap/MapPins/MapPinNumber.tsx deleted file mode 100644 index 82d4944b..00000000 --- a/src/components/CandidatesMap/MapPins/MapPinNumber.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import styles from './MapPinNumber.module.scss'; - -const MapPinNumber = ({number}: {number: number}) => { - return ( -
-

{number}

-
- ); -}; - -export default MapPinNumber; diff --git a/src/components/MapZoomIn/RouteMapBody/RouteMapBody.tsx b/src/components/MapZoomIn/RouteMapBody/RouteMapBody.tsx index 66c87c61..340e7a9d 100644 --- a/src/components/MapZoomIn/RouteMapBody/RouteMapBody.tsx +++ b/src/components/MapZoomIn/RouteMapBody/RouteMapBody.tsx @@ -6,7 +6,7 @@ import styles from './RouteMapBody.module.scss'; import RouteMapSlide from '../RouteMapSlide/RouteMapSlide'; import MapPinActive from '../../CandidatesMap/MapPins/MapPinActive'; -import MapPinNumber from '../../CandidatesMap/MapPins/MapPinNumber'; +import MapPinCommon from '../../CandidatesMap/MapPins/MapPinCommon'; import {Journeys, LatLng} from '@/types/route'; @@ -58,7 +58,7 @@ const RouteMapBody = ({journeys}: Journeys) => { className={`pin ${selectedPinIndex === i ? 'active' : ''}`} onClick={() => handleMapMarkerClick({lat: place.place.latitude, lng: place.place.latitude}, i)} > - {selectedPinIndex === i ? : } + {selectedPinIndex === i ? : }
diff --git a/src/components/Route/MapInTrip/MapInTrip.tsx b/src/components/Route/MapInTrip/MapInTrip.tsx index 767826f4..57e0a116 100644 --- a/src/components/Route/MapInTrip/MapInTrip.tsx +++ b/src/components/Route/MapInTrip/MapInTrip.tsx @@ -1,36 +1,25 @@ -import { CustomOverlayMap, Map, Polyline } from "react-kakao-maps-sdk"; +import {CustomOverlayMap, Map, Polyline} from 'react-kakao-maps-sdk'; -import styles from "./MapInTrip.module.scss"; +import styles from './MapInTrip.module.scss'; -import MapPinNumber from "@/components/CandidatesMap/MapPins/MapPinNumber"; +import MapPinCommon from '@/components/CandidatesMap/MapPins/MapPinCommon'; -import { MapInTripProps } from "@/types/route"; +import {MapInTripProps} from '@/types/route'; -function MapInTrip({ mapRef, center }: MapInTripProps) { +function MapInTrip({mapRef, center}: MapInTripProps) { const linePath = [ - { lat: 37.76437082535426, lng: 128.87675285339355 }, - { lat: 37.7911054, lng: 128.9149116 }, - { lat: 37.6964635, lng: 128.890664 }, + {lat: 37.76437082535426, lng: 128.87675285339355}, + {lat: 37.7911054, lng: 128.9149116}, + {lat: 37.6964635, lng: 128.890664}, ]; return ( - - + + {linePath.map((item, index) => (
- +
))} diff --git a/src/main.tsx b/src/main.tsx index b7509afa..1a091569 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,28 +1,28 @@ -import { ChakraProvider } from "@chakra-ui/react"; -import React from "react"; -import ReactDOM from "react-dom/client"; -import { RecoilRoot } from "recoil"; +import {ChakraProvider} from '@chakra-ui/react'; +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import {RecoilRoot} from 'recoil'; -import App from "./App.tsx"; -import { customTheme } from "./chakra/chakraCustomTheme.ts"; +import App from './App.tsx'; +import {customTheme} from './chakra/chakraCustomTheme.ts'; async function enableMocking() { - if (import.meta.env.MODE !== "development") { + if (import.meta.env.MODE !== 'development') { return; } - const { worker } = await import("./mocks/browser"); + const {worker} = await import('./mocks/browser'); return worker.start(); } enableMocking().then(() => { - ReactDOM.createRoot(document.getElementById("root")!).render( - - - - - - - , + ReactDOM.createRoot(document.getElementById('root')!).render( + // + + + + + , + // ); }); From 42aaf410e6dacd0bbe586c5af1a2cb769f86369a Mon Sep 17 00:00:00 2001 From: SKY-PEY Date: Wed, 24 Jan 2024 16:47:56 +0900 Subject: [PATCH 06/14] Refactor: change showResults state to recoil --- .../CandidatesSlide/CandidatesSlide.tsx | 2 +- .../Vote/VoteContent/CandidateCard/CandidateCard.tsx | 4 +++- .../Vote/VoteContent/CandidateList/CandidateList.tsx | 7 +------ src/pages/Vote/Vote.tsx | 12 ++++++------ src/recoil/vote/showResults.ts | 6 ++++++ src/types/vote.ts | 1 - 6 files changed, 17 insertions(+), 15 deletions(-) create mode 100644 src/recoil/vote/showResults.ts diff --git a/src/components/CandidatesMap/CandidatesSlide/CandidatesSlide.tsx b/src/components/CandidatesMap/CandidatesSlide/CandidatesSlide.tsx index 64ec0af2..2db3e749 100644 --- a/src/components/CandidatesMap/CandidatesSlide/CandidatesSlide.tsx +++ b/src/components/CandidatesMap/CandidatesSlide/CandidatesSlide.tsx @@ -27,7 +27,7 @@ const CandidatesSlide = ({candidates, setSelectedPinIndex, setCenterMarker, swip > {candidates.map((candidate, i) => ( - + ))} diff --git a/src/components/Vote/VoteContent/CandidateCard/CandidateCard.tsx b/src/components/Vote/VoteContent/CandidateCard/CandidateCard.tsx index c06fcd42..5c14e683 100644 --- a/src/components/Vote/VoteContent/CandidateCard/CandidateCard.tsx +++ b/src/components/Vote/VoteContent/CandidateCard/CandidateCard.tsx @@ -9,15 +9,17 @@ import SecondIcon from '@/assets/voteIcons/rank_2.svg?react'; import ThirdIcon from '@/assets/voteIcons/rank_3.svg?react'; import AddDayIcon from '@/assets/voteIcons/vote_addDay.svg?react'; import {isCandidateSelectingState} from '@/recoil/vote/alertModal'; +import {showResultsState} from '@/recoil/vote/showResults'; import AddToJourney from '../../VoteBottomSlideContent/AddToJourney/AddToJourney'; import VotedUserList from '../../VoteBottomSlideContent/VotedUserList/VotedUserList'; import {CandidateCardProps} from '@/types/vote'; -const CandidateCard = ({onBottomSlideOpen, candidate, showResults, index, isMapStyle}: CandidateCardProps) => { +const CandidateCard = ({onBottomSlideOpen, candidate, index, isMapStyle}: CandidateCardProps) => { const [isVoted, setIsVoted] = useState(false); const isCandidateSelecting = useRecoilValue(isCandidateSelectingState); + const showResults = useRecoilValue(showResultsState); const placeInfo = candidate.placeInfo; diff --git a/src/components/Vote/VoteContent/CandidateList/CandidateList.tsx b/src/components/Vote/VoteContent/CandidateList/CandidateList.tsx index 4f786258..bcf57d2b 100644 --- a/src/components/Vote/VoteContent/CandidateList/CandidateList.tsx +++ b/src/components/Vote/VoteContent/CandidateList/CandidateList.tsx @@ -33,12 +33,7 @@ const CandidateList = ({candidates, onBottomSlideOpen, showResults, isCandidateS )}
diff --git a/src/pages/Vote/Vote.tsx b/src/pages/Vote/Vote.tsx index 55972b21..2329a5fa 100644 --- a/src/pages/Vote/Vote.tsx +++ b/src/pages/Vote/Vote.tsx @@ -16,6 +16,7 @@ import VoteHeader from '@/components/Vote/VoteHeader/VoteHeader'; import {isCandidateSelectingState} from '@/recoil/vote/alertModal'; import {isBottomSlideOpenState} from '@/recoil/vote/bottomSlide'; import {selectedCandidatesState} from '@/recoil/vote/candidateList'; +import {showResultsState} from '@/recoil/vote/showResults'; import {VoteInfo} from '@/types/vote'; @@ -26,7 +27,7 @@ const Vote = () => { const [isBTOpen, setIsBTOpen] = useRecoilState(isBottomSlideOpenState); const [isCandidateSelecting, setIsCandidateSelecting] = useRecoilState(isCandidateSelectingState); const setSelectedCandidates = useSetRecoilState(selectedCandidatesState); - const [showResults, setShowResults] = useState(false); + const [showResults, setShowResults] = useRecoilState(showResultsState); const [bottomSlideContent, setBottomSlideContent] = useState(null); const isZeroCandidates = voteInfo.candidates.length === 0; @@ -36,13 +37,11 @@ const Vote = () => { } const allCandidatesNotVoted = areAllCandidatesNotVoted(voteInfo); - // if (voteInfo.voteStatus === '결정완료') { - // setShowResults(true); - // } - useEffect(() => { + if (voteInfo.voteStatus === '결정완료') { + setShowResults(true); + } setIsCandidateSelecting(false); - setShowResults(false); setSelectedCandidates(new Set()); }, []); @@ -56,6 +55,7 @@ const Vote = () => { const handleShowResultsClick = () => { setShowResults(!showResults); + //api넣기 }; return ( diff --git a/src/recoil/vote/showResults.ts b/src/recoil/vote/showResults.ts new file mode 100644 index 00000000..48ab0d5d --- /dev/null +++ b/src/recoil/vote/showResults.ts @@ -0,0 +1,6 @@ +import {atom} from 'recoil'; + +export const showResultsState = atom({ + key: 'showResultsState', + default: false, +}); diff --git a/src/types/vote.ts b/src/types/vote.ts index ab6aaaa9..d4b70410 100644 --- a/src/types/vote.ts +++ b/src/types/vote.ts @@ -86,7 +86,6 @@ export interface VoteHeaderProps { export interface CandidateCardProps { onBottomSlideOpen?: (content: ReactNode) => void | undefined; candidate: CandidatesInfo; - showResults: boolean; index: number; isMapStyle?: boolean; } From 8baac4732fd0b1f2af2a03d404311cefb91af000 Mon Sep 17 00:00:00 2001 From: SKY-PEY Date: Wed, 24 Jan 2024 18:37:42 +0900 Subject: [PATCH 07/14] Feat: connect api in VoteTabPanel --- src/api/vote.ts | 17 ++++----- .../CandidateCard/CandidateCard.tsx | 2 +- src/components/VoteTabPanel/VoteTabPanel.tsx | 37 ++++++++++++------- src/hooks/Votes/vote.ts | 7 +++- 4 files changed, 38 insertions(+), 25 deletions(-) diff --git a/src/api/vote.ts b/src/api/vote.ts index 6583339a..712a2048 100644 --- a/src/api/vote.ts +++ b/src/api/vote.ts @@ -6,20 +6,19 @@ import { PostNewCandidateProps, PostVoteTitleProps, VoteInfo, - VoteListInfo, } from '@/types/vote'; /* ----------------------------------- G E T ---------------------------------- */ //단일 보트 export const getVoteInfo = async (voteId: number): Promise => { - const response = await axios.get(`/api/votes/${voteId}`); + const response = await axios.get(`/api/votes/${voteId}`, {withCredentials: true}); return response.data; }; //보트 리스트 -export const getVoteListInfo = async (spaceId: number): Promise => { - const response = await axios.get(`/api/votes`, {params: {spaceId, voteStatusOption: 'ALL'}}); +export const getVoteListInfo = async (spaceId: number) => { + const response = await axios.get(`/api/votes`, {params: {spaceId, voteStatusOption: 'ALL', withCredentials: true}}); return response.data; }; @@ -30,7 +29,7 @@ export const getVoteListInfo = async (spaceId: number): Promise //vote 추가 export const postNewVote = async ({spaceId, title}: PostVoteTitleProps) => { try { - const response = await axios.post('/api/votes', {spaceId, title}); + const response = await axios.post('/api/votes', {spaceId, title, withCredentials: true}); console.log('axios 포스트 성공', response); return response; } catch (error) { @@ -40,7 +39,7 @@ export const postNewVote = async ({spaceId, title}: PostVoteTitleProps) => { //후보 메모 후 추가 export const postNewCandidate = async ({voteId, candidates}: PostNewCandidateProps) => { - const response = await axios.post(`/api/votes/${voteId}`, {params: candidates}); + const response = await axios.post(`/api/votes/${voteId}`, {params: {candidates, withCredentials: true}}); return response.data; }; @@ -49,7 +48,7 @@ export const postNewCandidate = async ({voteId, candidates}: PostNewCandidatePro //voteTitle 수정 PUT - api미정 export const editVoteTitle = async ({title, voteId}: EditVoteTitleProps) => { try { - const response = await axios.put(`/api/votes/${voteId}`, {params: title}); + const response = await axios.put(`/api/votes/${voteId}`, {params: {title, withCredentials: true}}); return response.data; } catch (error) { console.error(error); @@ -61,7 +60,7 @@ export const editVoteTitle = async ({title, voteId}: EditVoteTitleProps) => { //votes/{voteId} vote 삭제 export const deleteVote = async (voteId: number) => { try { - const response = await axios.delete(`/api/votes/${voteId}`); + const response = await axios.delete(`/api/votes/${voteId}`, {withCredentials: true}); return response.data; } catch (error) { console.error(error); @@ -72,7 +71,7 @@ export const deleteVote = async (voteId: number) => { //candidate 삭제- api 미정 / candidateId:number[] 여러아이디 배열에 담음 export const deleteCandidates = async ({voteId, candidateId}: DeleteCandidatesProps) => { try { - const response = await axios.delete(`/api/votes/${voteId}/candidates/${candidateId}`); + const response = await axios.delete(`/api/votes/${voteId}/candidates/${candidateId}`, {withCredentials: true}); return response.data; } catch (error) { console.error(error); diff --git a/src/components/Vote/VoteContent/CandidateCard/CandidateCard.tsx b/src/components/Vote/VoteContent/CandidateCard/CandidateCard.tsx index 5c14e683..5ba3faa2 100644 --- a/src/components/Vote/VoteContent/CandidateCard/CandidateCard.tsx +++ b/src/components/Vote/VoteContent/CandidateCard/CandidateCard.tsx @@ -84,7 +84,7 @@ const CandidateCard = ({onBottomSlideOpen, candidate, index, isMapStyle}: Candid // onClick={navigate로 넣기} disabled={isCandidateSelecting} > - {placeInfo.placeName.length >= 12 ? placeInfo.placeName.slice(0, 10) + ' ⋯' : placeInfo.placeName} + {placeInfo.placeName.length >= 12 ? placeInfo.placeName.slice(0, 12) + ' ⋯' : placeInfo.placeName}
diff --git a/src/components/VoteTabPanel/VoteTabPanel.tsx b/src/components/VoteTabPanel/VoteTabPanel.tsx index 577e5cdd..3b2248ff 100644 --- a/src/components/VoteTabPanel/VoteTabPanel.tsx +++ b/src/components/VoteTabPanel/VoteTabPanel.tsx @@ -15,13 +15,20 @@ import {VoteListInfo} from '@/types/vote'; const VoteTabPanel = () => { const {id: spaceId} = useParams(); - const {data: voteListData} = useGetVoteListInfo(Number(spaceId)); + const data = useGetVoteListInfo(Number(spaceId)); + const voteListAllData = data.data; + const voteListData: VoteListInfo[] | undefined = voteListAllData.voteResponse; + // const viewResultVoteIdsData = voteListAllData.viewResultVoteIds; const [activeTabIndex, setActiveTabIndex] = useState(0); - const inProgressVotes = voteListData.filter((vote) => vote.voteStatus === '진행 중'); - const completeVotes = voteListData.filter((vote) => vote.voteStatus === '결정완료'); + const inProgressVotes = voteListData?.filter((vote) => vote.voteStatus === '진행 중'); + const completeVotes = voteListData?.filter((vote) => vote.voteStatus === '결정완료'); - const getVotesCount = (vote: VoteListInfo[]) => `총 ${vote.length}개`; + const getVotesCount = (vote: VoteListInfo[] | undefined) => `총 ${vote ? vote.length : '0'}개`; + + // console.log('voteListData', data); + console.log('voteListData', voteListData); + console.log('voteListAllData', voteListAllData); return (
@@ -38,21 +45,25 @@ const VoteTabPanel = () => {
- {voteListData.length === 0 ? ( - - ) : ( + {voteListData ? ( voteListData.map((vote) => ) + ) : ( + )} - {inProgressVotes.map((vote) => ( - - ))} + {inProgressVotes ? ( + inProgressVotes?.map((vote) => ) + ) : ( + + )} - {completeVotes.map((vote) => ( - - ))} + {completeVotes ? ( + completeVotes?.map((vote) => ) + ) : ( + + )} diff --git a/src/hooks/Votes/vote.ts b/src/hooks/Votes/vote.ts index 3b671d2a..fb566d37 100644 --- a/src/hooks/Votes/vote.ts +++ b/src/hooks/Votes/vote.ts @@ -1,4 +1,4 @@ -import {useMutation, useQueryClient, useSuspenseQuery} from '@tanstack/react-query'; +import {useMutation, useQuery, useQueryClient, useSuspenseQuery} from '@tanstack/react-query'; import {deleteCandidates, deleteVote, editVoteTitle, getVoteInfo, getVoteListInfo, postNewVote} from '@/api/vote'; @@ -9,14 +9,16 @@ export const useGetVotesInfo = (voteId: number) => { return useSuspenseQuery({ queryKey: ['vote', voteId], queryFn: () => getVoteInfo(voteId), + retry: false, }); }; //보트 리스트 GET export const useGetVoteListInfo = (spaceId: number) => { - return useSuspenseQuery({ + return useQuery({ queryKey: ['votes', spaceId], queryFn: () => getVoteListInfo(spaceId), + retry: false, }); }; @@ -34,6 +36,7 @@ export const useCustomMutation = { console.error('Mutation error:', error); }, + retry: false, }); }; From 540cf10b6fd0429d7a7a207c500a37d671300426 Mon Sep 17 00:00:00 2001 From: SKY-PEY Date: Wed, 24 Jan 2024 21:10:38 +0900 Subject: [PATCH 08/14] Refactor: fix a type of useGetVoteListInfo in VoteTabPanel --- src/components/VoteTabPanel/VoteTabPanel.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/VoteTabPanel/VoteTabPanel.tsx b/src/components/VoteTabPanel/VoteTabPanel.tsx index 3b2248ff..fbf84591 100644 --- a/src/components/VoteTabPanel/VoteTabPanel.tsx +++ b/src/components/VoteTabPanel/VoteTabPanel.tsx @@ -17,8 +17,8 @@ const VoteTabPanel = () => { const {id: spaceId} = useParams(); const data = useGetVoteListInfo(Number(spaceId)); const voteListAllData = data.data; - const voteListData: VoteListInfo[] | undefined = voteListAllData.voteResponse; - // const viewResultVoteIdsData = voteListAllData.viewResultVoteIds; + const voteListData: VoteListInfo[] | undefined = voteListAllData?.voteResponse; + // const viewResultVoteIdsData = voteListAllData?.viewResultVoteIds; const [activeTabIndex, setActiveTabIndex] = useState(0); const inProgressVotes = voteListData?.filter((vote) => vote.voteStatus === '진행 중'); From d8a9c23dcd5d0e845f36e3020098307e1cb55895 Mon Sep 17 00:00:00 2001 From: SKY-PEY Date: Thu, 25 Jan 2024 02:26:19 +0900 Subject: [PATCH 09/14] Feat: connect apis post/votes, get/votes, get/votes/voteid --- src/api/vote.ts | 9 ++-- .../CandidateCard/CandidateCard.tsx | 2 +- src/components/VoteTabPanel/VoteTabPanel.tsx | 2 +- src/hooks/Votes/vote.ts | 12 +++-- src/pages/Vote/Vote.tsx | 45 +++++++++++++++---- 5 files changed, 50 insertions(+), 20 deletions(-) diff --git a/src/api/vote.ts b/src/api/vote.ts index 712a2048..be653cf3 100644 --- a/src/api/vote.ts +++ b/src/api/vote.ts @@ -5,13 +5,12 @@ import { EditVoteTitleProps, PostNewCandidateProps, PostVoteTitleProps, - VoteInfo, } from '@/types/vote'; /* ----------------------------------- G E T ---------------------------------- */ //단일 보트 -export const getVoteInfo = async (voteId: number): Promise => { +export const getVoteInfo = async (voteId: number) => { const response = await axios.get(`/api/votes/${voteId}`, {withCredentials: true}); return response.data; }; @@ -29,9 +28,9 @@ export const getVoteListInfo = async (spaceId: number) => { //vote 추가 export const postNewVote = async ({spaceId, title}: PostVoteTitleProps) => { try { - const response = await axios.post('/api/votes', {spaceId, title, withCredentials: true}); - console.log('axios 포스트 성공', response); - return response; + const response = await axios.post('/api/votes', {spaceId, title}); + console.log('axios 포스트 성공', response.data); + return response.data; } catch (error) { console.error(error); } diff --git a/src/components/Vote/VoteContent/CandidateCard/CandidateCard.tsx b/src/components/Vote/VoteContent/CandidateCard/CandidateCard.tsx index 5ba3faa2..177bb047 100644 --- a/src/components/Vote/VoteContent/CandidateCard/CandidateCard.tsx +++ b/src/components/Vote/VoteContent/CandidateCard/CandidateCard.tsx @@ -84,7 +84,7 @@ const CandidateCard = ({onBottomSlideOpen, candidate, index, isMapStyle}: Candid // onClick={navigate로 넣기} disabled={isCandidateSelecting} > - {placeInfo.placeName.length >= 12 ? placeInfo.placeName.slice(0, 12) + ' ⋯' : placeInfo.placeName} + {placeInfo.placeName.length >= 10 ? placeInfo.placeName.slice(0, 10) + ' ⋯' : placeInfo.placeName}
diff --git a/src/components/VoteTabPanel/VoteTabPanel.tsx b/src/components/VoteTabPanel/VoteTabPanel.tsx index fbf84591..8617c2a6 100644 --- a/src/components/VoteTabPanel/VoteTabPanel.tsx +++ b/src/components/VoteTabPanel/VoteTabPanel.tsx @@ -17,7 +17,7 @@ const VoteTabPanel = () => { const {id: spaceId} = useParams(); const data = useGetVoteListInfo(Number(spaceId)); const voteListAllData = data.data; - const voteListData: VoteListInfo[] | undefined = voteListAllData?.voteResponse; + const voteListData: VoteListInfo[] = voteListAllData?.data?.voteResponse; // const viewResultVoteIdsData = voteListAllData?.viewResultVoteIds; const [activeTabIndex, setActiveTabIndex] = useState(0); diff --git a/src/hooks/Votes/vote.ts b/src/hooks/Votes/vote.ts index fb566d37..e09a6b34 100644 --- a/src/hooks/Votes/vote.ts +++ b/src/hooks/Votes/vote.ts @@ -42,20 +42,24 @@ export const useCustomMutation = { - return useCustomMutation(postNewVote, ['votes']); + const queryClient = useQueryClient(); + return useMutation({ + mutationFn: postNewVote, + onSuccess: () => queryClient.invalidateQueries({queryKey: ['votes']}), + }); }; -//voteTitle 수정 PUT +// //voteTitle 수정 PUT export const useEditVoteTitle = () => { return useCustomMutation(editVoteTitle, ['vote']); }; -//vote 삭제 DELETE -> 쿼리 무효화 필요없는지 확인하기 +// //vote 삭제 DELETE -> 쿼리 무효화 필요없는지 확인하기 export const useDeleteVote = () => { return useCustomMutation(deleteVote, ['votes']); }; -//candidate 삭제- api 미정 +// //candidate 삭제- api 미정 export const useDeleteCandidates = () => { return useCustomMutation(deleteCandidates, ['votes']); }; diff --git a/src/pages/Vote/Vote.tsx b/src/pages/Vote/Vote.tsx index 2329a5fa..9fd279d4 100644 --- a/src/pages/Vote/Vote.tsx +++ b/src/pages/Vote/Vote.tsx @@ -22,7 +22,10 @@ import {VoteInfo} from '@/types/vote'; const Vote = () => { const {id: voteId} = useParams(); - const {data: voteInfo} = useGetVotesInfo(Number(voteId)); + const data = useGetVotesInfo(Number(voteId)); + const voteInfo = data.data?.data; + + console.log('voteInfo', voteInfo); const [isBTOpen, setIsBTOpen] = useRecoilState(isBottomSlideOpenState); const [isCandidateSelecting, setIsCandidateSelecting] = useRecoilState(isCandidateSelectingState); @@ -37,6 +40,8 @@ const Vote = () => { } const allCandidatesNotVoted = areAllCandidatesNotVoted(voteInfo); + // console.log() + useEffect(() => { if (voteInfo.voteStatus === '결정완료') { setShowResults(true); @@ -54,8 +59,25 @@ const Vote = () => { }; const handleShowResultsClick = () => { - setShowResults(!showResults); - //api넣기 + // if (isZeroCandidates) { + // return '후보 추가하기'; 후보 추가 연결 + // } else if (showResults) { + // return '다시 투표하기'; //리셋 mutate + // } else { + // return '결과보기'; //결과보기 api연결 + // } + // setShowResults(!showResults); + console.log('showResults', showResults); + }; + + const getButtonStatus = () => { + if (isZeroCandidates) { + return '후보 추가하기'; + } else if (showResults) { + return '다시 투표하기'; + } else { + return '결과보기'; + } }; return ( @@ -75,19 +97,24 @@ const Vote = () => { } /> - {voteInfo.candidates ? ( + {isZeroCandidates ? ( + + ) : ( - ) : ( - )} - {!isCandidateSelecting && voteInfo.voteStatus === '진행 중' && ( - )} setIsBTOpen(false)} children={bottomSlideContent} /> From 6f0d2142565b2db2660607a61f7b01530f73ae08 Mon Sep 17 00:00:00 2001 From: SKY-PEY Date: Thu, 25 Jan 2024 03:58:05 +0900 Subject: [PATCH 10/14] Feat: connect react-query to most vote's api --- src/api/vote.ts | 57 ++++++++++++++----- .../DeleteCandidatesButton.tsx | 2 +- .../VoteMeatball/VoteMeatball.tsx | 24 ++++++-- src/hooks/Votes/vote.ts | 50 +++++++++++++--- src/types/vote.ts | 12 +++- 5 files changed, 117 insertions(+), 28 deletions(-) diff --git a/src/api/vote.ts b/src/api/vote.ts index be653cf3..fa708b69 100644 --- a/src/api/vote.ts +++ b/src/api/vote.ts @@ -5,6 +5,7 @@ import { EditVoteTitleProps, PostNewCandidateProps, PostVoteTitleProps, + PostVotingProps, } from '@/types/vote'; /* ----------------------------------- G E T ---------------------------------- */ @@ -21,7 +22,11 @@ export const getVoteListInfo = async (spaceId: number) => { return response.data; }; -//getVotesResults +//투표 결과 조회 +export const getVoteResults = async (voteId: number) => { + const response = await axios.get(`/api/votes/${voteId}/result`, {withCredentials: true}); + return response.data; +}; /* ----------------------------------- P O S T ---------------------------------- */ @@ -36,9 +41,19 @@ export const postNewVote = async ({spaceId, title}: PostVoteTitleProps) => { } }; +//투표하기&취소 +export const postVoting = async ({voteId, candidateId}: PostVotingProps) => { + try { + const response = await axios.post('/api/votes/voting', {voteId, candidateId}); + return response.data; + } catch (error) { + console.error(error); + } +}; + //후보 메모 후 추가 -export const postNewCandidate = async ({voteId, candidates}: PostNewCandidateProps) => { - const response = await axios.post(`/api/votes/${voteId}`, {params: {candidates, withCredentials: true}}); +export const postNewCandidate = async ({voteId, candidateInfos}: PostNewCandidateProps) => { + const response = await axios.post(`/api/votes/${voteId}/candidates`, {params: {candidateInfos}}); return response.data; }; @@ -54,31 +69,47 @@ export const editVoteTitle = async ({title, voteId}: EditVoteTitleProps) => { } }; +//투표 상태 결과보기로 변경 +export const changeStatusComplete = async (voteId: number) => { + try { + const response = await axios.put(`/api/votes/${voteId}/voteStatus`); + return response.data; + } catch (error) { + console.error(error); + } +}; + +//재투표, 리셋 +export const resetVoteStatus = async (voteId: number) => { + try { + const response = await axios.put(`/api/votes/${voteId}`); + return response.data; + } catch (error) { + console.error(error); + } +}; + /* ----------------------------------- D E L E T E ---------------------------------- */ //votes/{voteId} vote 삭제 export const deleteVote = async (voteId: number) => { try { - const response = await axios.delete(`/api/votes/${voteId}`, {withCredentials: true}); + const response = await axios.delete(`/api/votes/${voteId}/voteStatus`, {withCredentials: true}); + console.log('투표삭제', response.data); return response.data; } catch (error) { console.error(error); } }; -//msw 돌려야함 //candidate 삭제- api 미정 / candidateId:number[] 여러아이디 배열에 담음 -export const deleteCandidates = async ({voteId, candidateId}: DeleteCandidatesProps) => { +export const deleteCandidates = async ({voteId, candidateIds}: DeleteCandidatesProps) => { try { - const response = await axios.delete(`/api/votes/${voteId}/candidates/${candidateId}`, {withCredentials: true}); + const response = await axios.delete(`/api/votes/${voteId}/candidates`, { + params: {candidateIds, withCredentials: true}, + }); return response.data; } catch (error) { console.error(error); } }; - -///votes/{voteId}/candidates candidate메모와 함께 추가 POST - -//votes/{voteId}/candidates/{candidatesId} 별 투표하기 POST -> + DELETE 투표 삭제? - -//PUT 투표 상태 변경(재진행) -> ? diff --git a/src/components/Vote/DeleteCandidatesButton/DeleteCandidatesButton.tsx b/src/components/Vote/DeleteCandidatesButton/DeleteCandidatesButton.tsx index 5dc2f9e9..086e3bb7 100644 --- a/src/components/Vote/DeleteCandidatesButton/DeleteCandidatesButton.tsx +++ b/src/components/Vote/DeleteCandidatesButton/DeleteCandidatesButton.tsx @@ -24,7 +24,7 @@ const DeleteCandidatesButton = () => { const deleteCandidateMutation = useDeleteCandidates(); const deleteCandidate = () => { - deleteCandidateMutation.mutate({voteId: Number(voteId), candidateId: [...selectedCandidates]}); + deleteCandidateMutation.mutate({voteId: Number(voteId), candidateIds: [...selectedCandidates]}); setSelectedCandidates(new Set()); }; diff --git a/src/components/Vote/VoteBottomSlideContent/VoteMeatball/VoteMeatball.tsx b/src/components/Vote/VoteBottomSlideContent/VoteMeatball/VoteMeatball.tsx index d1d0ea4a..ceead01a 100644 --- a/src/components/Vote/VoteBottomSlideContent/VoteMeatball/VoteMeatball.tsx +++ b/src/components/Vote/VoteBottomSlideContent/VoteMeatball/VoteMeatball.tsx @@ -4,7 +4,7 @@ import {useRecoilState, useSetRecoilState} from 'recoil'; import styles from './VoteMeatball.module.scss'; -import {useDeleteVote} from '@/hooks/Votes/vote'; +import {useChangeStatusComplete, useDeleteVote, useResetVoteStatus} from '@/hooks/Votes/vote'; import AlertModal from '@/components/AlertModal/AlertModal'; @@ -30,6 +30,8 @@ const VoteMeatball = ({state, title, isZeroCandidates, allCandidatesNotVoted}: V const setIsCandidateSelecting = useSetRecoilState(isCandidateSelectingState); const deleteVoteMutation = useDeleteVote(); + const changeCompleteMutation = useChangeStatusComplete(); + const resetStatusMutation = useResetVoteStatus(); const modalConsole = () => { console.log('변경'); @@ -51,15 +53,25 @@ const VoteMeatball = ({state, title, isZeroCandidates, allCandidatesNotVoted}: V setIsCreateModalOpen(true); }; - const deleteVote = async () => { + const handleDeleteVote = async () => { const res = await deleteVoteMutation.mutateAsync(Number(voteId)); - console.log('delete 결과:', res); + console.log('delete 리액트쿼리:', res); + }; + + const handleChangeComplete = async () => { + const res = await changeCompleteMutation.mutateAsync(Number(voteId)); + console.log('결정완료 리액트쿼리:', res); + }; + + const handleResetStatus = async () => { + const res = await resetStatusMutation.mutateAsync(Number(voteId)); + console.log('재진행 리액트쿼리:', res); }; return (
{state === '결정완료' ? ( - @@ -68,7 +80,7 @@ const VoteMeatball = ({state, title, isZeroCandidates, allCandidatesNotVoted}: V disabled={isZeroCandidates || allCandidatesNotVoted} onClick={() => showAlertModal({ - onClickAction: modalConsole, + onClickAction: handleChangeComplete, ...confirmVoteContent, }) } @@ -88,7 +100,7 @@ const VoteMeatball = ({state, title, isZeroCandidates, allCandidatesNotVoted}: V

후보 삭제

- diff --git a/src/hooks/Votes/vote.ts b/src/hooks/Votes/vote.ts index e09a6b34..099f1c73 100644 --- a/src/hooks/Votes/vote.ts +++ b/src/hooks/Votes/vote.ts @@ -1,6 +1,18 @@ import {useMutation, useQuery, useQueryClient, useSuspenseQuery} from '@tanstack/react-query'; -import {deleteCandidates, deleteVote, editVoteTitle, getVoteInfo, getVoteListInfo, postNewVote} from '@/api/vote'; +import { + changeStatusComplete, + deleteCandidates, + deleteVote, + editVoteTitle, + getVoteInfo, + getVoteListInfo, + getVoteResults, + postNewCandidate, + postNewVote, + postVoting, + resetVoteStatus, +} from '@/api/vote'; /* ----------------------------------- Q U E R Y ---------------------------------- */ @@ -22,6 +34,14 @@ export const useGetVoteListInfo = (spaceId: number) => { }); }; +export const useGetVotesResults = (voteId: number) => { + return useSuspenseQuery({ + queryKey: ['votes', voteId], + queryFn: () => getVoteResults(voteId), + retry: false, + }); +}; + /* ----------------------------------- M U T A T I O N ---------------------------------- */ //커스텀 mutation @@ -42,11 +62,17 @@ export const useCustomMutation = { - const queryClient = useQueryClient(); - return useMutation({ - mutationFn: postNewVote, - onSuccess: () => queryClient.invalidateQueries({queryKey: ['votes']}), - }); + return useCustomMutation(postNewVote, ['votes']); +}; + +//투표하기&취소 POST +export const usePostVoting = () => { + return useCustomMutation(postVoting, ['vote', 'candidates']); //vote? +}; + +//후보 메모 후 추가 POST +export const usePostNewCandidate = () => { + return useMutation({mutationFn: postNewCandidate}); //onSuccess? }; // //voteTitle 수정 PUT @@ -54,9 +80,19 @@ export const useEditVoteTitle = () => { return useCustomMutation(editVoteTitle, ['vote']); }; +//투표 상태 결과보기로 변경 PUT +export const useChangeStatusComplete = () => { + return useCustomMutation(changeStatusComplete, ['vote']); +}; + +//재투표, 리셋 +export const useResetVoteStatus = () => { + return useCustomMutation(resetVoteStatus, ['vote']); +}; + // //vote 삭제 DELETE -> 쿼리 무효화 필요없는지 확인하기 export const useDeleteVote = () => { - return useCustomMutation(deleteVote, ['votes']); + return useMutation({mutationFn: deleteVote}); }; // //candidate 삭제- api 미정 diff --git a/src/types/vote.ts b/src/types/vote.ts index d4b70410..b80393bf 100644 --- a/src/types/vote.ts +++ b/src/types/vote.ts @@ -144,7 +144,7 @@ export interface EditVoteTitleProps { } export interface DeleteCandidatesProps { voteId: number; - candidateId: number[]; + candidateIds: number[]; } export interface TaglineType { @@ -156,3 +156,13 @@ export interface MemoItemProps { candidate: CandidatesInfo; existingTagline?: TaglineType; } + +export interface PostVotingProps { + voteId: number; + candidateId: number; +} + +export interface PostNewCandidateProps { + voteId: number; + candidateInfos: TaglineType[]; +} From dbdaa7d8c333f99aef89e5f5f3e0f1f4e5ecee7f Mon Sep 17 00:00:00 2001 From: SKY-PEY Date: Thu, 25 Jan 2024 17:23:50 +0900 Subject: [PATCH 11/14] Conf: set initial code in votememo --- src/main.tsx | 1 + src/pages/Vote/VoteMemo/VoteMemo.tsx | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/main.tsx b/src/main.tsx index 1a091569..2382b9ce 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -7,6 +7,7 @@ import App from './App.tsx'; import {customTheme} from './chakra/chakraCustomTheme.ts'; async function enableMocking() { + return; if (import.meta.env.MODE !== 'development') { return; } diff --git a/src/pages/Vote/VoteMemo/VoteMemo.tsx b/src/pages/Vote/VoteMemo/VoteMemo.tsx index 49339ae8..480e5ab0 100644 --- a/src/pages/Vote/VoteMemo/VoteMemo.tsx +++ b/src/pages/Vote/VoteMemo/VoteMemo.tsx @@ -17,6 +17,7 @@ import {isBottomSlideOpenState} from '@/recoil/vote/bottomSlide'; import {selectedTaglineState} from '@/recoil/vote/voteMemo'; import {TaglineType} from '@/types/vote'; +// import { selectedPlaceState } from '@/recoil/vote/selectPlace'; const VoteMemo = () => { const {id: voteId} = useParams(); @@ -24,6 +25,7 @@ const VoteMemo = () => { // const navigate = useNavigate(); const [isBTOpen, setIsBTOpen] = useRecoilState(isBottomSlideOpenState); const [selectedTagline, setSelectedTagline] = useRecoilState(selectedTaglineState); + // const [selectedPlaces,SetSelectedPlaces] = useRecoilState(selectedPlaceState); const {toggleItemInNewArray} = useGetSelectedArray(selectedTaglineState); const getExistingTaglines = localStorage.getItem('recoil-persist'); From ace95ab8dfec416d2393ecd3ba85cc7ae30dff63 Mon Sep 17 00:00:00 2001 From: SKY-PEY Date: Thu, 25 Jan 2024 18:40:11 +0900 Subject: [PATCH 12/14] Fix: edit the type of votememo --- .../SelectButton/SelectButton.tsx | 12 +----------- .../VoteMeatball/VoteMeatball.tsx | 4 ---- .../VoteContent/CandidateList/CandidateList.tsx | 2 +- src/components/Vote/VoteContent/VoteContent.tsx | 1 - src/components/VoteMemo/MemoContent.tsx | 2 +- src/hooks/useGetSelectedArray.ts | 9 +++++---- src/pages/Vote/Vote.tsx | 4 +++- src/pages/Vote/VoteMemo/VoteMemo.tsx | 16 +++++++++------- src/recoil/vote/selectPlace.ts | 4 ++-- src/types/vote.ts | 4 ++-- 10 files changed, 24 insertions(+), 34 deletions(-) diff --git a/src/components/ButtonsInAddingCandidate/SelectButton/SelectButton.tsx b/src/components/ButtonsInAddingCandidate/SelectButton/SelectButton.tsx index 5781c42c..30afed22 100644 --- a/src/components/ButtonsInAddingCandidate/SelectButton/SelectButton.tsx +++ b/src/components/ButtonsInAddingCandidate/SelectButton/SelectButton.tsx @@ -9,16 +9,6 @@ import {selectedPlaceState} from '@/recoil/vote/selectPlace'; import {SearchItemType} from '@/types/home'; -// //"선택된 장소 객체" -const placeInfo = { - placeId: 23, - placeName: '안녕호텔', - category: '호텔', - location: '서울', - placeImageURL: 'https://img-cf.kurly.com/shop/data/goodsview/20210218/gv30000159355_1.jpg', - latlng: {lat: 33.450936, lng: 126.569477}, -}; - interface Propstype { data: SearchItemType; } @@ -32,7 +22,7 @@ const SelectButton = ({data}: Propstype) => { const handleClick = (e: React.MouseEvent) => { e.preventDefault(); setIsClicked((prev) => !prev); - toggleItemInNewArray(placeInfo); + toggleItemInNewArray(data); console.log(data); }; diff --git a/src/components/Vote/VoteBottomSlideContent/VoteMeatball/VoteMeatball.tsx b/src/components/Vote/VoteBottomSlideContent/VoteMeatball/VoteMeatball.tsx index ceead01a..59a43d82 100644 --- a/src/components/Vote/VoteBottomSlideContent/VoteMeatball/VoteMeatball.tsx +++ b/src/components/Vote/VoteBottomSlideContent/VoteMeatball/VoteMeatball.tsx @@ -33,10 +33,6 @@ const VoteMeatball = ({state, title, isZeroCandidates, allCandidatesNotVoted}: V const changeCompleteMutation = useChangeStatusComplete(); const resetStatusMutation = useResetVoteStatus(); - const modalConsole = () => { - console.log('변경'); - }; - const showAlertModal = ({...content}: AlertModalProps) => { setIsBTOpen(false); setIsModalOpen(true); diff --git a/src/components/Vote/VoteContent/CandidateList/CandidateList.tsx b/src/components/Vote/VoteContent/CandidateList/CandidateList.tsx index bcf57d2b..15f6be74 100644 --- a/src/components/Vote/VoteContent/CandidateList/CandidateList.tsx +++ b/src/components/Vote/VoteContent/CandidateList/CandidateList.tsx @@ -12,7 +12,7 @@ import VoteContentEmpty from '../VoteContentEmpty/VoteContentEmpty'; import {CandidateListProps} from '@/types/vote'; -const CandidateList = ({candidates, onBottomSlideOpen, showResults, isCandidateSelecting}: CandidateListProps) => { +const CandidateList = ({candidates, onBottomSlideOpen, isCandidateSelecting}: CandidateListProps) => { const setSelectedCandidates = useSetRecoilState(selectedCandidatesState); const {addItemInNewSet} = useGetSelectedSet(setSelectedCandidates); diff --git a/src/components/Vote/VoteContent/VoteContent.tsx b/src/components/Vote/VoteContent/VoteContent.tsx index 4059ae90..0247d574 100644 --- a/src/components/Vote/VoteContent/VoteContent.tsx +++ b/src/components/Vote/VoteContent/VoteContent.tsx @@ -46,7 +46,6 @@ const VoteContent = ({onBottomSlideOpen, data, isZeroCandidates, showResults}: V diff --git a/src/components/VoteMemo/MemoContent.tsx b/src/components/VoteMemo/MemoContent.tsx index bd9c68cf..7680cb79 100644 --- a/src/components/VoteMemo/MemoContent.tsx +++ b/src/components/VoteMemo/MemoContent.tsx @@ -16,7 +16,7 @@ const MemoContent = ({data}: {data: VoteInfo}) => { tagline.placeId === candidate.placeInfo.placeId)} + existingTagline={existingTaglines?.find((tagline) => tagline.id === candidate.placeInfo.placeId)} /> ))}
diff --git a/src/hooks/useGetSelectedArray.ts b/src/hooks/useGetSelectedArray.ts index 76207ac3..37dce6f9 100644 --- a/src/hooks/useGetSelectedArray.ts +++ b/src/hooks/useGetSelectedArray.ts @@ -1,13 +1,14 @@ import {RecoilState, useSetRecoilState} from 'recoil'; -import {PlaceInfo, TaglineType} from '@/types/vote'; +import {SearchItemType} from '@/types/home'; +import {TaglineType} from '@/types/vote'; -const useGetSelectedArray = (selectedState: RecoilState) => { +const useGetSelectedArray = (selectedState: RecoilState) => { const setSelectedState = useSetRecoilState(selectedState); const toggleItemInNewArray = (data: T) => { setSelectedState((currentArray) => { - const index = currentArray.findIndex((item) => item.placeId === data.placeId); + const index = currentArray.findIndex((item) => item.id === data.id); if (index !== -1) { const newArray = [...currentArray.slice(0, index), ...currentArray.slice(index + 1)]; @@ -23,7 +24,7 @@ const useGetSelectedArray = (selectedState: R const setMemoArray = (data: T) => { setSelectedState((currentArray: T[]) => { - const index = currentArray.findIndex((item) => item.placeId === data.placeId); + const index = currentArray.findIndex((item) => item.id === data.id); if (index !== -1) { const newArray = [...currentArray]; newArray[index] = data; diff --git a/src/pages/Vote/Vote.tsx b/src/pages/Vote/Vote.tsx index 9fd279d4..fc2ed8f3 100644 --- a/src/pages/Vote/Vote.tsx +++ b/src/pages/Vote/Vote.tsx @@ -8,6 +8,7 @@ import styles from './Vote.module.scss'; import {useGetVotesInfo} from '@/hooks/Votes/vote'; import BottomSlide from '@/components/BottomSlide/BottomSlide'; +import AddCandidate from '@/components/Vote/VoteBottomSlideContent/AddCandidate/AddCandidate'; import VoteMeatball from '@/components/Vote/VoteBottomSlideContent/VoteMeatball/VoteMeatball'; import VoteContent from '@/components/Vote/VoteContent/VoteContent'; import VoteContentEmpty from '@/components/Vote/VoteContent/VoteContentEmpty/VoteContentEmpty'; @@ -59,6 +60,7 @@ const Vote = () => { }; const handleShowResultsClick = () => { + BottomSlideOpen(); // if (isZeroCandidates) { // return '후보 추가하기'; 후보 추가 연결 // } else if (showResults) { @@ -67,7 +69,7 @@ const Vote = () => { // return '결과보기'; //결과보기 api연결 // } // setShowResults(!showResults); - console.log('showResults', showResults); + // console.log('showResults', showResults); }; const getButtonStatus = () => { diff --git a/src/pages/Vote/VoteMemo/VoteMemo.tsx b/src/pages/Vote/VoteMemo/VoteMemo.tsx index 480e5ab0..0eb892c4 100644 --- a/src/pages/Vote/VoteMemo/VoteMemo.tsx +++ b/src/pages/Vote/VoteMemo/VoteMemo.tsx @@ -1,7 +1,7 @@ import {Button} from '@chakra-ui/react'; import {useEffect} from 'react'; import {useParams} from 'react-router-dom'; -import {useRecoilState} from 'recoil'; +import {useRecoilState, useRecoilValue} from 'recoil'; import styles from './VoteMemo.module.scss'; @@ -14,6 +14,7 @@ import VoteHeader from '@/components/Vote/VoteHeader/VoteHeader'; import MemoContent from '@/components/VoteMemo/MemoContent'; import {isBottomSlideOpenState} from '@/recoil/vote/bottomSlide'; +import {selectedPlaceState} from '@/recoil/vote/selectPlace'; import {selectedTaglineState} from '@/recoil/vote/voteMemo'; import {TaglineType} from '@/types/vote'; @@ -25,23 +26,24 @@ const VoteMemo = () => { // const navigate = useNavigate(); const [isBTOpen, setIsBTOpen] = useRecoilState(isBottomSlideOpenState); const [selectedTagline, setSelectedTagline] = useRecoilState(selectedTaglineState); - // const [selectedPlaces,SetSelectedPlaces] = useRecoilState(selectedPlaceState); + // const [selectedPlaces, SetSelectedPlaces] = useRecoilState(selectedPlaceState); + const selectedPlaces = useRecoilValue(selectedPlaceState); const {toggleItemInNewArray} = useGetSelectedArray(selectedTaglineState); const getExistingTaglines = localStorage.getItem('recoil-persist'); const setInitializeTagline = () => { - setSelectedTagline(voteInfo.candidates.map(({placeInfo}) => ({placeId: placeInfo.placeId, tagline: ''}))); + setSelectedTagline(selectedPlaces?.map((place) => ({id: place.id, tagline: ''}))); }; const setExistingTagline = () => { const existingTaglines: TaglineType[] = getExistingTaglines && JSON.parse(getExistingTaglines).selectedTaglineState; - const nonExistPlaceIds = voteInfo.candidates - .map(({placeInfo}) => placeInfo.placeId) - .filter((placeId) => !existingTaglines.some((tagline) => tagline.placeId === placeId)); + const nonExistPlaceIds = selectedPlaces + .map((place) => place.id) + .filter((id) => !existingTaglines.some((tagline) => tagline.id === id)); - nonExistPlaceIds.map((placeId) => ({placeId, tagline: ''})).forEach((tagline) => toggleItemInNewArray(tagline)); + nonExistPlaceIds.map((id) => ({id, tagline: ''})).forEach((tagline) => toggleItemInNewArray(tagline)); }; useEffect(() => { diff --git a/src/recoil/vote/selectPlace.ts b/src/recoil/vote/selectPlace.ts index e000fb02..fe298dd3 100644 --- a/src/recoil/vote/selectPlace.ts +++ b/src/recoil/vote/selectPlace.ts @@ -1,8 +1,8 @@ import {atom} from 'recoil'; -import {PlaceInfo} from '@/types/vote'; +import {SearchItemType} from '@/types/home'; -export const selectedPlaceState = atom({ +export const selectedPlaceState = atom({ key: 'selectedPlaceState', default: [], }); diff --git a/src/types/vote.ts b/src/types/vote.ts index b80393bf..9c57ea0e 100644 --- a/src/types/vote.ts +++ b/src/types/vote.ts @@ -109,7 +109,7 @@ export interface AlertModalProps { export interface CandidateListProps { candidates: CandidatesInfo[]; onBottomSlideOpen: (content: ReactNode) => void; - showResults: boolean; + isCandidateSelecting: boolean; } @@ -148,7 +148,7 @@ export interface DeleteCandidatesProps { } export interface TaglineType { - placeId: number; + id: number; tagline: string; } From 46b705481969895acded25f97dd38a139ff201f6 Mon Sep 17 00:00:00 2001 From: SKY-PEY Date: Thu, 25 Jan 2024 18:53:50 +0900 Subject: [PATCH 13/14] Fix: edit type of selectedPlaces --- src/components/VoteMemo/MemoContent.tsx | 15 ++++++------ src/components/VoteMemo/MemoItem/MemoItem.tsx | 24 ++++++++++--------- src/main.tsx | 4 +--- src/pages/Vote/VoteMemo/VoteMemo.tsx | 2 +- src/types/vote.ts | 4 +++- 5 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/components/VoteMemo/MemoContent.tsx b/src/components/VoteMemo/MemoContent.tsx index 7680cb79..67229a16 100644 --- a/src/components/VoteMemo/MemoContent.tsx +++ b/src/components/VoteMemo/MemoContent.tsx @@ -2,21 +2,20 @@ import styles from './MemoContent.module.scss'; import MemoItem from './MemoItem/MemoItem'; -import {TaglineType, VoteInfo} from '@/types/vote'; - -const MemoContent = ({data}: {data: VoteInfo}) => { - const candidates = data.candidates; +import {SearchItemType} from '@/types/home'; +import {TaglineType} from '@/types/vote'; +const MemoContent = ({selectedPlaces}: {selectedPlaces: SearchItemType[]}) => { const getExistingTaglines = localStorage.getItem('recoil-persist'); const existingTaglines: TaglineType[] = getExistingTaglines && JSON.parse(getExistingTaglines).selectedTaglineState; return (
- {candidates?.map((candidate) => ( + {selectedPlaces?.map((place) => ( tagline.id === candidate.placeInfo.placeId)} + place={place} + key={place.id} + existingTagline={existingTaglines?.find((tagline) => tagline.id === place.id)} /> ))}
diff --git a/src/components/VoteMemo/MemoItem/MemoItem.tsx b/src/components/VoteMemo/MemoItem/MemoItem.tsx index 1ce907ba..6ad981c0 100644 --- a/src/components/VoteMemo/MemoItem/MemoItem.tsx +++ b/src/components/VoteMemo/MemoItem/MemoItem.tsx @@ -1,21 +1,23 @@ import {Checkbox} from '@chakra-ui/react'; import {useCallback, useEffect, useState} from 'react'; +import {useRecoilValue} from 'recoil'; import styles from './MemoItem.module.scss'; import {useDebounce} from '@/hooks/useDebounce'; import useGetSelectedArray from '@/hooks/useGetSelectedArray'; +import {selectedPlaceState} from '@/recoil/vote/selectPlace'; import {selectedTaglineState} from '@/recoil/vote/voteMemo'; import {MemoItemProps} from '@/types/vote'; -const MemoItem = ({candidate, existingTagline}: MemoItemProps) => { +const MemoItem = ({place, existingTagline}: MemoItemProps) => { const [text, setText] = useState(''); // const [selectedTagline, setSelectedTagline] = useRecoilState(selectedTaglineState); const {toggleItemInNewArray, setMemoArray} = useGetSelectedArray(selectedTaglineState); const debouncedText = useDebounce(text, 500); - const placeInfo = candidate.placeInfo; + const selectedPlaces = useRecoilValue(selectedPlaceState); useEffect(() => { if (existingTagline) { @@ -25,17 +27,17 @@ const MemoItem = ({candidate, existingTagline}: MemoItemProps) => { const handleCheckboxChange = () => { toggleItemInNewArray({ - placeId: placeInfo.placeId, + id: place.id, tagline: debouncedText, }); }; const handleDebouncedTextChange = useCallback(() => { setMemoArray({ - placeId: placeInfo.placeId, + id: place.id, tagline: debouncedText, }); - }, [debouncedText, placeInfo.placeId, setMemoArray]); + }, [debouncedText, place.id, setMemoArray]); useEffect(() => { handleDebouncedTextChange(); @@ -45,23 +47,23 @@ const MemoItem = ({candidate, existingTagline}: MemoItemProps) => {
-