diff --git a/src/apis/idolApi.js b/src/apis/idolApi.js new file mode 100644 index 0000000..7d8a1ae --- /dev/null +++ b/src/apis/idolApi.js @@ -0,0 +1,13 @@ +import axios from 'axios'; + +export const fetchIdols = async (pageSize = 30) => { + try { + const response = await axios.get( + `https://fandom-k-api.vercel.app/13-3/idols?pageSize=${pageSize}` + ); + return response.data.list; + } catch (error) { + console.error('아이돌 데이터를 불러오는 중 오류 발생:', error); + return []; + } +}; diff --git a/src/assets/icons/xButton.svg b/src/assets/icons/xButton.svg new file mode 100644 index 0000000..13058a2 --- /dev/null +++ b/src/assets/icons/xButton.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/components/IdolCard.jsx b/src/components/IdolCard.jsx index 4b4c700..3c6a24f 100644 --- a/src/components/IdolCard.jsx +++ b/src/components/IdolCard.jsx @@ -8,7 +8,7 @@ const IdolCard = ({ idol }) => { console.log('IdolCard 받은 데이터:', idol); return ( -
+
setIsSelected(!isSelected)} diff --git a/src/components/IdolImage.jsx b/src/components/IdolImage.jsx index d2c99bb..5df8c75 100644 --- a/src/components/IdolImage.jsx +++ b/src/components/IdolImage.jsx @@ -1,11 +1,10 @@ -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect } from 'react'; -const ImageWithBorder = ({ borderColor = "#f96868", size = "128px" }) => { - const [imageSrc, setImageSrc] = useState(""); +const ImageWithBorder = ({ borderColor = '#f96868', size = '128px' }) => { + const [imageSrc, setImageSrc] = useState(''); useEffect(() => { - - setImageSrc("https://via.placeholder.com/150"); + setImageSrc('https://via.placeholder.com/150'); }, []); if (!imageSrc) { @@ -27,12 +26,13 @@ const ImageWithBorder = ({ borderColor = "#f96868", size = "128px" }) => { }} >
{ const [idols, setIdols] = useState([]); + const [selectedIdols, setSelectedIdols] = useState([]); + const [favoriteIdols, setFavoriteIdols] = useState([]); + const [currentPage, setCurrentPage] = useState(0); + const [isClicked, setIsClicked] = useState(false); + + const getItemsPerPage = () => { + if (typeof window !== 'undefined') { + if (window.innerWidth < 640) return 6; + if (window.innerWidth < 768) return 8; + return 16; + } + return 16; + }; useEffect(() => { - const fetchIdols = async () => { - try { - const response = await axios.get( - 'https://fandom-k-api.vercel.app/13-3/idols?pageSize=30' - ); - setIdols(response.data.list); // API 응답 데이터 리스트를 저장 - } catch (error) { - console.error('아이돌 데이터를 불러오는 중 오류 발생:', error); //아이돌 데이터 로딩 중 에러 확인 - } + const loadIdols = async () => { + const data = await fetchIdols(30); + setIdols(data); }; + loadIdols(); + }, []); - fetchIdols(); + useEffect(() => { + const storedFavorites = localStorage.getItem(storageKey); + if (storedFavorites) { + setFavoriteIdols(storedFavorites.split(',')); + } }, []); + useEffect(() => { + localStorage.setItem(storageKey, favoriteIdols.join(',')); + }, [favoriteIdols]); + + const handleToggle = (idolId) => { + setSelectedIdols((prev) => + prev.includes(idolId) + ? prev.filter((id) => id !== idolId) + : [...prev, idolId] + ); + setIsClicked(true); + }; + + const handleAddFavorites = () => { + if (!isClicked) return; + + setFavoriteIdols((prev) => [...prev, ...selectedIdols]); + setSelectedIdols([]); + setIsClicked(false); + }; + + const handleRemoveFavorite = (idolId) => { + setFavoriteIdols((prev) => prev.filter((id) => id !== idolId)); + }; + + const nextPage = () => { + const itemsPerPage = getItemsPerPage(); + if ((currentPage + 1) * itemsPerPage < idols.length) { + setCurrentPage((prev) => prev + 1); + } + }; + + const prevPage = () => { + if (currentPage > 0) { + setCurrentPage((prev) => prev - 1); + } + }; + return ( -
-
- {idols.length > 0 ? ( - idols.map((idol) => ) - ) : ( -

아이돌 데이터를 불러오는 중...

- )} +
+
+ +
+

+ 내가 관심있는 아이돌 +

+ +
+
+ {favoriteIdols.length > 0 ? ( + favoriteIdols.map((idolId) => { + const idol = idols.find((i) => i.id === idolId); + return idol ? ( +
+ +
+ ) : null; + }) + ) : ( +

+ 관심있는 아이돌을 추가해보세요. +

+ )} +
+
+ +
+ +

+ 관심 있는 아이돌을 추가해보세요. +

+ +
+ + + + +
+ {idols + .slice( + currentPage * getItemsPerPage(), + (currentPage + 1) * getItemsPerPage() + ) + .map((idol) => ( +
handleToggle(idol.id)} + > + +
+ ))} +
+
+ +
); diff --git a/vite.config.js b/vite.config.js index 15e5fec..dd4efa7 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,13 +1,21 @@ import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; -import path from "path"; +import path from 'path'; -// https://vite.dev/config/ export default defineConfig({ plugins: [react()], resolve: { alias: { - "@": path.resolve(__dirname, "src"), // 수정된 부분 + '@': path.resolve(__dirname, 'src'), }, }, -}); \ No newline at end of file + server: { + proxy: { + '/api': { + target: 'https://fandom-k-api.vercel.app', + changeOrigin: true, + secure: false, + }, + }, + }, +});