diff --git a/package-lock.json b/package-lock.json index d32fbf2..c35a119 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,20 +8,27 @@ "name": "checkmo", "version": "0.1.0", "dependencies": { - "next": "16.0.1", + "@vercel/analytics": "^1.6.1", + "@vercel/speed-insights": "^1.3.1", + "js-cookie": "^3.0.5", + "next": "^16.1.6", "react": "19.2.0", - "react-dom": "19.2.0" + "react-dom": "19.2.0", + "react-hot-toast": "^2.6.0", + "zustand": "^5.0.10" }, "devDependencies": { "@tailwindcss/cli": "^4.1.17", "@tailwindcss/postcss": "^4", + "@types/js-cookie": "^3.0.6", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", "autoprefixer": "^10.4.21", "babel-plugin-react-compiler": "1.0.0", + "baseline-browser-mapping": "^2.9.19", "eslint": "^9", - "eslint-config-next": "16.0.1", + "eslint-config-next": "^16.1.6", "postcss": "^8.5.6", "tailwindcss": "^4", "typescript": "^5" @@ -1039,15 +1046,15 @@ } }, "node_modules/@next/env": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/@next/env/-/env-16.0.1.tgz", - "integrity": "sha512-LFvlK0TG2L3fEOX77OC35KowL8D7DlFF45C0OvKMC4hy8c/md1RC4UMNDlUGJqfCoCS2VWrZ4dSE6OjaX5+8mw==", + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.1.6.tgz", + "integrity": "sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.0.1.tgz", - "integrity": "sha512-g4Cqmv/gyFEXNeVB2HkqDlYKfy+YrlM2k8AVIO/YQVEPfhVruH1VA99uT1zELLnPLIeOnx8IZ6Ddso0asfTIdw==", + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.1.6.tgz", + "integrity": "sha512-/Qq3PTagA6+nYVfryAtQ7/9FEr/6YVyvOtl6rZnGsbReGLf0jZU6gkpr1FuChAQpvV46a78p4cmHOVP8mbfSMQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1055,9 +1062,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.0.1.tgz", - "integrity": "sha512-R0YxRp6/4W7yG1nKbfu41bp3d96a0EalonQXiMe+1H9GTHfKxGNCGFNWUho18avRBPsO8T3RmdWuzmfurlQPbg==", + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.1.6.tgz", + "integrity": "sha512-wTzYulosJr/6nFnqGW7FrG3jfUUlEf8UjGA0/pyypJl42ExdVgC6xJgcXQ+V8QFn6niSG2Pb8+MIG1mZr2vczw==", "cpu": [ "arm64" ], @@ -1071,9 +1078,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.0.1.tgz", - "integrity": "sha512-kETZBocRux3xITiZtOtVoVvXyQLB7VBxN7L6EPqgI5paZiUlnsgYv4q8diTNYeHmF9EiehydOBo20lTttCbHAg==", + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.1.6.tgz", + "integrity": "sha512-BLFPYPDO+MNJsiDWbeVzqvYd4NyuRrEYVB5k2N3JfWncuHAy2IVwMAOlVQDFjj+krkWzhY2apvmekMkfQR0CUQ==", "cpu": [ "x64" ], @@ -1087,9 +1094,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.0.1.tgz", - "integrity": "sha512-hWg3BtsxQuSKhfe0LunJoqxjO4NEpBmKkE+P2Sroos7yB//OOX3jD5ISP2wv8QdUwtRehMdwYz6VB50mY6hqAg==", + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.1.6.tgz", + "integrity": "sha512-OJYkCd5pj/QloBvoEcJ2XiMnlJkRv9idWA/j0ugSuA34gMT6f5b7vOiCQHVRpvStoZUknhl6/UxOXL4OwtdaBw==", "cpu": [ "arm64" ], @@ -1103,9 +1110,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.0.1.tgz", - "integrity": "sha512-UPnOvYg+fjAhP3b1iQStcYPWeBFRLrugEyK/lDKGk7kLNua8t5/DvDbAEFotfV1YfcOY6bru76qN9qnjLoyHCQ==", + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.1.6.tgz", + "integrity": "sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ==", "cpu": [ "arm64" ], @@ -1119,9 +1126,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.0.1.tgz", - "integrity": "sha512-Et81SdWkcRqAJziIgFtsFyJizHoWne4fzJkvjd6V4wEkWTB4MX6J0uByUb0peiJQ4WeAt6GGmMszE5KrXK6WKg==", + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.1.6.tgz", + "integrity": "sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ==", "cpu": [ "x64" ], @@ -1135,9 +1142,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.0.1.tgz", - "integrity": "sha512-qBbgYEBRrC1egcG03FZaVfVxrJm8wBl7vr8UFKplnxNRprctdP26xEv9nJ07Ggq4y1adwa0nz2mz83CELY7N6Q==", + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.1.6.tgz", + "integrity": "sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg==", "cpu": [ "x64" ], @@ -1151,9 +1158,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.0.1.tgz", - "integrity": "sha512-cPuBjYP6I699/RdbHJonb3BiRNEDm5CKEBuJ6SD8k3oLam2fDRMKAvmrli4QMDgT2ixyRJ0+DTkiODbIQhRkeQ==", + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.1.6.tgz", + "integrity": "sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw==", "cpu": [ "arm64" ], @@ -1167,9 +1174,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.0.1.tgz", - "integrity": "sha512-XeEUJsE4JYtfrXe/LaJn3z1pD19fK0Q6Er8Qoufi+HqvdO4LEPyCxLUt4rxA+4RfYo6S9gMlmzCMU2F+AatFqQ==", + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.1.6.tgz", + "integrity": "sha512-NRfO39AIrzBnixKbjuo2YiYhB6o9d8v/ymU9m/Xk8cyVk+k7XylniXkHwjs4s70wedVffc6bQNbufk5v0xEm0A==", "cpu": [ "x64" ], @@ -1863,6 +1870,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/js-cookie": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz", + "integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -1891,7 +1905,7 @@ "version": "19.2.7", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz", "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "csstype": "^3.2.2" @@ -2445,6 +2459,78 @@ "win32" ] }, + "node_modules/@vercel/analytics": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@vercel/analytics/-/analytics-1.6.1.tgz", + "integrity": "sha512-oH9He/bEM+6oKlv3chWuOOcp8Y6fo6/PSro8hEkgCW3pu9/OiCXiUpRUogDh3Fs3LH2sosDrx8CxeOLBEE+afg==", + "license": "MPL-2.0", + "peerDependencies": { + "@remix-run/react": "^2", + "@sveltejs/kit": "^1 || ^2", + "next": ">= 13", + "react": "^18 || ^19 || ^19.0.0-rc", + "svelte": ">= 4", + "vue": "^3", + "vue-router": "^4" + }, + "peerDependenciesMeta": { + "@remix-run/react": { + "optional": true + }, + "@sveltejs/kit": { + "optional": true + }, + "next": { + "optional": true + }, + "react": { + "optional": true + }, + "svelte": { + "optional": true + }, + "vue": { + "optional": true + }, + "vue-router": { + "optional": true + } + } + }, + "node_modules/@vercel/speed-insights": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@vercel/speed-insights/-/speed-insights-1.3.1.tgz", + "integrity": "sha512-PbEr7FrMkUrGYvlcLHGkXdCkxnylCWePx7lPxxq36DNdfo9mcUjLOmqOyPDHAOgnfqgGGdmE3XI9L/4+5fr+vQ==", + "license": "Apache-2.0", + "peerDependencies": { + "@sveltejs/kit": "^1 || ^2", + "next": ">= 13", + "react": "^18 || ^19 || ^19.0.0-rc", + "svelte": ">= 4", + "vue": "^3", + "vue-router": "^4" + }, + "peerDependenciesMeta": { + "@sveltejs/kit": { + "optional": true + }, + "next": { + "optional": true + }, + "react": { + "optional": true + }, + "svelte": { + "optional": true + }, + "vue": { + "optional": true + }, + "vue-router": { + "optional": true + } + } + }, "node_modules/acorn": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", @@ -2786,10 +2872,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.9.11", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.11.tgz", - "integrity": "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==", - "dev": true, + "version": "2.9.19", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", + "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==", "license": "Apache-2.0", "bin": { "baseline-browser-mapping": "dist/cli.js" @@ -3009,7 +3094,6 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "dev": true, "license": "MIT" }, "node_modules/damerau-levenshtein": { @@ -3464,13 +3548,13 @@ } }, "node_modules/eslint-config-next": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.0.1.tgz", - "integrity": "sha512-wNuHw5gNOxwLUvpg0cu6IL0crrVC9hAwdS/7UwleNkwyaMiWIOAwf8yzXVqBBzL3c9A7jVRngJxjoSpPP1aEhg==", + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.1.6.tgz", + "integrity": "sha512-vKq40io2B0XtkkNDYyleATwblNt8xuh3FWp8SpSz3pt7P01OkBFlKsJZ2mWt5WsCySlDQLckb1zMY9yE9Qy0LA==", "dev": true, "license": "MIT", "dependencies": { - "@next/eslint-plugin-next": "16.0.1", + "@next/eslint-plugin-next": "16.1.6", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.32.0", @@ -4156,6 +4240,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/goober": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.18.tgz", + "integrity": "sha512-2vFqsaDVIT9Gz7N6kAL++pLpp41l3PfDuusHcjnGLfR6+huZkl6ziX+zgVC3ZxpqWhzH6pyDdGrCeDhMIvwaxw==", + "license": "MIT", + "peerDependencies": { + "csstype": "^3.0.10" + } + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -4796,6 +4889,15 @@ "jiti": "lib/jiti-cli.mjs" } }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -5366,14 +5468,14 @@ "license": "MIT" }, "node_modules/next": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/next/-/next-16.0.1.tgz", - "integrity": "sha512-e9RLSssZwd35p7/vOa+hoDFggUZIUbZhIUSLZuETCwrCVvxOs87NamoUzT+vbcNAL8Ld9GobBnWOA6SbV/arOw==", - "deprecated": "This version has a security vulnerability. Please upgrade to a patched version. See https://nextjs.org/blog/CVE-2025-66478 for more details.", + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/next/-/next-16.1.6.tgz", + "integrity": "sha512-hkyRkcu5x/41KoqnROkfTm2pZVbKxvbZRuNvKXLRXxs3VfyO0WhY50TQS40EuKO9SW3rBj/sF3WbVwDACeMZyw==", "license": "MIT", "dependencies": { - "@next/env": "16.0.1", + "@next/env": "16.1.6", "@swc/helpers": "0.5.15", + "baseline-browser-mapping": "^2.8.3", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" @@ -5385,14 +5487,14 @@ "node": ">=20.9.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "16.0.1", - "@next/swc-darwin-x64": "16.0.1", - "@next/swc-linux-arm64-gnu": "16.0.1", - "@next/swc-linux-arm64-musl": "16.0.1", - "@next/swc-linux-x64-gnu": "16.0.1", - "@next/swc-linux-x64-musl": "16.0.1", - "@next/swc-win32-arm64-msvc": "16.0.1", - "@next/swc-win32-x64-msvc": "16.0.1", + "@next/swc-darwin-arm64": "16.1.6", + "@next/swc-darwin-x64": "16.1.6", + "@next/swc-linux-arm64-gnu": "16.1.6", + "@next/swc-linux-arm64-musl": "16.1.6", + "@next/swc-linux-x64-gnu": "16.1.6", + "@next/swc-linux-x64-musl": "16.1.6", + "@next/swc-win32-arm64-msvc": "16.1.6", + "@next/swc-win32-x64-msvc": "16.1.6", "sharp": "^0.34.4" }, "peerDependencies": { @@ -5830,6 +5932,23 @@ "react": "^19.2.0" } }, + "node_modules/react-hot-toast": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.6.0.tgz", + "integrity": "sha512-bH+2EBMZ4sdyou/DPrfgIouFpcRLCJ+HoCA32UoAYHn6T3Ur5yfcDCeSr5mwldl6pFOsiocmrXMuoCJ1vV8bWg==", + "license": "MIT", + "dependencies": { + "csstype": "^3.1.3", + "goober": "^2.1.16" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -6974,6 +7093,35 @@ "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } + }, + "node_modules/zustand": { + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.11.tgz", + "integrity": "sha512-fdZY+dk7zn/vbWNCYmzZULHRrss0jx5pPFiOuMZ/5HJN6Yv3u+1Wswy/4MpZEkEGhtNH+pwxZB8OKgUBPzYAGg==", + "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/package.json b/package.json index 4a1ad1e..6732074 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "@types/react-dom": "^19", "autoprefixer": "^10.4.21", "babel-plugin-react-compiler": "1.0.0", + "baseline-browser-mapping": "^2.9.19", "eslint": "^9", "eslint-config-next": "^16.1.6", "postcss": "^8.5.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ee7cf01..c0f67ce 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -57,6 +57,9 @@ importers: babel-plugin-react-compiler: specifier: 1.0.0 version: 1.0.0 + baseline-browser-mapping: + specifier: ^2.9.19 + version: 2.9.19 eslint: specifier: ^9 version: 9.39.1(jiti@2.6.1) @@ -239,105 +242,89 @@ packages: resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} cpu: [arm64] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-arm@1.2.4': resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} cpu: [arm] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-ppc64@1.2.4': resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} cpu: [ppc64] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-riscv64@1.2.4': resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} cpu: [riscv64] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-s390x@1.2.4': resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} cpu: [s390x] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-x64@1.2.4': resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} cpu: [x64] os: [linux] - libc: [glibc] '@img/sharp-libvips-linuxmusl-arm64@1.2.4': resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} cpu: [arm64] os: [linux] - libc: [musl] '@img/sharp-libvips-linuxmusl-x64@1.2.4': resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} cpu: [x64] os: [linux] - libc: [musl] '@img/sharp-linux-arm64@0.34.5': resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] - libc: [glibc] '@img/sharp-linux-arm@0.34.5': resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] - libc: [glibc] '@img/sharp-linux-ppc64@0.34.5': resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ppc64] os: [linux] - libc: [glibc] '@img/sharp-linux-riscv64@0.34.5': resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [riscv64] os: [linux] - libc: [glibc] '@img/sharp-linux-s390x@0.34.5': resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] - libc: [glibc] '@img/sharp-linux-x64@0.34.5': resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] - libc: [glibc] '@img/sharp-linuxmusl-arm64@0.34.5': resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] - libc: [musl] '@img/sharp-linuxmusl-x64@0.34.5': resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] - libc: [musl] '@img/sharp-wasm32@0.34.5': resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} @@ -404,28 +391,24 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] - libc: [glibc] '@next/swc-linux-arm64-musl@16.1.6': resolution: {integrity: sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - libc: [musl] '@next/swc-linux-x64-gnu@16.1.6': resolution: {integrity: sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - libc: [glibc] '@next/swc-linux-x64-musl@16.1.6': resolution: {integrity: sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - libc: [musl] '@next/swc-win32-arm64-msvc@16.1.6': resolution: {integrity: sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw==} @@ -484,42 +467,36 @@ packages: engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] - libc: [glibc] '@parcel/watcher-linux-arm-musl@2.5.1': resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==} engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] - libc: [musl] '@parcel/watcher-linux-arm64-glibc@2.5.1': resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] - libc: [glibc] '@parcel/watcher-linux-arm64-musl@2.5.1': resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] - libc: [musl] '@parcel/watcher-linux-x64-glibc@2.5.1': resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] - libc: [glibc] '@parcel/watcher-linux-x64-musl@2.5.1': resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] - libc: [musl] '@parcel/watcher-win32-arm64@2.5.1': resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==} @@ -591,28 +568,24 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] - libc: [glibc] '@tailwindcss/oxide-linux-arm64-musl@4.1.17': resolution: {integrity: sha512-HvZLfGr42i5anKtIeQzxdkw/wPqIbpeZqe7vd3V9vI3RQxe3xU1fLjss0TjyhxWcBaipk7NYwSrwTwK1hJARMg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - libc: [musl] '@tailwindcss/oxide-linux-x64-gnu@4.1.17': resolution: {integrity: sha512-M3XZuORCGB7VPOEDH+nzpJ21XPvK5PyjlkSFkFziNHGLc5d6g3di2McAAblmaSUNl8IOmzYwLx9NsE7bplNkwQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - libc: [glibc] '@tailwindcss/oxide-linux-x64-musl@4.1.17': resolution: {integrity: sha512-k7f+pf9eXLEey4pBlw+8dgfJHY4PZ5qOUFDyNf7SI6lHjQ9Zt7+NcscjpwdCEbYi6FI5c2KDTDWyf2iHcCSyyQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - libc: [musl] '@tailwindcss/oxide-wasm32-wasi@4.1.17': resolution: {integrity: sha512-cEytGqSSoy7zK4JRWiTCx43FsKP/zGr0CsuMawhH67ONlH+T79VteQeJQRO/X7L0juEUA8ZyuYikcRBf0vsxhg==} @@ -769,49 +742,41 @@ packages: resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==} cpu: [arm64] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-arm64-musl@1.11.1': resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==} cpu: [arm64] os: [linux] - libc: [musl] '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==} cpu: [ppc64] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==} cpu: [riscv64] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==} cpu: [riscv64] os: [linux] - libc: [musl] '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==} cpu: [s390x] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-x64-gnu@1.11.1': resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==} cpu: [x64] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-x64-musl@1.11.1': resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==} cpu: [x64] os: [linux] - libc: [musl] '@unrs/resolver-binding-wasm32-wasi@1.11.1': resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==} @@ -970,8 +935,8 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - baseline-browser-mapping@2.8.25: - resolution: {integrity: sha512-2NovHVesVF5TXefsGX1yzx1xgr7+m9JQenvz6FQY3qd+YXkKkYiv+vTCc7OriP9mcDZpTC5mAOYN4ocd29+erA==} + baseline-browser-mapping@2.9.19: + resolution: {integrity: sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==} hasBin: true brace-expansion@1.1.12: @@ -1641,28 +1606,24 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [glibc] lightningcss-linux-arm64-musl@1.30.2: resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [musl] lightningcss-linux-x64-gnu@1.30.2: resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [glibc] lightningcss-linux-x64-musl@1.30.2: resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [musl] lightningcss-win32-arm64-msvc@1.30.2: resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==} @@ -2979,7 +2940,7 @@ snapshots: balanced-match@1.0.2: {} - baseline-browser-mapping@2.8.25: {} + baseline-browser-mapping@2.9.19: {} brace-expansion@1.1.12: dependencies: @@ -2996,7 +2957,7 @@ snapshots: browserslist@4.27.0: dependencies: - baseline-browser-mapping: 2.8.25 + baseline-browser-mapping: 2.9.19 caniuse-lite: 1.0.30001754 electron-to-chromium: 1.5.249 node-releases: 2.0.27 @@ -3865,7 +3826,7 @@ snapshots: dependencies: '@next/env': 16.1.6 '@swc/helpers': 0.5.15 - baseline-browser-mapping: 2.8.25 + baseline-browser-mapping: 2.9.19 caniuse-lite: 1.0.30001754 postcss: 8.4.31 react: 19.2.0 diff --git a/public/icons_calling.svg b/public/icons_calling.svg new file mode 100644 index 0000000..c80042f --- /dev/null +++ b/public/icons_calling.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/icons_chat.svg b/public/icons_chat.svg new file mode 100644 index 0000000..9f8a19c --- /dev/null +++ b/public/icons_chat.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/icons_pencil.svg b/public/icons_pencil.svg new file mode 100644 index 0000000..4b04fca --- /dev/null +++ b/public/icons_pencil.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/app/(main)/books/[id]/page.tsx b/src/app/(main)/books/[id]/page.tsx index c40cf12..f2b6472 100644 --- a/src/app/(main)/books/[id]/page.tsx +++ b/src/app/(main)/books/[id]/page.tsx @@ -3,8 +3,8 @@ import { useState } from "react"; import { useParams, useRouter } from "next/navigation"; import SearchBookResult from "@/components/base-ui/Search/search_bookresult"; -import BookStoryCard from "@/components/base-ui/BookStory/bookstory_card"; import { DUMMY_STORIES } from "@/data/dummyStories"; +import BookStoryCardLarge from "@/components/base-ui/BookStory/bookstory_card_large"; export default function BookDetailPage() { const params = useParams(); @@ -23,58 +23,61 @@ export default function BookDetailPage() { // 관련된 책 이야기들 (더미 데이터에서 필터링) const relatedStories = DUMMY_STORIES.filter( - (story) => story.bookTitle === bookData.title + (story) => story.bookTitle === bookData.title, ); return ( -
-

- 도서 선택 {bookData.title} 중 -

+
+
+

+ 도서 선택 {bookData.title} 중 +

- {/* 선택한 책 카드 */} -
- { - router.push(`/stories/new?bookId=${bookId}`); - }} - /> -
+ {/* 선택한 책 카드 */} +
+ { + router.push(`/stories/new?bookId=${bookId}`); + }} + /> +
- {/* 책이야기 */} -
-

- 책이야기 {relatedStories.length} -

-
+ {/* 책이야기 */} +
+

+ 책이야기{" "} + {relatedStories.length} +

+
- {/* 책 이야기 카드 */} -
- {relatedStories.map((story) => ( -
router.push(`/stories/${story.id}`)} - className="cursor-pointer" - > - -
- ))} + {/* 책 이야기 카드 */} +
+ {relatedStories.map((story) => ( +
router.push(`/stories/${story.id}`)} + className="cursor-pointer" + > + +
+ ))} +
); diff --git a/src/app/(main)/news/[id]/page.tsx b/src/app/(main)/news/[id]/page.tsx index 55f3cd6..23ec1ce 100644 --- a/src/app/(main)/news/[id]/page.tsx +++ b/src/app/(main)/news/[id]/page.tsx @@ -1,3 +1,4 @@ +import FloatingFab from "@/components/base-ui/Float"; import TodayRecommendedBooks from "@/components/base-ui/News/today_recommended_books"; import Image from "next/image"; import { notFound } from "next/navigation"; @@ -159,21 +160,10 @@ export default async function NewsDetailPage({ params }: Props) {
- {/* 문의하기 */} - + ); } diff --git a/src/app/(main)/news/page.tsx b/src/app/(main)/news/page.tsx index 60ff7dc..3d2c943 100644 --- a/src/app/(main)/news/page.tsx +++ b/src/app/(main)/news/page.tsx @@ -3,6 +3,7 @@ import Image from "next/image"; import NewsList from "@/components/base-ui/News/news_list"; import TodayRecommendedBooks from "@/components/base-ui/News/today_recommended_books"; +import FloatingFab from "@/components/base-ui/Float"; const DUMMY_NEWS = [ { @@ -105,21 +106,11 @@ export default function NewsPage() {
- {/* 문의하기 */} - + +
); } diff --git a/src/app/(main)/page.tsx b/src/app/(main)/page.tsx index 2799e9b..d0994e3 100644 --- a/src/app/(main)/page.tsx +++ b/src/app/(main)/page.tsx @@ -13,20 +13,20 @@ import BookStoryCardLarge from "@/components/base-ui/BookStory/bookstory_card_la export default function HomePage() { const groups: { id: string; name: string }[] = []; const [showLoginModal, setShowLoginModal] = useState(false); - + // 사용자 더미 데이터 const users = [ - { id: '1', name: 'hy_0716', subscribingCount: 17, subscribersCount: 32 }, - { id: '2', name: 'hy_0716', subscribingCount: 17, subscribersCount: 32 }, - { id: '3', name: 'hy_0716', subscribingCount: 17, subscribersCount: 32 }, - { id: '4', name: 'hy_0716', subscribingCount: 17, subscribersCount: 32 }, + { id: "1", name: "hy_0716", subscribingCount: 17, subscribersCount: 32 }, + { id: "2", name: "hy_0716", subscribingCount: 17, subscribersCount: 32 }, + { id: "3", name: "hy_0716", subscribingCount: 17, subscribersCount: 32 }, + { id: "4", name: "hy_0716", subscribingCount: 17, subscribersCount: 32 }, ]; return (
{/* 임시 로그인 모달 테스트 버튼 */} @@ -39,9 +39,7 @@ export default function HomePage() {
{/* 소식 */}
-

- 소식 -

+

소식

@@ -49,9 +47,7 @@ export default function HomePage() {
-

- 독서모임 -

+

독서모임

@@ -65,7 +61,7 @@ export default function HomePage() { name={u.name} subscribingCount={u.subscribingCount} subscribersCount={u.subscribersCount} - onSubscribeClick={() => console.log('subscribe', u.id)} + onSubscribeClick={() => console.log("subscribe", u.id)} /> ))}
@@ -151,17 +147,17 @@ export default function HomePage() {
{/* 소식 */}
-

- 소식 -

- +

+ 소식 +

+
{/* 책 이야기 카드 */}
{DUMMY_STORIES.slice(0, 3).map((story) => ( - + /> ))} -
-
+
+
diff --git a/src/app/(main)/stories/new/page.tsx b/src/app/(main)/stories/new/page.tsx index a87875f..5d09d79 100644 --- a/src/app/(main)/stories/new/page.tsx +++ b/src/app/(main)/stories/new/page.tsx @@ -42,35 +42,39 @@ function StoryNewContent() { return (
- {/* 책이야기 > 글 작성하기 */} - {/* 모바일: 전체 너비 선 */} -
-
-
전체
-
- next + {/* 책이야기 > 글 작성하기 - 모달 열리면 숨김 */} + {!isBookSelectModalOpen && ( + <> + {/* 모바일: 전체 너비 선 */} +
+
+
전체
+
+ next +
+
글 작성하기
+
-
글 작성하기
-
-
- {/* 태블릿/데스크탑: max-w 안에서 선 */} -
-
전체
-
- next -
-
글 작성하기
-
+ {/* 태블릿/데스크탑: max-w 안에서 선 */} +
+
전체
+
+ next +
+
글 작성하기
+
+ + )} {/* 메인 콘텐츠 영역 */}
{/* 책 선택하기 박스 */} diff --git a/src/app/(main)/stories/page.tsx b/src/app/(main)/stories/page.tsx index 14aae92..fa6ae07 100644 --- a/src/app/(main)/stories/page.tsx +++ b/src/app/(main)/stories/page.tsx @@ -1,9 +1,9 @@ "use client"; import BookStoryCardLarge from "@/components/base-ui/BookStory/bookstory_card_large"; import ListSubscribeLarge from "@/components/base-ui/home/list_subscribe_large"; -import Image from "next/image"; import { useRouter } from "next/navigation"; import { DUMMY_STORIES } from "@/data/dummyStories"; +import FloatingFab from "@/components/base-ui/Float"; // TODO: 실제 로그인 상태 여부는 나중에 const isLoggedIn = false; // true: 로그인, false: 로그인X @@ -17,30 +17,30 @@ export default function StoriesPage() { return (
-
-
+
+
전체
-
+
구독중
-
+
긁적긁적
-
+
북적북적
{/* 메인 콘텐츠 영역 */}
-
+
{/* 첫 번째 줄 */} {DUMMY_STORIES.slice(0, 4).map((story) => (
handleCardClick(story.id)} - className="cursor-pointer" + className="cursor-pointer shrink-0" > handleCardClick(story.id)} - className="cursor-pointer" + className="cursor-pointer shrink-0" > ))}
- {/* 글쓰기 버튼 */} -
); diff --git a/src/app/(public)/signup/[step]/page.tsx b/src/app/(public)/signup/[step]/page.tsx new file mode 100644 index 0000000..ccd72d3 --- /dev/null +++ b/src/app/(public)/signup/[step]/page.tsx @@ -0,0 +1,38 @@ +"use client"; + +import React from "react"; +import { useParams, useRouter } from "next/navigation"; +import TermsAgreement from "@/components/base-ui/Join/steps/TermsAgreement/TermsAgreement"; +import EmailVerification from "@/components/base-ui/Join/steps/EmailVerification/EmailVerification"; +import PasswordEntry from "@/components/base-ui/Join/steps/PasswordEntry/PasswordEntry"; +import ProfileSetup from "@/components/base-ui/Join/steps/ProfileSetup/ProfileSetup"; +import ProfileImage from "@/components/base-ui/Join/steps/ProfileImage/ProfileImage"; +import SignupComplete from "@/components/base-ui/Join/steps/SignupComplete/SignupComplete"; + +export default function SignupStepPage() { + const params = useParams(); + const router = useRouter(); + const step = params.step as string; + + const navigateTo = (nextStep: string) => { + router.push(`/signup/${nextStep}`); + }; + + const steps: Record = { + terms: navigateTo("email")} />, + email: navigateTo("password")} />, + password: navigateTo("profile")} />, + profile: navigateTo("profile-image")} />, + "profile-image": navigateTo("complete")} />, + complete: , + }; + + const currentStep = steps[step]; + + if (!currentStep) { + // Falls back to terms if step is invalid + return null; + } + + return <>{currentStep}; +} diff --git a/src/app/(public)/signup/layout.tsx b/src/app/(public)/signup/layout.tsx index 8b21600..835a483 100644 --- a/src/app/(public)/signup/layout.tsx +++ b/src/app/(public)/signup/layout.tsx @@ -1,4 +1,5 @@ import React from "react"; +import { SignupProvider } from "@/contexts/SignupContext"; export default function SignupLayout({ children, @@ -6,11 +7,13 @@ export default function SignupLayout({ children: React.ReactNode; }) { return ( -
- {children} -
+ +
+ {children} +
+
); } \ No newline at end of file diff --git a/src/app/(public)/signup/page.tsx b/src/app/(public)/signup/page.tsx index a35a982..b916629 100644 --- a/src/app/(public)/signup/page.tsx +++ b/src/app/(public)/signup/page.tsx @@ -1,35 +1,14 @@ "use client"; -import React, { useState } from "react"; -import TermsAgreement from "@/components/base-ui/Join/steps/TermsAgreement/TermsAgreement"; -import EmailVerification from "@/components/base-ui/Join/steps/EmailVerification/EmailVerification"; -import PasswordEntry from "@/components/base-ui/Join/steps/PasswordEntry/PasswordEntry"; -import ProfileSetup from "@/components/base-ui/Join/steps/ProfileSetup/ProfileSetup"; -import ProfileImage from "@/components/base-ui/Join/steps/ProfileImage/ProfileImage"; -import SignupComplete from "@/components/base-ui/Join/steps/SignupComplete/SignupComplete"; +import { useEffect } from "react"; +import { useRouter } from "next/navigation"; export default function SignupPage() { - const [step, setStep] = useState< - "terms" | "email" | "password" | "profile" | "profile-image" | "complete" - >("terms"); - const steps = { - terms: ( - { - setStep("email"); - }} - /> - ), - email: setStep("password")} />, - password: setStep("profile")} />, - profile: setStep("profile-image")} />, - "profile-image": setStep("complete")} />, - complete: , - }; + const router = useRouter(); - return ( - <> - {steps[step]} - - ); + useEffect(() => { + router.replace("/signup/terms"); + }, [router]); + + return null; } diff --git a/src/app/globals.css b/src/app/globals.css index 604a790..086e1a3 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -146,3 +146,32 @@ body { --breakpoint-t: 768px; --breakpoint-d: 1440px; } + +/* 애니메이션 */ +@keyframes fade-in { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes slide-down { + from { + opacity: 0; + transform: translateY(-20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@utility animate-fade-in { + animation: fade-in 0.2s ease-out; +} + +@utility animate-slide-down { + animation: slide-down 0.3s ease-out; +} diff --git a/src/app/groups/[id]/admin/notice/new/page.tsx b/src/app/groups/[id]/admin/notice/new/page.tsx index 553570a..12d33be 100644 --- a/src/app/groups/[id]/admin/notice/new/page.tsx +++ b/src/app/groups/[id]/admin/notice/new/page.tsx @@ -1,11 +1,11 @@ -'use client'; +"use client"; -import { useState, useRef, useEffect, type ChangeEvent } from 'react'; -import { useParams, useRouter } from 'next/navigation'; -import Image from 'next/image'; -import BookshelfModal from '@/components/base-ui/Group/BookshelfModal'; -import BookDetailCard from '@/components/base-ui/Bookcase/BookDetailCard'; -import { useHeaderTitle } from '@/contexts/HeaderTitleContext'; +import { useState, useRef, useEffect, type ChangeEvent } from "react"; +import { useParams, useRouter } from "next/navigation"; +import Image from "next/image"; +import BookshelfModal from "@/components/base-ui/Group/BookshelfModal"; +import BookDetailCard from "@/components/base-ui/Bookcase/BookDetailCard"; +import { useHeaderTitle } from "@/contexts/HeaderTitleContext"; type Book = { id: number; @@ -21,16 +21,17 @@ export default function NewNoticePage() { const router = useRouter(); const groupId = params.id as string; const { setCustomTitle } = useHeaderTitle(); - - const [title, setTitle] = useState(''); - const [content, setContent] = useState(''); - const [selectedOption, setSelectedOption] = - useState<'vote' | 'bookshelf' | 'image' | null>(null); - const [voteItems, setVoteItems] = useState(['', '', '', '']); + + const [title, setTitle] = useState(""); + const [content, setContent] = useState(""); + const [selectedOption, setSelectedOption] = useState< + "vote" | "bookshelf" | "image" | null + >(null); + const [voteItems, setVoteItems] = useState(["", "", "", ""]); const [isMultiple, setIsMultiple] = useState(false); const [isAnonymous, setIsAnonymous] = useState(false); const [isImportant, setIsImportant] = useState(false); - const [voteDate, setVoteDate] = useState(''); + const [voteDate, setVoteDate] = useState(""); const [isBookshelfModalOpen, setIsBookshelfModalOpen] = useState(false); const [imagePreviews, setImagePreviews] = useState([]); const [selectedBook, setSelectedBook] = useState(null); @@ -39,7 +40,7 @@ export default function NewNoticePage() { // 모바일 헤더 타이틀 설정 useEffect(() => { - setCustomTitle('공지사항 작성'); + setCustomTitle("공지사항 작성"); return () => setCustomTitle(null); }, [setCustomTitle]); @@ -49,20 +50,18 @@ export default function NewNoticePage() { const handleSubmit = () => { const trimmedVoteItems = - selectedOption === 'vote' - ? voteItems - .map((item) => item.trim()) - .filter((item) => item.length > 0) + selectedOption === "vote" + ? voteItems.map((item) => item.trim()).filter((item) => item.length > 0) : []; // TODO: 실제 저장 로직 구현 - console.log('공지사항 저장:', { + console.log("공지사항 저장:", { title, content, selectedOption, voteItems: trimmedVoteItems, voteSettings: - selectedOption === 'vote' + selectedOption === "vote" ? { isMultiple, isAnonymous, @@ -75,34 +74,31 @@ export default function NewNoticePage() { }; const handleCreateVote = () => { - setSelectedOption(selectedOption === 'vote' ? null : 'vote'); + setSelectedOption(selectedOption === "vote" ? null : "vote"); // TODO: 투표 생성 페이지로 이동 또는 모달 열기 - console.log('투표 생성'); + console.log("투표 생성"); }; const handleVoteItemChange = (index: number, value: string) => { - setVoteItems((prev) => - prev.map((item, i) => (i === index ? value : item)), - ); + setVoteItems((prev) => prev.map((item, i) => (i === index ? value : item))); }; const handleRegisterBookshelf = () => { - const nextSelected = - selectedOption === 'bookshelf' ? null : 'bookshelf'; + const nextSelected = selectedOption === "bookshelf" ? null : "bookshelf"; setSelectedOption(nextSelected); - setIsBookshelfModalOpen(nextSelected === 'bookshelf'); - console.log('책장 등록'); + setIsBookshelfModalOpen(nextSelected === "bookshelf"); + console.log("책장 등록"); }; const handleBookSelect = (book: Book) => { setSelectedBook(book); - setSelectedOption('bookshelf'); + setSelectedOption("bookshelf"); }; const handleImageFile = () => { - setSelectedOption('image'); + setSelectedOption("image"); imageInputRef.current?.click(); - console.log('이미지 파일'); + console.log("이미지 파일"); }; const handleImageChange = (e: ChangeEvent) => { @@ -122,27 +118,17 @@ export default function NewNoticePage() { }, []); return (
- {/* 뒤로가기 - 모바일에서만 표시 */} -
- -
- {/* 구분선 */}
- -
+ +
{/* 제목 및 내용 입력 영역 */}
-

공지사항 작성

- +

+ 공지사항 작성 +

+ {/* 선택된 책 표시 */} {selectedBook && (
@@ -157,215 +143,221 @@ export default function NewNoticePage() { )} {/* 입력 박스 */} -
- {/* 제목 */} -
- setTitle(e.target.value)} - placeholder="제목을 입력해주세요." - className="w-full bg-transparent outline-none text-Gray-7 subhead_4_1 placeholder:text-Gray-3" - /> -
- - {/* 내용 */} -
-