diff --git a/frontend/package-lock.json b/frontend/package-lock.json index fcd56ef..f53da44 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -18,7 +18,8 @@ "overlayscrollbars-react": "^0.5.6", "react": "^19.2.4", "react-dom": "^19.2.4", - "react-router-dom": "^7.14.0" + "react-router-dom": "^7.14.0", + "zustand": "^5.0.12" }, "devDependencies": { "@eslint/js": "^9.39.4", @@ -3139,6 +3140,35 @@ "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } + }, + "node_modules/zustand": { + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.12.tgz", + "integrity": "sha512-i77ae3aZq4dhMlRhJVCYgMLKuSiZAaUPAct2AksxQ+gOtimhGMdXljRT21P5BNpeT4kXlLIckvkPM029OljD7g==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } } } } diff --git a/frontend/package.json b/frontend/package.json index c6606a8..b6f5333 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -20,7 +20,8 @@ "overlayscrollbars-react": "^0.5.6", "react": "^19.2.4", "react-dom": "^19.2.4", - "react-router-dom": "^7.14.0" + "react-router-dom": "^7.14.0", + "zustand": "^5.0.12" }, "devDependencies": { "@eslint/js": "^9.39.4", diff --git a/frontend/src/features/symbol/Symbol.jsx b/frontend/src/features/symbol/Symbol.jsx index ff45795..f3d544e 100644 --- a/frontend/src/features/symbol/Symbol.jsx +++ b/frontend/src/features/symbol/Symbol.jsx @@ -3,7 +3,7 @@ import { useQuery, useMutation } from '@tanstack/react-query' import { api } from '../../api/client' import { useLayout } from '../../components/Layout' import Select from '../../components/Select' - +import { useSymbolStore } from './store' const TYPE_ORDER = ['아케인', '어센틱', '그랜드 어센틱'] @@ -57,12 +57,19 @@ function CharacterCard({ char, active, onSelect, onRemove }) { ) } -function SymbolCard({ symbol, equipped }) { - const [weeklyCount, setWeeklyCount] = useState(3) - const [dailyDone, setDailyDone] = useState(false) +function SymbolCard({ symbol, equipped, charId }) { + const progress = useSymbolStore((s) => s.progress?.[charId]?.[symbol.id]) + const updateSymbol = useSymbolStore((s) => s.updateSymbol) + + const dailyDone = progress?.dailyDone ?? false + const weeklyCount = progress?.weeklyCount ?? 3 + const daily = progress?.daily ?? symbol.daily_default + const extra = progress?.extra ?? 0 + const patch = (p) => charId && updateSymbol(charId, symbol.id, p) + // 임시 목업 값 (계산 기능 미구현) - const level = equipped ? 0 : 0 - const growth = 0 + const level = progress?.level ?? 0 + const growth = progress?.growth ?? 0 const requireGrowth = symbol.levels?.[0]?.required_count || 0 const remainingSymbols = '-' const remainingMeso = '-' @@ -96,7 +103,7 @@ function SymbolCard({ symbol, equipped }) {