diff --git a/sprint9/.eslintrc.json b/sprint9/.eslintrc.json new file mode 100644 index 000000000..bffb357a7 --- /dev/null +++ b/sprint9/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "next/core-web-vitals" +} diff --git a/sprint9/.gitignore b/sprint9/.gitignore new file mode 100644 index 000000000..130d83e6d --- /dev/null +++ b/sprint9/.gitignore @@ -0,0 +1,241 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions +!.yarn/cache + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# env files (can opt-in for committing if needed) +.env* + +# typescript +*.tsbuildinfo +next-env.d.ts + +# macOS +.Icon* + +# Thumbnails +._* + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +### yarn ### +/.yarn/ + +### React ### +.DS_* +**/*.backup.* +**/*.back.* + +### ReactNative ### +# React Native Stack Base + +.expo +__generated__ + +### OTHER ### +# Node.js logs +logs +*.log +lerna-debug.log* +.pnpm-debug.log* +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Optional eslint cache +.eslintcache + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# yarn v2 +.yarn-integrity + +# General +.DS_Store +.AppleDouble +.LSOverride + +### ReactNative.Android Stack ### +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Log/OS Files + +# Android Studio generated files and folders +captures/ +.externalNativeBuild/ +.cxx/ +*.apk +output.json + +# IntelliJ +*.iml +.idea/ +misc.xml +deploymentTargetDropDown.xml +render.experimental.xml + +# Keystore files +*.jks +*.keystore + +# Google Services (e.g. APIs or Firebase) +google-services.json + +# Android Profiling +*.hprof + +### ReactNative.Xcode Stack ### +## User settings +xcuserdata/ + +## Xcode 8 and earlier +*.xcscmblueprint +*.xccheckout + +### ReactNative.Buck Stack ### +buck-out/ +.buckconfig.local +.buckd/ +.buckversion +.fakebuckversion + +### ReactNative.Gradle Stack ### +.gradle +**/build/ +!src/**/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +### ReactNative.Linux Stack ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +### Webstorm +.idea/ + +# Stores IntelliJ IDEA project settings +*.iml + +# IDEs +.idea/ +.vscode diff --git a/sprint9/README.md b/sprint9/README.md new file mode 100644 index 000000000..705e683a1 --- /dev/null +++ b/sprint9/README.md @@ -0,0 +1,99 @@ +## ๐Ÿ“‹ ์œ„ํด๋ฆฌ ๋ฏธ์…˜ ์š”๊ตฌ์‚ฌํ•ญ + +### **๊ธฐ๋ณธ ์š”๊ตฌ์‚ฌํ•ญ** + +#### **๊ณตํ†ต** +- [ ] Github์— ์œ„ํด๋ฆฌ ๋ฏธ์…˜ PR์„ ๋งŒ๋“ค์–ด ์ฃผ์„ธ์š”. +- [ ] React ํ˜น์€ Next.js๋ฅผ ์‚ฌ์šฉํ•ด ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค. +- [ ] ํ”„๋ก ํŠธ์—”๋“œ์—์„œ API ์š”์ฒญ ๊ตฌํ˜„์€ TanStack React Query๋ฅผ ํ™œ์šฉํ•ด ์ฃผ์„ธ์š”. +- [ ] API๋Š” `https://panda-market-api.vercel.app`๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋ช…์„ธ๋Š” `https://panda-market-api.vercel.app/docs`๋ฅผ ํ™•์ธํ•ด ์ฃผ์„ธ์š”. + +--- + +#### **๋กœ๊ทธ์ธ/ํšŒ์›๊ฐ€์ž… ํŽ˜์ด์ง€** +- [ ] JavaScript๋กœ ๊ตฌํ˜„ํ•œ ๋กœ๊ทธ์ธ/ํšŒ์›๊ฐ€์ž… ํŽ˜์ด์ง€๋ฅผ React.js ํ˜น์€ Next.js๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•ด ์ฃผ์„ธ์š”. + +--- + +#### **๋กœ๊ทธ์ธ ํŽ˜์ด์ง€** +- [ ] "ํšŒ์› ๊ฐ€์ž…ํ•˜๊ธฐ"๋ฅผ ํด๋ฆญํ•˜๋ฉด ํšŒ์›๊ฐ€์ž… ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ด ์ฃผ์„ธ์š”. +- [ ] ๋กœ๊ทธ์ธ ์‹คํŒจํ•˜๋Š” ๊ฒฝ์šฐ, ์ด๋ฉ”์ผ input ์•„๋ž˜์— "์ด๋ฉ”์ผ์„ ํ™•์ธํ•ด ์ฃผ์„ธ์š”.", ๋น„๋ฐ€๋ฒˆํ˜ธ input ์•„๋ž˜์— "๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ํ™•์ธํ•ด ์ฃผ์„ธ์š”." ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ํ‘œ์‹œํ•ด ์ฃผ์„ธ์š”. +- [ ] ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ์ด ํ™œ์„ฑํ™”๋œ ํ›„, ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ ํด๋ฆญ ๋˜๋Š” Enterํ‚ค ์ž…๋ ฅ์œผ๋กœ ๋กœ๊ทธ์ธ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. +- [ ] "/auth/signIn"์œผ๋กœ POST ์š”์ฒญํ•ด์„œ ์„ฑ๊ณต ์‘๋‹ต์„ ๋ฐ›์œผ๋ฉด ์ค‘๊ณ  ๋งˆ์ผ“ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. ์ฐธ๊ณ ๋กœ JWT๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. +- [ ] ์‹คํŒจํ•  ๊ฒฝ์šฐ, ์‹คํŒจ ๋ฉ”์‹œ์ง€๋ฅผ ๋ชจ๋‹ฌ์„ ํ†ตํ•ด ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. + +--- + +#### **ํšŒ์›๊ฐ€์ž… ํŽ˜์ด์ง€** +- [ ] "ํšŒ์› ๊ฐ€์ž…ํ•˜๊ธฐ"๋ฅผ ํด๋ฆญํ•˜๋ฉด '/signin' ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. +- [ ] ํšŒ์›๊ฐ€์ž… ๋ฒ„ํŠผ ํด๋ฆญ ๋˜๋Š” Enterํ‚ค ์ž…๋ ฅ์œผ๋กœ ํšŒ์›๊ฐ€์ž…์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. +- [ ] ๋น„๋ฐ€๋ฒˆํ˜ธ input๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ ํ™•์ธ input์˜ ๊ฐ’์ด ๋‹ค๋ฅธ ๊ฒฝ์šฐ, ๋น„๋ฐ€๋ฒˆํ˜ธ ํ™•์ธ input ์•„๋ž˜์— "๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์•„์š”." ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ํ‘œ์‹œํ•ด ์ฃผ์„ธ์š”. +- [ ] ๋ฒ„ํŠผ์ด ํ™œ์„ฑํ™”๋œ ํ›„, ํšŒ์›๊ฐ€์ž…์€ "/auth/signUp" POST ์š”์ฒญํ•ด์„œ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ฐธ๊ณ ๋กœ JWT๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. +- [ ] ํšŒ์›๊ฐ€์ž… ์„ฑ๊ณต ์‘๋‹ต์„ ๋ฐ›์œผ๋ฉด ์ค‘๊ณ ๋งˆ์ผ“ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. +- [ ] ์‹คํŒจํ•  ๊ฒฝ์šฐ, ์‹คํŒจ ๋ฉ”์‹œ์ง€๋ฅผ ๋ชจ๋‹ฌ์„ ํ†ตํ•ด ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. + +--- + +#### **๋กœ๊ทธ์ธ, ํšŒ์›๊ฐ€์ž… ํŽ˜์ด์ง€ ๊ณตํ†ต** +- [ ] ๋ˆˆ ๋ชจ์–‘ ์•„์ด์ฝ˜ ํด๋ฆญ ์‹œ ๋น„๋ฐ€๋ฒˆํ˜ธ์˜ ๋ฌธ์ž์—ด์ด ๋ณด์ด๊ธฐ๋„ ํ•˜๊ณ , ๊ฐ€๋ ค์ง‘๋‹ˆ๋‹ค. +- [ ] ๋น„๋ฐ€๋ฒˆํ˜ธ์˜ ๋ฌธ์ž์—ด์ด ๊ฐ€๋ ค์งˆ ๋•Œ๋Š” ๋ˆˆ ๋ชจ์–‘ ์•„์ด์ฝ˜์—๋Š” ์‚ฌ์„ ์ด ๊ทธ์–ด์ ธ ์žˆ๊ณ , ๋น„๋ฐ€๋ฒˆํ˜ธ์˜ ๋ฌธ์ž์—ด์ด ๋ณด์ผ ๋•Œ๋Š” ์‚ฌ์„ ์ด ์—†๋Š” ๋ˆˆ ๋ชจ์–‘ ์•„์ด์ฝ˜์ด ๋ณด์ž…๋‹ˆ๋‹ค. +- [ ] ์†Œ์…œ ๋กœ๊ทธ์ธ์— ๊ตฌ๊ธ€ ์•„์ด์ฝ˜ ํด๋ฆญ ์‹œ 'https://www.google.com', ์นด์นด์˜ค ์•„์ด์ฝ˜ ํด๋ฆญ ์‹œ 'https://www.kakaocorp.com/page'๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. +- [ ] ๋กœ๊ทธ์ธ/ํšŒ์›๊ฐ€์ž… ์‹œ ์„ฑ๊ณต ์‘๋‹ต์œผ๋กœ ๋ฐ›์€ accessToken์„ ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. +- [ ] ๋กœ๊ทธ์ธ/ํšŒ์›๊ฐ€์ž… ํŽ˜์ด์ง€์— ์ ‘๊ทผ ์‹œ ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์— accessToken์ด ์žˆ๋Š” ๊ฒฝ์šฐ '/items' ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. + +--- + +#### **GNB** +- [ ] ์ƒ๋‹จ ๋‚ด๋น„๊ฒŒ์ด์…˜ ๋ฐ”์— ํ”„๋กœํ•„ ์˜์—ญ์€ ์ธ๊ฐ€๋œ ๊ฒฝ์šฐ, ์œ ์ € ์ •๋ณด API๋ฅผ ํ™œ์šฉํ•ด ์ฃผ์„ธ์š”. +- [ ] ์ธ๊ฐ€๋˜์ง€ ์•Š์•˜์„ ๊ฒฝ์šฐ "๋กœ๊ทธ์ธ" ๋ฒ„ํŠผ์ด ๋ณด์ด๊ฒŒ ํ•ด ์ฃผ์„ธ์š”. + +--- + +#### **์ƒํ’ˆ ์ƒ์„ธ ํŽ˜์ด์ง€** +- [ ] PC, Tablet, Mobile ๋””์ž์ธ์— ํ•ด๋‹นํ•˜๋Š” ์ƒํ’ˆ ์ƒ์„ธ ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค์–ด ์ฃผ์„ธ์š”. +- [ ] ์ƒํ’ˆ ์ƒ์„ธ ํŽ˜์ด์ง€ URL path๋Š” "/items/{itemId}"๋กœ ์„ค์ •ํ•˜์„ธ์š”. +- [ ] '๋ชฉ๋ก์œผ๋กœ ๋Œ์•„๊ฐ€๊ธฐ' ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ์ค‘๊ณ ๋งˆ์ผ“ ํŽ˜์ด์ง€ "/items"๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. +- [ ] ์ƒํ’ˆ ์ƒ์„ธ ๋ฐ์ดํ„ฐ๋Š” '/products/{productId}' GET ๋ฉ”์„œ๋“œ ์‚ฌ์šฉํ•ด ๋ถˆ๋Ÿฌ์˜ค์„ธ์š”. ์ด๋•Œ, ์ƒํ’ˆ ์ƒ์„ธ ์กฐํšŒ๋Š” ์ธ๊ฐ€๋œ ์‚ฌ์šฉ์ž๋งŒ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. +- [ ] ์ƒํ’ˆ์— ๋Œ€ํ•œ ๋Œ“๊ธ€ ์กฐํšŒ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. +- [ ] ์ƒํ’ˆ ์ˆ˜์ • ๋ฐ ์‚ญ์ œ ๊ธฐ๋Šฅ์„ API๋ฅผ ํ™œ์šฉํ•ด ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ, ์ธ๊ฐ€๋œ ์‚ฌ์šฉ์ž๋งŒ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. + - [ ] ์ƒํ’ˆ ์ˆ˜์ •์€ '/products/{productId}' PATCH์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + - [ ] ์ƒํ’ˆ ์‚ญ์ œ๋Š” '/products/{productId}' DELETE๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. +- [ ] ์ƒํ’ˆ ์‚ญ์ œ ์ „, ํ™•์ธ ๋ชจ๋‹ฌ์„ ๋„์›Œ์ฃผ์„ธ์š”. +- [ ] ์ƒํ’ˆ์— ๋Œ€ํ•œ ์ข‹์•„์š” ๋ฐ ์ข‹์•„์š” ์ทจ์†Œ ๊ธฐ๋Šฅ์„ '/products/{productId}/favorite' POST & DELETE ํ™œ์šฉํ•ด ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ ์ธ๊ฐ€๋œ ์‚ฌ์šฉ์ž๋งŒ ์ข‹์•„์š” ๊ธฐ๋Šฅ์„ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. +- [ ] ๋Œ“๊ธ€ ์ƒ์„ฑ ๋ฐ ์‚ญ์ œ ๊ธฐ๋Šฅ์„ API๋ฅผ ํ™œ์šฉํ•ด ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ, ์ธ๊ฐ€๋œ ์‚ฌ์šฉ์ž๋งŒ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. + - [ ] ๋Œ“๊ธ€ ์ˆ˜์ •์€ '/comments/{commentId}' PATCH์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + - [ ] ๋Œ“๊ธ€ ์‚ญ์ œ๋Š” '/comments/{commentId}' DELETE๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +--- + +### **์‹ฌํ™” ์š”๊ตฌ์‚ฌํ•ญ** + +#### **๋กœ๊ทธ์ธ ๋ฐ ํšŒ์›๊ฐ€์ž… ํŽ˜์ด์ง€ ๊ณตํ†ต** +- [ ] ๋กœ๊ทธ์ธ, ํšŒ์›๊ฐ€์ž… ๊ธฐ๋Šฅ์— react-hook-form์„ ํ™œ์šฉํ•ด ์ฃผ์„ธ์š”. +- [ ] ๋ธŒ๋ผ์šฐ์ €์— ํ˜„์žฌ ๋ณด์ด๋Š” ํ™”๋ฉด์˜ ์˜์—ญ(viewport) ๋„ˆ๋น„๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ถ„๊ธฐ๋˜๋Š” ๋ฐ˜์‘ํ˜• ๋””์ž์ธ์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค: + - PC: 1200px ์ด์ƒ + - Tablet: 744px ์ด์ƒ ~ 1199px ์ดํ•˜ + - Mobile: 375px ์ด์ƒ ~ 743px ์ดํ•˜ + - 375px ๋ฏธ๋งŒ ์‚ฌ์ด์ฆˆ์˜ ๋””์ž์ธ์€ ๊ณ ๋ คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +--- + +#### **์œ ์ € ๊ธฐ๋Šฅ** +- [ ] ๋ฆฌํ€˜์ŠคํŠธ ํ—ค๋”์— ์ธ์ฆ ํ† ํฐ์„ ์ฒจ๋ถ€ํ•  ๋•Œ axios interceptors๋ฅผ ํ™œ์šฉํ•ด ์ฃผ์„ธ์š”. (axios๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์ด์™€ ์œ ์‚ฌํ•œ ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•ด ์ฃผ์„ธ์š”.) + +--- + +#### **React-Query๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜** +- [ ] fetch ํ˜น์€ axios๋กœ ๊ตฌํ˜„๋œ ๊ธฐ์กด์˜ API ์š”์ฒญ ์ฝ”๋“œ๋ฅผ React-Qeury๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํ•ฉ๋‹ˆ๋‹ค. + +--- + +#### **๋กœ๋”ฉ ๋ฐ ์—๋Ÿฌ ํ•ธ๋“ค๋ง** +- [ ] ๋กœ๋”ฉ ์ธ๋””์ผ€์ดํ„ฐ์™€ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. +- [ ] ์ƒํ’ˆ ๋ชฉ๋ก ๋ฐ ์ƒํ’ˆ ์ƒ์„ธ ๋ฐ์ดํ„ฐ๋ฅผ Prefetching ํ•ฉ๋‹ˆ๋‹ค. + +--- + +#### **์ƒํ’ˆ ๋ฐ์ดํ„ฐ ์บ์‹ฑ ๋ฐ ์—…๋ฐ์ดํŠธ** +- [ ] React Query์˜ ์บ์‹ฑ ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ ์‹œ๊ฐ„์„ ์ตœ์†Œํ™”ํ•ฉ๋‹ˆ๋‹ค. +- [ ] ์ƒํ’ˆ ๋ชฉ๋ก ํŽ˜์ด์ง€์—์„œ ๋ฐ์ดํ„ฐ์˜ ์‹ค์‹œ๊ฐ„ ์—…๋ฐ์ดํŠธ๋ฅผ ์œ„ํ•ด ์ ์ ˆํ•œ Query Refresh ์„ค์ •์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค. diff --git a/sprint9/components/ArticleDetail/ArticleInfo.jsx b/sprint9/components/ArticleDetail/ArticleInfo.jsx new file mode 100644 index 000000000..801cb0085 --- /dev/null +++ b/sprint9/components/ArticleDetail/ArticleInfo.jsx @@ -0,0 +1,76 @@ +import { useState } from "react"; +import Image from "next/image"; +import styles from "@/styles/components/ArticleDetail/ArticleInfo.module.css"; +import formatDate from '@/lib/formatDate'; +import EditDeletMenu from "@/components/ArticleDetail/EditDeletMenu"; + +function ArticleInfo({ article }) { + const [toggleMenu, setToggleMenu] = useState(false); + const [articleEditDelete, setArticleEditDelete] = useState(false); + + return ( +
+
+

{article.title}

+
{ + setToggleMenu(!toggleMenu) + setArticleEditDelete(!articleEditDelete) + }} + className={styles.togleMenuMark} + >โ‹ฎ
+ {toggleMenu ? : null} +
+
+
+
+ ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ +
+
์ด๋ช…ํ•œํŒ๋‹ค
+
+ {formatDate(article.createdAt)} +
+
+
+
+
+ ํ•˜ํŠธ ์ด๋ฏธ์ง€ +
+

+ ❤️ +

+
{article.likes}
+
+
+
+
+

+ {article.content} +

+
+
+ ); +} + +export default ArticleInfo; diff --git a/sprint9/components/ArticleDetail/CommentPost.jsx b/sprint9/components/ArticleDetail/CommentPost.jsx new file mode 100644 index 000000000..ada2382e5 --- /dev/null +++ b/sprint9/components/ArticleDetail/CommentPost.jsx @@ -0,0 +1,34 @@ +import { useState } from "react"; +import styles from "@/styles/components/ArticleDetail/CommentPost.module.css"; +import { postComment } from "@/lib/pandaMarketApiService"; +import useComment from "@/hooks/useComment"; + +function CommentPost({ handlePostComment, setTextareaValue, textareaValue }) { + + + return ( +
+

๋Œ“๊ธ€๋‹ฌ๊ธฐ

+