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 (
- {/* 책이야기 > 글 작성하기 */}
- {/* 모바일: 전체 너비 선 */}
-
-
-
전체
-
-
+ {/* 책이야기 > 글 작성하기 - 모달 열리면 숨김 */}
+ {!isBookSelectModalOpen && (
+ <>
+ {/* 모바일: 전체 너비 선 */}
+
-
글 작성하기
-
-
- {/* 태블릿/데스크탑: max-w 안에서 선 */}
-
+ {/* 태블릿/데스크탑: max-w 안에서 선 */}
+
+ >
+ )}
{/* 메인 콘텐츠 영역 */}
{/* 책 선택하기 박스 */}
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"
- />
-
-
- {/* 내용 */}
-
-
+
+ {/* 제목 */}
+
+ setTitle(e.target.value)}
+ placeholder="제목을 입력해주세요."
+ className="w-full bg-transparent outline-none text-Gray-7 subhead_4_1 placeholder:text-Gray-3"
+ />
+
- {/* 투표 */}
-
- {selectedOption === 'vote' && (
-
-
- {[0, 1, 2, 3].map((index) => (
-
-
- handleVoteItemChange(index, e.target.value)
- }
- placeholder={`투표 항목 ${index + 1} 입력`}
- className="w-full bg-transparent outline-none text-Gray-7 body_1_2 placeholder:text-Gray-3"
- />
-
- ))}
-
+ {/* 내용 */}
+
+
- {/* 추가 설정 */}
-
- {/* 복수선택 */}
-
+ {/* 투표 */}
+
+ {selectedOption === "vote" && (
+
+
+ {[0, 1, 2, 3].map((index) => (
+
+
+ handleVoteItemChange(index, e.target.value)
+ }
+ placeholder={`투표 항목 ${index + 1} 입력`}
+ className="w-full bg-transparent outline-none text-Gray-7 body_1_2 placeholder:text-Gray-3"
+ />
+
+ ))}
+
- {/* 익명선택 */}
-
+ {/* 추가 설정 */}
+
+ {/* 복수선택 */}
+
- {/* 중요여부 */}
-
+ {/* 익명선택 */}
+
- {/* 날짜 선택 */}
-
-
-
- )}
+ {/* 중요여부 */}
+
- {selectedOption === 'image' && (
-
- {imagePreviews.length > 0 ? (
-
- {imagePreviews.map((src, index) => (
-
+ {/* 날짜 선택 */}
+
+
- {/* 이미지 삭제 */}
-
- ))}
+
날짜선택
+
- ) : null}
-
- )}
-
-
-
-
-
-
+
+ )}
+
+ {selectedOption === "image" && (
+
+ {imagePreviews.length > 0 ? (
+
+ {imagePreviews.map((src, index) => (
+
+
+ {/* 이미지 삭제 */}
+
+
+ ))}
+
+ ) : null}
+
+ )}
+
+
+
+
+
+
+
+
-
-
@@ -395,9 +387,7 @@ export default function NewNoticePage() {
isOpen={isBookshelfModalOpen}
onClose={() => {
setIsBookshelfModalOpen(false);
- setSelectedOption((prev) =>
- prev === 'bookshelf' ? null : prev,
- );
+ setSelectedOption((prev) => (prev === "bookshelf" ? null : prev));
}}
onSelect={handleBookSelect}
/>
diff --git a/src/app/groups/[id]/bookcase/[bookId]/DebateSection.tsx b/src/app/groups/[id]/bookcase/[bookId]/DebateSection.tsx
index a8cdcbf..12236e9 100644
--- a/src/app/groups/[id]/bookcase/[bookId]/DebateSection.tsx
+++ b/src/app/groups/[id]/bookcase/[bookId]/DebateSection.tsx
@@ -56,7 +56,7 @@ export default function DebateSection({