From af2684c051b783378c732eb2df86451e8b359efa Mon Sep 17 00:00:00 2001 From: ajin Date: Fri, 10 Jan 2025 19:51:59 +0900 Subject: [PATCH 01/18] =?UTF-8?q?Chore:=20shadcn=20Calendar=20=EB=B2=84?= =?UTF-8?q?=EC=A0=84=20=EC=97=85=EA=B7=B8=EB=A0=88=EC=9D=B4=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 162 +++++++++++----- package.json | 4 +- src/components/ui/calendar.tsx | 325 ++++----------------------------- 3 files changed, 155 insertions(+), 336 deletions(-) diff --git a/package-lock.json b/package-lock.json index 733ed6f7..9165dd9c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "@radix-ui/react-label": "^2.1.0", "@radix-ui/react-radio-group": "^1.2.0", "@radix-ui/react-select": "^2.1.1", - "@radix-ui/react-slot": "^1.1.0", + "@radix-ui/react-slot": "^1.1.1", "@radix-ui/react-tabs": "^1.1.0", "@radix-ui/react-toast": "^1.2.4", "@tanstack/react-query": "^5.51.21", @@ -36,7 +36,7 @@ "next": "^14.2.21", "next-safe-action": "^7.4.0", "react": "^18", - "react-day-picker": "^9.0.8", + "react-day-picker": "^8.10.1", "react-dom": "^18", "react-hook-form": "^7.52.1", "swagger-typescript-api": "^13.0.23", @@ -473,12 +473,6 @@ "react-dom": "^18.0 || ^19.0 || >= 19.0.0-rc" } }, - "node_modules/@date-fns/tz": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@date-fns/tz/-/tz-1.2.0.tgz", - "integrity": "sha512-LBrd7MiJZ9McsOgxqWX7AaxrDjcFVjWH/tIKJd7pnR7McaslGYOP1QmmiBXdJH/H/yLCT+rcQ7FaPBUxRGUtrg==", - "license": "MIT" - }, "node_modules/@emoji-mart/data": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@emoji-mart/data/-/data-1.2.1.tgz", @@ -1281,6 +1275,24 @@ } } }, + "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-compose-refs": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", @@ -1347,6 +1359,24 @@ } } }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-direction": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", @@ -1550,6 +1580,25 @@ } } }, + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-popper": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz", @@ -1668,6 +1717,24 @@ } } }, + "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-radio-group": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.2.1.tgz", @@ -1789,7 +1856,7 @@ } } }, - "node_modules/@radix-ui/react-slot": { + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", @@ -1807,6 +1874,39 @@ } } }, + "node_modules/@radix-ui/react-slot": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz", + "integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", + "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-tabs": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.1.tgz", @@ -2016,24 +2116,6 @@ } } }, - "node_modules/@radix-ui/react-toast/node_modules/@radix-ui/react-slot": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz", - "integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/@radix-ui/react-toast/node_modules/@radix-ui/react-visually-hidden": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.1.tgz", @@ -9811,33 +9893,17 @@ } }, "node_modules/react-day-picker": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-9.4.1.tgz", - "integrity": "sha512-eyNjKQ2lFHby42K2itlMNMSpp6+A5m+wbXB31xFaufnplpam274AZ1G2NuBjhnyiehpS+4gJZVILJN54e9Xvhw==", + "version": "8.10.1", + "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-8.10.1.tgz", + "integrity": "sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA==", "license": "MIT", - "dependencies": { - "@date-fns/tz": "^1.2.0", - "date-fns": "^4.1.0" - }, - "engines": { - "node": ">=18" - }, "funding": { "type": "individual", "url": "https://github.com/sponsors/gpbl" }, "peerDependencies": { - "react": ">=16.8.0" - } - }, - "node_modules/react-day-picker/node_modules/date-fns": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", - "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/kossnocorp" + "date-fns": "^2.28.0 || ^3.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, "node_modules/react-dom": { diff --git a/package.json b/package.json index 580eebfe..9f39e7c5 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "@radix-ui/react-label": "^2.1.0", "@radix-ui/react-radio-group": "^1.2.0", "@radix-ui/react-select": "^2.1.1", - "@radix-ui/react-slot": "^1.1.0", + "@radix-ui/react-slot": "^1.1.1", "@radix-ui/react-tabs": "^1.1.0", "@radix-ui/react-toast": "^1.2.4", "@tanstack/react-query": "^5.51.21", @@ -38,7 +38,7 @@ "next": "^14.2.21", "next-safe-action": "^7.4.0", "react": "^18", - "react-day-picker": "^9.0.8", + "react-day-picker": "^8.10.1", "react-dom": "^18", "react-hook-form": "^7.52.1", "swagger-typescript-api": "^13.0.23", diff --git a/src/components/ui/calendar.tsx b/src/components/ui/calendar.tsx index 1fed0117..4f5f8757 100644 --- a/src/components/ui/calendar.tsx +++ b/src/components/ui/calendar.tsx @@ -1,316 +1,69 @@ 'use client' import * as React from 'react' -import { - DayPicker, - labelNext, - labelPrevious, - useDayPicker, -} from 'react-day-picker' +import { DayPicker } from 'react-day-picker' import { ChevronLeftIcon, ChevronRightIcon } from '@radix-ui/react-icons' -import { differenceInCalendarDays } from 'date-fns' +import { buttonVariants } from '@/components/ui/button' import { cn } from '@/lib/utils' -import { Button, buttonVariants } from './button' - -export type CalendarProps = React.ComponentProps & { - /** - * In the year view, the number of years to display at once. - * @default 12 - */ - yearRange?: number - /** - * Wether to let user switch between months and years view. - * @default false - */ - showYearSwitcher?: boolean -} +export type CalendarProps = React.ComponentProps function Calendar({ className, classNames, showOutsideDays = true, - yearRange = 12, - showYearSwitcher = false, - numberOfMonths, ...props }: CalendarProps) { - const [navView, setNavView] = React.useState<'days' | 'years'>('days') - const [displayYears, setDisplayYears] = React.useState<{ - from: number - to: number - }>( - React.useMemo(() => { - const currentYear = new Date().getFullYear() - return { - from: currentYear - Math.floor(yearRange / 2 - 1), - to: currentYear + Math.ceil(yearRange / 2), - } - }, [yearRange]), - ) - - const { onNextClick, onPrevClick, startMonth, endMonth } = props - - const columnsDisplayed = navView === 'years' ? 1 : numberOfMonths - return ( .day-range-end)]:rounded-r-md [&:has(>.day-range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md' + : '[&:has([aria-selected])]:rounded-md', ), - nav: 'flex items-start', - month_grid: 'm-1', - week: 'mt-2 flex w-full', - day: 'flex size-8 flex-1 items-center justify-center rounded-md p-0 text-sm [&:has(button)]:hover:!bg-accent [&:has(button)]:hover:text-accent-foreground [&:has(button)]:hover:aria-selected:!bg-primary [&:has(button)]:hover:aria-selected:text-primary-foreground', - day_button: cn( + day: cn( buttonVariants({ variant: 'ghost' }), - 'h-8 w-8 p-0 font-normal transition-none hover:bg-transparent hover:text-inherit aria-selected:opacity-100', + 'h-8 w-8 p-0 font-normal aria-selected:opacity-100', ), - range_start: 'day-range-start rounded-s-md', - range_end: 'day-range-end rounded-e-md', - selected: - 'bg-primary text-primary-foreground hover:!bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground', - today: 'bg-accent text-accent-foreground', - outside: - 'day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30', - disabled: 'text-muted-foreground opacity-50', - range_middle: - 'rounded-none aria-selected:bg-accent aria-selected:text-accent-foreground hover:aria-selected:!bg-accent hover:aria-selected:text-accent-foreground hover:rounded-md', - hidden: 'invisible hidden', + day_range_start: 'day-range-start', + day_range_end: 'day-range-end', + day_selected: + 'bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground', + day_today: 'bg-accent text-accent-foreground', + day_outside: + 'day-outside text-muted-foreground aria-selected:bg-accent/50 aria-selected:text-muted-foreground', + day_disabled: 'text-muted-foreground opacity-50', + day_range_middle: + 'aria-selected:bg-accent aria-selected:text-accent-foreground', + day_hidden: 'invisible', ...classNames, }} components={{ - Chevron: ({ orientation }) => { - const Icon = - orientation === 'left' ? ChevronLeftIcon : ChevronRightIcon - return - }, - Nav: ({ className, ...props }) => { - const { nextMonth, previousMonth, goToMonth } = useDayPicker() - - const isPreviousDisabled = (() => { - if (navView === 'years') { - return ( - (startMonth && - differenceInCalendarDays( - new Date(displayYears.from - 1, 0, 1), - startMonth, - ) < 0) || - (endMonth && - differenceInCalendarDays( - new Date(displayYears.from - 1, 0, 1), - endMonth, - ) > 0) - ) - } - return !previousMonth - })() - - const isNextDisabled = (() => { - if (navView === 'years') { - return ( - (startMonth && - differenceInCalendarDays( - new Date(displayYears.to + 1, 0, 1), - startMonth, - ) < 0) || - (endMonth && - differenceInCalendarDays( - new Date(displayYears.to + 1, 0, 1), - endMonth, - ) > 0) - ) - } - return !nextMonth - })() - - const handlePreviousClick = React.useCallback(() => { - if (!previousMonth) return - if (navView === 'years') { - setDisplayYears((prev) => ({ - from: prev.from - (prev.to - prev.from + 1), - to: prev.to - (prev.to - prev.from + 1), - })) - onPrevClick?.( - new Date( - displayYears.from - (displayYears.to - displayYears.from), - 0, - 1, - ), - ) - return - } - goToMonth(previousMonth) - onPrevClick?.(previousMonth) - }, [previousMonth, goToMonth]) - - const handleNextClick = React.useCallback(() => { - if (!nextMonth) return - if (navView === 'years') { - setDisplayYears((prev) => ({ - from: prev.from + (prev.to - prev.from + 1), - to: prev.to + (prev.to - prev.from + 1), - })) - onNextClick?.( - new Date( - displayYears.from + (displayYears.to - displayYears.from), - 0, - 1, - ), - ) - return - } - goToMonth(nextMonth) - onNextClick?.(nextMonth) - }, [goToMonth, nextMonth]) - return ( - - ) - }, - CaptionLabel: ({ children, ...props }) => { - if (!showYearSwitcher) return {children} - - return ( - - ) - }, - MonthGrid: ({ className, children, ...props }) => { - const { goToMonth } = useDayPicker() - if (navView === 'years') { - return ( -
- {Array.from( - { length: displayYears.to - displayYears.from + 1 }, - (_, i) => { - const isBefore = - differenceInCalendarDays( - new Date(displayYears.from + i, 12, 31), - startMonth!, - ) < 0 - - const isAfter = - differenceInCalendarDays( - new Date(displayYears.from + i, 0, 0), - endMonth!, - ) > 0 - - const isDisabled = isBefore || isAfter - return ( - - ) - }, - )} -
- ) - } - return ( - - {children} -
- ) - }, + IconLeft: () => , + IconRight: () => , }} - numberOfMonths={ - // we need to override the number of months if we are in years view to 1 - columnsDisplayed - } {...props} /> ) From c240c40ea37c7cabc76dab5bf19e8e39796e57b7 Mon Sep 17 00:00:00 2001 From: ajin Date: Fri, 10 Jan 2025 19:52:30 +0900 Subject: [PATCH 02/18] =?UTF-8?q?Chore:=20.gitignore=EC=97=90=20models=20?= =?UTF-8?q?=ED=8F=B4=EB=8D=94=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index bce9269b..f7e9b8c7 100644 --- a/.gitignore +++ b/.gitignore @@ -32,4 +32,7 @@ yarn-error.log* # typescript *.tsbuildinfo -next-env.d.ts \ No newline at end of file +next-env.d.ts + +# api docs +/src/models \ No newline at end of file From b8cf9a9e491d319aa184dfede75f585d00c3727e Mon Sep 17 00:00:00 2001 From: ajin Date: Fri, 10 Jan 2025 20:03:18 +0900 Subject: [PATCH 03/18] =?UTF-8?q?Rename:=20ActivityDateDialog=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=9C=84=EC=B9=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_components}/ActivityDateDialog.tsx | 41 +++++++++++-------- .../_components}/TriggerButton.tsx | 0 .../create-post/_components/form/Form.tsx | 1 - .../notice/create-post/_components/Form.tsx | 1 - .../activity-date-dialog/index.ts | 1 - .../trigger-button/index.ts | 1 - 6 files changed, 25 insertions(+), 20 deletions(-) rename src/{components/feature/post/create-post-form/activity-date-dialog => app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components}/ActivityDateDialog.tsx (68%) rename src/{components/feature/post/create-post-form/activity-date-dialog/trigger-button => app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components}/TriggerButton.tsx (100%) delete mode 100644 src/components/feature/post/create-post-form/activity-date-dialog/index.ts delete mode 100644 src/components/feature/post/create-post-form/activity-date-dialog/trigger-button/index.ts diff --git a/src/components/feature/post/create-post-form/activity-date-dialog/ActivityDateDialog.tsx b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/ActivityDateDialog.tsx similarity index 68% rename from src/components/feature/post/create-post-form/activity-date-dialog/ActivityDateDialog.tsx rename to src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/ActivityDateDialog.tsx index 12f332f2..f8ea6f1b 100644 --- a/src/components/feature/post/create-post-form/activity-date-dialog/ActivityDateDialog.tsx +++ b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/ActivityDateDialog.tsx @@ -4,7 +4,7 @@ import { useState } from 'react' import { DateRange } from 'react-day-picker' import { useFormContext } from 'react-hook-form' -import { getDateDistance } from '@toss/date' +import { getDateDistance, kstFormat } from '@toss/date' import { Button, @@ -23,20 +23,34 @@ import { } from '@/components/ui' import { CreateActivityPost } from '@/schema/post' -import { DateDialogTriggerButton } from './trigger-button' +import { DateDialogTriggerButton } from './TriggerButton' export const ActivityDateFieldDialog = () => { - const { control, setValue } = useFormContext() + const { control, setValue, getValues } = useFormContext() const [date, setDate] = useState({ from: undefined, to: undefined, }) + const onSelectCalendar = (from?: Date, to?: Date) => { + if (from) { + setValue('postActivityStartDate', kstFormat(from, 'yyyy-LL-dd')) + } + if (from && to) { + setValue( + 'postActivityEndDate', + getDateDistance(from, to).days === 0 ? '' : kstFormat(to, 'yyyy-LL-dd'), + ) + } else { + setValue('postActivityEndDate', '') + } + } + return ( (
@@ -44,8 +58,12 @@ export const ActivityDateFieldDialog = () => {
@@ -56,20 +74,11 @@ export const ActivityDateFieldDialog = () => {
{ setDate(range) - setValue('activityDate', { - start: range?.from, - end: - range?.from && - range?.to && - getDateDistance(range.from, range.to).days === 0 - ? undefined - : range?.to, - }) + onSelectCalendar(range?.from, range?.to) }} />
diff --git a/src/components/feature/post/create-post-form/activity-date-dialog/trigger-button/TriggerButton.tsx b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/TriggerButton.tsx similarity index 100% rename from src/components/feature/post/create-post-form/activity-date-dialog/trigger-button/TriggerButton.tsx rename to src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/TriggerButton.tsx diff --git a/src/app/(main)/event/board/create-post/_components/form/Form.tsx b/src/app/(main)/event/board/create-post/_components/form/Form.tsx index 925a71b1..224e18d0 100644 --- a/src/app/(main)/event/board/create-post/_components/form/Form.tsx +++ b/src/app/(main)/event/board/create-post/_components/form/Form.tsx @@ -21,7 +21,6 @@ export const CreateEventPostForm = () => { form={form} onSubmit={() => {}} isExecuting={false} - isActivityDateRequired={false} isImageRequired={false} /> ) diff --git a/src/app/(main)/notice/create-post/_components/Form.tsx b/src/app/(main)/notice/create-post/_components/Form.tsx index 95e97869..bd78f1cf 100644 --- a/src/app/(main)/notice/create-post/_components/Form.tsx +++ b/src/app/(main)/notice/create-post/_components/Form.tsx @@ -48,7 +48,6 @@ export const CreateNoticePostForm = () => { form={form} onSubmit={(values) => addNoticePost({ data: values })} isExecuting={isPending} - isActivityDateRequired={false} isImageRequired={false} /> ) diff --git a/src/components/feature/post/create-post-form/activity-date-dialog/index.ts b/src/components/feature/post/create-post-form/activity-date-dialog/index.ts deleted file mode 100644 index 84fdaa11..00000000 --- a/src/components/feature/post/create-post-form/activity-date-dialog/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { ActivityDateFieldDialog } from './ActivityDateDialog' diff --git a/src/components/feature/post/create-post-form/activity-date-dialog/trigger-button/index.ts b/src/components/feature/post/create-post-form/activity-date-dialog/trigger-button/index.ts deleted file mode 100644 index 2cb21d42..00000000 --- a/src/components/feature/post/create-post-form/activity-date-dialog/trigger-button/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { DateDialogTriggerButton } from './TriggerButton' From 33c70b7f4428229e14d2c6107ec6498228f2c770 Mon Sep 17 00:00:00 2001 From: ajin Date: Fri, 10 Jan 2025 20:10:21 +0900 Subject: [PATCH 04/18] =?UTF-8?q?Rename:=20activity=20create=20post=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../create-post/_components/PostForm.tsx | 66 ----------- .../create-post/_components/form/Form.tsx | 106 ++++++++++++++++++ .../date-field-dialog/DateFieldDialog.tsx} | 0 .../date-field-dialog}/TriggerButton.tsx | 0 .../form/date-field-dialog/index.ts | 1 + .../create-post/_components/form/index.ts | 1 + .../_components/{ => hero}/Hero.tsx | 0 .../create-post/_components/hero/index.ts | 1 + .../create-post/_components/index.ts | 4 +- 9 files changed, 111 insertions(+), 68 deletions(-) delete mode 100644 src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/PostForm.tsx create mode 100644 src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/form/Form.tsx rename src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/{ActivityDateDialog.tsx => form/date-field-dialog/DateFieldDialog.tsx} (100%) rename src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/{ => form/date-field-dialog}/TriggerButton.tsx (100%) create mode 100644 src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/form/date-field-dialog/index.ts create mode 100644 src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/form/index.ts rename src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/{ => hero}/Hero.tsx (100%) create mode 100644 src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/hero/index.ts diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/PostForm.tsx b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/PostForm.tsx deleted file mode 100644 index b8dc3c67..00000000 --- a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/PostForm.tsx +++ /dev/null @@ -1,66 +0,0 @@ -'use client' - -import { useForm } from 'react-hook-form' - -import { zodResolver } from '@hookform/resolvers/zod' -import { useMutation } from '@tanstack/react-query' -import { usePathname, useRouter } from 'next/navigation' - -import { CreatePostForm } from '@/components/feature' -import { useToast } from '@/components/ui' -import { queryClient } from '@/lib/query-client' -import { CreateActivityPost, CreateActivityPostSchema } from '@/schema/post' -import { activityPostQuries, addActivityPostApi } from '@/service/api' - -type CreateActivityPostFormProps = { - boardId: number -} - -export const CreateActivityPostForm = ({ - boardId, -}: CreateActivityPostFormProps) => { - const { toast } = useToast() - const router = useRouter() - const pathName = usePathname() - - const { mutate: addActivityPost, isPending } = useMutation({ - mutationFn: addActivityPostApi, - onSuccess: (data) => onSuccess(data.message), - }) - - const form = useForm({ - resolver: zodResolver(CreateActivityPostSchema), - defaultValues: { - postTitle: '', - postContent: '', - activityDate: { - start: undefined, - end: undefined, - }, - postType: 'ACTIVITY', - }, - }) - - const onSuccess = (message?: string) => { - toast({ - title: message, - duration: 2000, - }) - - queryClient.invalidateQueries({ - queryKey: activityPostQuries.board(boardId), - }) - - const basePath = pathName.split('/').slice(0, -1).join('/') - router.push(basePath) - } - - return ( - addActivityPost({ boardId, data: values })} - isExecuting={isPending} - isImageRequired={false} - /> - ) -} diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/form/Form.tsx b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/form/Form.tsx new file mode 100644 index 00000000..f77ab862 --- /dev/null +++ b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/form/Form.tsx @@ -0,0 +1,106 @@ +'use client' + +import { useForm } from 'react-hook-form' + +import { zodResolver } from '@hookform/resolvers/zod' +import { useMutation } from '@tanstack/react-query' +import { usePathname, useRouter } from 'next/navigation' + +import { PostContentFieldEditor } from '@/components/feature/post/create-post-form/editor' +import { + Button, + Form, + FormControl, + FormField, + FormItem, + FormMessage, + Input, + Label, + Separator, + useToast, +} from '@/components/ui' +import { queryClient } from '@/lib/query-client' +import { CreateActivityPost, CreateActivityPostSchema } from '@/schema/post' +import { activityPostQuries, addActivityPostApi } from '@/service/api' + +import { ActivityDateFieldDialog } from './date-field-dialog' + +type CreateActivityPostFormProps = { + boardId: number +} + +export const CreateActivityPostForm = ({ + boardId, +}: CreateActivityPostFormProps) => { + const { toast } = useToast() + const router = useRouter() + const pathName = usePathname() + + const { mutate: addActivityPost, isPending } = useMutation({ + mutationFn: addActivityPostApi, + onSuccess: (data) => onSuccess(data.message), + }) + + const form = useForm({ + resolver: zodResolver(CreateActivityPostSchema), + defaultValues: { + postTitle: '', + postContent: '', + postImageIds: [], + postActivityStartDate: '', + postActivityEndDate: '', + }, + }) + + const onSuccess = (message?: string) => { + toast({ + title: message, + duration: 2000, + }) + + queryClient.invalidateQueries({ + queryKey: activityPostQuries.board(boardId), + }) + + const basePath = pathName.split('/').slice(0, -1).join('/') + router.push(basePath) + } + + return ( +
+ + addActivityPost({ boardId, data: values }), + )} + className="flex flex-col gap-4" + > + ( + +
+ + + + +
+
+ +
+
+ )} + /> + + +
게시글 내용 작성하기
+ +
+ +
+ + + ) +} diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/ActivityDateDialog.tsx b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/form/date-field-dialog/DateFieldDialog.tsx similarity index 100% rename from src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/ActivityDateDialog.tsx rename to src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/form/date-field-dialog/DateFieldDialog.tsx diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/TriggerButton.tsx b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/form/date-field-dialog/TriggerButton.tsx similarity index 100% rename from src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/TriggerButton.tsx rename to src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/form/date-field-dialog/TriggerButton.tsx diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/form/date-field-dialog/index.ts b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/form/date-field-dialog/index.ts new file mode 100644 index 00000000..7dd3b4b9 --- /dev/null +++ b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/form/date-field-dialog/index.ts @@ -0,0 +1 @@ +export { ActivityDateFieldDialog } from './DateFieldDialog' diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/form/index.ts b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/form/index.ts new file mode 100644 index 00000000..a9519c38 --- /dev/null +++ b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/form/index.ts @@ -0,0 +1 @@ +export { CreateActivityPostForm } from './Form' diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/Hero.tsx b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/hero/Hero.tsx similarity index 100% rename from src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/Hero.tsx rename to src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/hero/Hero.tsx diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/hero/index.ts b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/hero/index.ts new file mode 100644 index 00000000..ae2774b6 --- /dev/null +++ b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/hero/index.ts @@ -0,0 +1 @@ +export { CreateActivityPostHero } from './Hero' diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/index.ts b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/index.ts index 1ec867f3..9a7a553c 100644 --- a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/index.ts +++ b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/index.ts @@ -1,2 +1,2 @@ -export { CreateActivityPostHero } from './Hero' -export { CreateActivityPostForm } from './PostForm' +export * from './hero' +export * from './form' From edb30cebf0a63f250a0ad83c9f7c508b5fc1e7c8 Mon Sep 17 00:00:00 2001 From: ajin Date: Fri, 10 Jan 2025 20:11:08 +0900 Subject: [PATCH 05/18] =?UTF-8?q?Refactor(activity):=20=ED=99=9C=EB=8F=99?= =?UTF-8?q?=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EC=83=9D=EC=84=B1=ED=95=98?= =?UTF-8?q?=EA=B8=B0=20request=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/create-post-form/CreatePostForm.tsx | 5 --- src/schema/post.ts | 14 +++----- src/service/api/post/activity.ts | 2 +- src/service/models/Boards.ts | 17 ++++----- src/service/models/data-contracts.ts | 36 +++++++++++++++++-- 5 files changed, 49 insertions(+), 25 deletions(-) diff --git a/src/components/feature/post/create-post-form/CreatePostForm.tsx b/src/components/feature/post/create-post-form/CreatePostForm.tsx index 74d18828..beb756f7 100644 --- a/src/components/feature/post/create-post-form/CreatePostForm.tsx +++ b/src/components/feature/post/create-post-form/CreatePostForm.tsx @@ -9,8 +9,6 @@ import dynamic from 'next/dynamic' import { ImageInput, PostFormField } from '@/components/feature' import { Button, Form, Input, Separator, Skeleton } from '@/components/ui' -import { ActivityDateFieldDialog } from './activity-date-dialog' - const PostContentFieldEditor = dynamic(() => import('./editor/EditorField'), { ssr: false, loading: () => , @@ -20,7 +18,6 @@ type CreatePostFormProps = { form: UseFormReturn onSubmit: (values: T) => void isExecuting: boolean - isActivityDateRequired?: boolean isImageRequired?: boolean } @@ -28,7 +25,6 @@ export const CreatePostForm = ({ form, onSubmit, isExecuting, - isActivityDateRequired = true, isImageRequired = true, }: CreatePostFormProps) => { return ( @@ -40,7 +36,6 @@ export const CreatePostForm = ({ {(field: ControllerRenderProps) => } - {isActivityDateRequired && }
게시글 내용 작성하기
diff --git a/src/schema/post.ts b/src/schema/post.ts index f0871325..36d8ee34 100644 --- a/src/schema/post.ts +++ b/src/schema/post.ts @@ -8,15 +8,11 @@ export const CreateActivityPostSchema = z.object({ .min(1, { message: '게시글 제목을 입력해주세요.' }) .max(50, { message: '게시글 제목은 50자 이내여야 합니다.' }), postContent: z.string().min(1, { message: '게시글 내용을 입력해주세요.' }), - activityDate: z - .object({ - start: z.date().optional(), - end: z.date().optional(), - }) - .refine((date) => { - return !!date.start - }, '활동 날짜를 선택해주세요.'), - postType: z.enum(['ACTIVITY', 'NOTICE']), + postImageIds: z.number().array(), + postActivityStartDate: z.string().refine((date) => date !== undefined, { + message: '활동 날짜를 선택해주세요.', + }), + postActivityEndDate: z.string(), }) export type CreateActivityPost = z.infer diff --git a/src/service/api/post/activity.ts b/src/service/api/post/activity.ts index d531990a..6b2d4992 100644 --- a/src/service/api/post/activity.ts +++ b/src/service/api/post/activity.ts @@ -81,7 +81,7 @@ export const addActivityPostApi = async ({ data, }: AddActivityPostRequest) => { const postClient = new Boards(AUTHORIZATION_API) - const response = await postClient.addPost(boardId, data) + const response = await postClient.registerPostWithBoard(boardId, data) return response.data } diff --git a/src/service/models/Boards.ts b/src/service/models/Boards.ts index 3cf3ebe5..b5de4a08 100644 --- a/src/service/models/Boards.ts +++ b/src/service/models/Boards.ts @@ -12,10 +12,10 @@ */ import { CustomHttpClient } from '../config' import { - AddPostData, - CreatePostRequestDto, DeletePostData, GetActivityPosts1Data, + PostWithBoardRequestDto, + RegisterPostWithBoardData, } from './data-contracts' import { ContentType, RequestParams } from './http-client' @@ -62,21 +62,21 @@ export class Boards< * No description * * @tags 게시글 API - * @name AddPost + * @name RegisterPostWithBoard * @summary 활동 게시글 생성 * @request POST:/boards/{boardId}/posts * @secure - * @response `200` `AddPostData` OK + * @response `200` `RegisterPostWithBoardData` OK * @response `201` `void` - * @response `400` `void` + * @response `401` `void` * @response `404` `void` */ - addPost = ( + registerPostWithBoard = ( boardId: number, - data: CreatePostRequestDto, + data: PostWithBoardRequestDto, params: RequestParams = {}, ) => - this.request({ + this.request({ path: `/boards/${boardId}/posts`, method: 'POST', body: data, @@ -84,6 +84,7 @@ export class Boards< type: ContentType.Json, ...params, }) + /** * No description * diff --git a/src/service/models/data-contracts.ts b/src/service/models/data-contracts.ts index 296f08b8..aea86f21 100644 --- a/src/service/models/data-contracts.ts +++ b/src/service/models/data-contracts.ts @@ -61,6 +61,38 @@ export interface BoardRequestDto { participants: string[] } +export interface PostWithBoardRequestDto { + /** + * 게시글 이름 + * @minLength 1 + * @maxLength 50 + * @example "게시글1" + */ + postTitle?: string + /** + * @minLength 1 + * @maxLength 200000 + */ + postContent?: string + /** + * 게시글 이미지 ID + * @example [1,2] + */ + postImageIds?: number[] + /** + * 활동 시작일 + * @format date + * @example "2024-07-24" + */ + postActivityStartDate: string + /** + * 활동 종료일 (생략 가능) + * @format date + * @example "2024-07-24" + */ + postActivityEndDate?: string +} + export interface CreatePostRequestDto { /** * 게시글 이름 @@ -572,7 +604,7 @@ export type CommonErrorCodeDefinitionData = any export type GetActivityPosts1Data = PagePostSummaryResponseDto -export type AddPostData = SuccessResponse +export type RegisterPostWithBoardData = SuccessResponse export type RegisterSemesterData = SuccessResponse @@ -732,7 +764,7 @@ export interface DeleteActivityPostRequest { export interface AddActivityPostRequest { boardId: number - data: CreatePostRequestDto + data: PostWithBoardRequestDto } export interface GetPostDetailRequest { From 9fbd3f3ac27937e336c448615ea5f7fc946602a3 Mon Sep 17 00:00:00 2001 From: ajin Date: Fri, 10 Jan 2025 20:28:08 +0900 Subject: [PATCH 06/18] =?UTF-8?q?Rename:=20=ED=99=9C=EB=8F=99=20=EA=B2=8C?= =?UTF-8?q?=EC=8B=9C=EA=B8=80=20=EA=B4=80=EB=A0=A8=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EA=B5=AC=EC=A1=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../[boardId]/_components/BoardHero.tsx | 17 +++++++++---- .../[boardId]/_components/CreateButton.tsx | 2 +- .../boards/[boardId]/_components/PostList.tsx | 8 +++++-- src/components/feature/skeleton/BoardHero.tsx | 24 ------------------- src/components/feature/skeleton/index.ts | 1 - 5 files changed, 19 insertions(+), 33 deletions(-) delete mode 100644 src/components/feature/skeleton/BoardHero.tsx diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/_components/BoardHero.tsx b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/_components/BoardHero.tsx index 27784b32..b99b6a22 100644 --- a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/_components/BoardHero.tsx +++ b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/_components/BoardHero.tsx @@ -1,11 +1,7 @@ import { useMutation, useQuery } from '@tanstack/react-query' import { usePathname, useRouter } from 'next/navigation' -import { - ActivityBreadcrumb, - BoardHeroSkeleton, - NameLabel, -} from '@/components/feature' +import { ActivityBreadcrumb, NameLabel } from '@/components/feature' import { Button, Separator, useToast } from '@/components/ui' import { DATA_ERROR_MESSAGES } from '@/constant/errorMessage' import { queryClient } from '@/lib/query-client' @@ -81,3 +77,14 @@ export const BoardHero = ({ boardId, activityId }: BoardHeroProps) => {
) } + +export const BoardHeroSkeleton = () => { + return ( +
+ +
+
+ +
+ ) +} diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/_components/CreateButton.tsx b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/_components/CreateButton.tsx index 17d20963..69abce0c 100644 --- a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/_components/CreateButton.tsx +++ b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/_components/CreateButton.tsx @@ -10,7 +10,7 @@ export const CreatePostButton = () => { const pathName = usePathname() const router = useRouter() - const { role } = useMyInfoStore.getState().myInfo + const { role } = useMyInfoStore((state) => state.myInfo) return (
diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/_components/PostList.tsx b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/_components/PostList.tsx index 596bf479..262a606d 100644 --- a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/_components/PostList.tsx +++ b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/_components/PostList.tsx @@ -1,7 +1,7 @@ import { useQuery } from '@tanstack/react-query' import { useSearchParams } from 'next/navigation' -import { PaginationButtons } from '@/components/common' +import { PaginationButtons, Spinner } from '@/components/common' import { PostTable } from '@/components/feature' import { DATA_ERROR_MESSAGES } from '@/constant/errorMessage' import { activityPostQuries } from '@/service/api' @@ -22,7 +22,11 @@ export const ActivityPostListSection = ({ const { data, status } = useQuery(activityPostQuries.list({ boardId, page })) if (status === 'pending') - return
loading...
+ return ( +
+ +
+ ) if (!data) { throw new Error(DATA_ERROR_MESSAGES.POST_NOT_FOUND) diff --git a/src/components/feature/skeleton/BoardHero.tsx b/src/components/feature/skeleton/BoardHero.tsx deleted file mode 100644 index 27911ed1..00000000 --- a/src/components/feature/skeleton/BoardHero.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { ChevronRightIcon } from '@radix-ui/react-icons' - -import { Separator } from '@/components/ui' - -export const BoardHeroSkeleton = () => { - return ( -
- -
-
- -
-
-
-
-
-
-
-
-
- -
- ) -} diff --git a/src/components/feature/skeleton/index.ts b/src/components/feature/skeleton/index.ts index 139af35d..af3bc875 100644 --- a/src/components/feature/skeleton/index.ts +++ b/src/components/feature/skeleton/index.ts @@ -1,4 +1,3 @@ export { AdminSemesterSkeleton } from './Semester' export { BoardSkeleton } from './Board' -export { BoardHeroSkeleton } from './BoardHero' export { AdminSemesterPageSkeleton } from './SemesterPage' From 7b882f5227934d7176567cd297b2f1566ae33093 Mon Sep 17 00:00:00 2001 From: ajin Date: Fri, 10 Jan 2025 20:41:20 +0900 Subject: [PATCH 07/18] =?UTF-8?q?Refactor:=20=EA=B2=8C=EC=8B=9C=EA=B8=80?= =?UTF-8?q?=20=EA=B3=B5=ED=86=B5=20table=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20props=20=20=EC=A0=9C=EB=84=88=EB=A6=AD=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/feature/post/table/TableContent.tsx | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/components/feature/post/table/TableContent.tsx b/src/components/feature/post/table/TableContent.tsx index 90c6f760..f883f172 100644 --- a/src/components/feature/post/table/TableContent.tsx +++ b/src/components/feature/post/table/TableContent.tsx @@ -1,7 +1,5 @@ 'use client' -import { HTMLAttributes } from 'react' - import { flexRender, Table as tanskTable } from '@tanstack/react-table' import Link from 'next/link' import { usePathname } from 'next/navigation' @@ -14,13 +12,12 @@ import { TableHeader, TableRow, } from '@/components/ui' -import { PostSummaryResponseDto } from '@/service/models' -interface PostTableContentProps extends HTMLAttributes { - table: tanskTable +interface TableContentProps { + table: tanskTable } -export function PostTableContent({ table }: PostTableContentProps) { +export function PostTableContent({ table }: TableContentProps) { const pathName = usePathname() return ( From d19501b76e2c92a73398efaa920fa86006273183 Mon Sep 17 00:00:00 2001 From: ajin Date: Fri, 10 Jan 2025 20:43:31 +0900 Subject: [PATCH 08/18] =?UTF-8?q?Refactor(activity):=20=ED=99=9C=EB=8F=99?= =?UTF-8?q?=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20response=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/feature/post/table/Table.tsx | 6 +- src/service/api/post/activity.ts | 8 +-- src/service/models/Boards.ts | 13 ++-- src/service/models/data-contracts.ts | 71 ++++++++++++++++++++- 4 files changed, 82 insertions(+), 16 deletions(-) diff --git a/src/components/feature/post/table/Table.tsx b/src/components/feature/post/table/Table.tsx index 5efab85b..aa4e2c7e 100644 --- a/src/components/feature/post/table/Table.tsx +++ b/src/components/feature/post/table/Table.tsx @@ -6,18 +6,18 @@ import { useReactTable, } from '@tanstack/react-table' -import { PostSummaryResponseDto } from '@/service/models' +import { PostWithBoardSummaryResponseDto } from '@/service/models' import { PostTableContent } from './TableContent' type PostTableProps = { - posts: PostSummaryResponseDto[] + posts: PostWithBoardSummaryResponseDto[] pageNumber: number pageSize: number } export const PostTable = ({ posts, pageNumber, pageSize }: PostTableProps) => { - const columns: ColumnDef[] = [ + const columns: ColumnDef[] = [ { header: '번호', accessorKey: 'postId', diff --git a/src/service/api/post/activity.ts b/src/service/api/post/activity.ts index 6b2d4992..74afa211 100644 --- a/src/service/api/post/activity.ts +++ b/src/service/api/post/activity.ts @@ -9,14 +9,14 @@ import { AddActivityPostRequest, Boards, DeleteActivityPostRequest, - PostSummaryResponseDto, + PostWithBoardSummaryResponseDto, } from '@/service/models' import { Paging } from '@/types/paging' import { PostQuries } from './post' type PostPagingResponse = { - posts: PostSummaryResponseDto[] + posts: PostWithBoardSummaryResponseDto[] } & Paging const activityPostPaging = async ({ @@ -25,13 +25,13 @@ const activityPostPaging = async ({ size = 10, }: ActivityPostPagingRequest): Promise => { const postClient = new Boards(BACKEND_API) - const response = await postClient.getActivityPosts1(boardId, { page, size }) + const response = await postClient.getPostsWithBoard(boardId, { page, size }) const { data } = response const posts = data.content.map((post) => { const formatCreateDate = formatDateDistanceFromToday( - new Date(post.postCreateDate), + new Date(post.postRegDate), ) if (!formatCreateDate) return post diff --git a/src/service/models/Boards.ts b/src/service/models/Boards.ts index b5de4a08..257d2b89 100644 --- a/src/service/models/Boards.ts +++ b/src/service/models/Boards.ts @@ -13,7 +13,7 @@ import { CustomHttpClient } from '../config' import { DeletePostData, - GetActivityPosts1Data, + GetPostsWithBoardData, PostWithBoardRequestDto, RegisterPostWithBoardData, } from './data-contracts' @@ -26,24 +26,21 @@ export class Boards< * No description * * @tags 게시글 API - * @name GetActivityPosts1 + * @name GetPostsWithBoard * @summary 활동 게시글 목록 조회 * @request GET:/boards/{boardId}/posts * @secure - * @response `200` `GetActivityPosts1Data` OK - * @response `404` `void` + * @response `200` `GetPostsWithBoardData` OK */ - getActivityPosts1 = ( + getPostsWithBoard = ( boardId: number, query?: { /** - * 조회 할 page, default: 0 * @format int32 * @default 0 */ page?: number /** - * 한 번에 조회 할 page 수, default: 10 * @format int32 * @default 10 */ @@ -51,7 +48,7 @@ export class Boards< }, params: RequestParams = {}, ) => - this.request({ + this.request({ path: `/boards/${boardId}/posts`, method: 'GET', query: query, diff --git a/src/service/models/data-contracts.ts b/src/service/models/data-contracts.ts index aea86f21..65c71c76 100644 --- a/src/service/models/data-contracts.ts +++ b/src/service/models/data-contracts.ts @@ -378,6 +378,25 @@ export interface PagePostSummaryResponseDto { empty?: boolean } +export interface PagePostWithBoardSummaryResponseDto { + /** @format int32 */ + totalPages: number + /** @format int64 */ + totalElements: number + /** @format int32 */ + size?: number + content: PostWithBoardSummaryResponseDto[] + /** @format int32 */ + number?: number + sort?: SortObject[] + /** @format int32 */ + numberOfElements?: number + pageable: PageableObject + first?: boolean + last?: boolean + empty?: boolean +} + export interface PostSummaryResponseDto { /** * 게시글 id @@ -430,6 +449,56 @@ export interface PostSummaryResponseDto { boardName?: string } +export interface PostWithBoardSummaryResponseDto { + /** + * 게시글 id + * @format int64 + */ + postId: number + /** 게시글 제목 */ + postTitle: string + /** + * 게시글 조회수 + * @format int64 + */ + postViews: number + /** + * 유저 아이디 + * @example "haedal12" + */ + userId: string + /** + * 유저 이름 + * @example "조대성" + */ + userName: string + /** + * 게시글 타입 + * @example "(NOTICE, ACTIVITY)" + */ + postType: 'ACTIVITY' | 'NOTICE' + /** + * 게시글 생성일 + * @format date-time + */ + postRegDate: string + /** + * 게시판 id + * @format int64 + */ + boardId: number + /** + * 활동 시작일 + * @format date + */ + postActivityStartDate: string + /** + * 활동 종료일 + * @format date + */ + postActivityEndDate?: string +} + export interface PostResponseDto { /** * 게시글 id @@ -602,7 +671,7 @@ export type ResisterAdminData = SuccessResponse export type CommonErrorCodeDefinitionData = any -export type GetActivityPosts1Data = PagePostSummaryResponseDto +export type GetPostsWithBoardData = PagePostWithBoardSummaryResponseDto export type RegisterPostWithBoardData = SuccessResponse From 75445910fc86af4d724e5ccd7bf1b4e313c48d1a Mon Sep 17 00:00:00 2001 From: ajin Date: Fri, 10 Jan 2025 21:03:11 +0900 Subject: [PATCH 09/18] =?UTF-8?q?Refactor(activity):=20=ED=99=9C=EB=8F=99?= =?UTF-8?q?=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EB=8B=A8=EC=9D=BC=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20API=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../posts/[postId]/_components/PostDetail.tsx | 6 +- .../boards/[boardId]/posts/[postId]/page.tsx | 7 ++- src/service/api/post/activity.ts | 16 +++++ src/service/models/Boards.ts | 23 +++++++ src/service/models/data-contracts.ts | 61 ++++++++++++++++++- 5 files changed, 107 insertions(+), 6 deletions(-) diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/PostDetail.tsx b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/PostDetail.tsx index dd808633..d976e1ae 100644 --- a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/PostDetail.tsx +++ b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/PostDetail.tsx @@ -5,12 +5,12 @@ import { usePathname, useRouter } from 'next/navigation' import { Button, Separator, useToast } from '@/components/ui' import { queryClient } from '@/lib/query-client' import { activityPostQuries, deleteActivityPostApi } from '@/service/api' -import { PostResponseDto } from '@/service/models' +import { PostWithBoardResponseDto } from '@/service/models' import { useMyInfoStore } from '@/store/myInfo' type ActivityPostDetailProps = { boardId: number - post: PostResponseDto + post: PostWithBoardResponseDto } export const ActivityPostDetail = ({ @@ -62,7 +62,7 @@ export const ActivityPostDetail = ({
{post.userName}
·
- {format(new Date(post.postCreateDate), 'yyyy-MM-dd')} + {format(new Date(post.postRegDate), 'yyyy-MM-dd')}
조회 {post.postViews}
diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/page.tsx b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/page.tsx index f07d83ae..76965205 100644 --- a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/page.tsx +++ b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/page.tsx @@ -5,7 +5,7 @@ import { useQuery, useSuspenseQuery } from '@tanstack/react-query' import { Spinner } from '@/components/common' import { BoardNavigationButton, PostContent } from '@/components/feature' import { DATA_ERROR_MESSAGES } from '@/constant/errorMessage' -import { PostQuries, boardQueries } from '@/service/api' +import { activityPostQuries, boardQueries } from '@/service/api' import { ActivityPostDetail, ActivityPostHero } from './_components' @@ -25,7 +25,10 @@ const PostPage = ({ params }: PostPageParams) => { }), ) const { data: post, status } = useQuery( - PostQuries.detail({ postId: Number(params.postId) }), + activityPostQuries.detail({ + boardId: Number(params.boardId), + postId: Number(params.postId), + }), ) if (!board) throw new Error(DATA_ERROR_MESSAGES.BOARD_DETAIL_NOT_FOUND) diff --git a/src/service/api/post/activity.ts b/src/service/api/post/activity.ts index 74afa211..d77e9fba 100644 --- a/src/service/api/post/activity.ts +++ b/src/service/api/post/activity.ts @@ -9,6 +9,7 @@ import { AddActivityPostRequest, Boards, DeleteActivityPostRequest, + GetActivityPostDetailRequest, PostWithBoardSummaryResponseDto, } from '@/service/models' import { Paging } from '@/types/paging' @@ -56,6 +57,16 @@ const activityPostPaging = async ({ } } +const getActivityPostDetail = async ({ + boardId, + postId, +}: GetActivityPostDetailRequest) => { + const boardClient = new Boards(BACKEND_API) + const response = await boardClient.getPostWithBoard(boardId, postId) + + return response.data +} + export const activityPostQuries = { all: () => [...PostQuries.all(), 'activity'], board: (boardId: number) => [...activityPostQuries.all(), boardId], @@ -64,6 +75,11 @@ export const activityPostQuries = { queryKey: [...activityPostQuries.board(boardId), page], queryFn: async () => activityPostPaging({ boardId, page, size }), }), + detail: ({ boardId, postId }: GetActivityPostDetailRequest) => + queryOptions({ + queryKey: [...activityPostQuries.board(boardId), 'detail'], + queryFn: async () => getActivityPostDetail({ boardId, postId }), + }), } export const deleteActivityPostApi = async ({ diff --git a/src/service/models/Boards.ts b/src/service/models/Boards.ts index 257d2b89..23b33a71 100644 --- a/src/service/models/Boards.ts +++ b/src/service/models/Boards.ts @@ -13,6 +13,7 @@ import { CustomHttpClient } from '../config' import { DeletePostData, + GetPostWithBoardData, GetPostsWithBoardData, PostWithBoardRequestDto, RegisterPostWithBoardData, @@ -22,6 +23,28 @@ import { ContentType, RequestParams } from './http-client' export class Boards< SecurityDataType = unknown, > extends CustomHttpClient { + /** + * No description + * + * @tags 게시글 API + * @name GetPostWithBoard + * @summary 활동 게시글 단일 조회 + * @request GET:/boards/{boardId}/posts/{postId} + * @secure + * @response `200` `GetPostWithBoardData` OK + * @response `404` `void` + */ + getPostWithBoard = ( + boardId: number, + postId: number, + params: RequestParams = {}, + ) => + this.request({ + path: `/boards/${boardId}/posts/${postId}`, + method: 'GET', + secure: true, + ...params, + }) /** * No description * diff --git a/src/service/models/data-contracts.ts b/src/service/models/data-contracts.ts index 65c71c76..27e771d8 100644 --- a/src/service/models/data-contracts.ts +++ b/src/service/models/data-contracts.ts @@ -93,6 +93,58 @@ export interface PostWithBoardRequestDto { postActivityEndDate?: string } +export interface PostWithBoardResponseDto { + /** + * 게시글 id + * @format int64 + */ + postId: number + /** 게시글 제목 */ + postTitle: string + /** 게시글 내용 */ + postContent: string + /** + * 게시글 조회수 + * @format int64 + */ + postViews: number + /** + * 게시글 타입 + * @example "(NOTICE, ACTIVITY)" + */ + postType: 'ACTIVITY' | 'NOTICE' + /** + * 게시글 생성일 + * @format date-time + */ + postRegDate: string + /** + * 유저 아이디 + * @example "haedal12" + */ + userId: string + /** + * 유저 이름 + * @example "조대성" + */ + userName: string + /** + * 게시판 id + * @format int64 + */ + boardId: number + /** + * 활동 시작일 + * @format date + */ + postActivityStartDate?: string + /** + * 활동 종료일 + * @format date + */ + postActivityEndDate?: string +} + export interface CreatePostRequestDto { /** * 게시글 이름 @@ -491,7 +543,7 @@ export interface PostWithBoardSummaryResponseDto { * 활동 시작일 * @format date */ - postActivityStartDate: string + postActivityStartDate?: string /** * 활동 종료일 * @format date @@ -649,6 +701,8 @@ export interface UpdateBoardImagePayload { file: File } +export type GetPostWithBoardData = PostWithBoardResponseDto + export type UpdateBoardImageData = any export type ReissueData = any @@ -840,6 +894,11 @@ export interface GetPostDetailRequest { postId: number } +export interface GetActivityPostDetailRequest { + boardId: number + postId: number +} + export interface GetSemesterRequest { semesterId: number } From 772702931d27a84038b7de875a01e847c44bde2a Mon Sep 17 00:00:00 2001 From: ajin Date: Fri, 10 Jan 2025 21:20:34 +0900 Subject: [PATCH 10/18] =?UTF-8?q?Fix:=20=ED=99=9C=EB=8F=99=20=EA=B2=8C?= =?UTF-8?q?=EC=8B=9C=EA=B8=80=20=EC=83=9D=EC=84=B1=20=ED=9B=84=20=EC=B4=88?= =?UTF-8?q?=EA=B8=B0=ED=99=94=20=ED=95=A0=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20query=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../boards/[boardId]/create-post/_components/form/Form.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/form/Form.tsx b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/form/Form.tsx index f77ab862..d43cbddf 100644 --- a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/form/Form.tsx +++ b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/form/Form.tsx @@ -59,7 +59,7 @@ export const CreateActivityPostForm = ({ }) queryClient.invalidateQueries({ - queryKey: activityPostQuries.board(boardId), + queryKey: activityPostQuries.all(), }) const basePath = pathName.split('/').slice(0, -1).join('/') From b891bd4b0209615fc93725a9ad45b83286030d84 Mon Sep 17 00:00:00 2001 From: ajin Date: Fri, 10 Jan 2025 21:51:18 +0900 Subject: [PATCH 11/18] =?UTF-8?q?Fix:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EA=B3=B5=ED=86=B5=20table=20type=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/feature/post/table/Table.tsx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/components/feature/post/table/Table.tsx b/src/components/feature/post/table/Table.tsx index aa4e2c7e..43566626 100644 --- a/src/components/feature/post/table/Table.tsx +++ b/src/components/feature/post/table/Table.tsx @@ -6,18 +6,23 @@ import { useReactTable, } from '@tanstack/react-table' -import { PostWithBoardSummaryResponseDto } from '@/service/models' +import { + PostSummaryResponseDto, + PostWithBoardSummaryResponseDto, +} from '@/service/models' import { PostTableContent } from './TableContent' type PostTableProps = { - posts: PostWithBoardSummaryResponseDto[] + posts: PostSummaryResponseDto[] | PostWithBoardSummaryResponseDto[] pageNumber: number pageSize: number } export const PostTable = ({ posts, pageNumber, pageSize }: PostTableProps) => { - const columns: ColumnDef[] = [ + const columns: ColumnDef< + PostSummaryResponseDto | PostWithBoardSummaryResponseDto + >[] = [ { header: '번호', accessorKey: 'postId', From 3578f667382acf246b05915744f953dbe8b9ce72 Mon Sep 17 00:00:00 2001 From: ajin Date: Fri, 10 Jan 2025 21:52:10 +0900 Subject: [PATCH 12/18] =?UTF-8?q?Feat:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EC=8B=9C=20=ED=99=95=EC=9D=B8=EC=B0=BD=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../detail/delete-dialog/DeleteDialog.tsx | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/delete-dialog/DeleteDialog.tsx diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/delete-dialog/DeleteDialog.tsx b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/delete-dialog/DeleteDialog.tsx new file mode 100644 index 00000000..54ab522f --- /dev/null +++ b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/delete-dialog/DeleteDialog.tsx @@ -0,0 +1,55 @@ +import { useState } from 'react' + +import { + Button, + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from '@/components/ui' + +interface DeletePostDialogProps { + onClick: () => void + disabled?: boolean +} + +export const DeletePostDialog = ({ + onClick, + disabled, +}: DeletePostDialogProps) => { + const [open, setOpen] = useState(false) + + return ( + + + + + + + + 정말로 게시글을 삭제하시겠습니까? + + + 삭제된 게시글은 복구가 불가합니다. + + + + + + + + + ) +} From 96a149a61255a820a328c6adad41cd2f5962da54 Mon Sep 17 00:00:00 2001 From: ajin Date: Fri, 10 Jan 2025 21:52:36 +0900 Subject: [PATCH 13/18] =?UTF-8?q?Rename(activity):=20=ED=99=9C=EB=8F=99=20?= =?UTF-8?q?=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EB=8B=A8=EC=9D=BC=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EA=B4=80=EB=A0=A8=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EA=B5=AC=EC=A1=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{PostDetail.tsx => detail/Detail.tsx} | 16 +++++++--------- .../_components/detail/delete-dialog/index.ts | 1 + .../posts/[postId]/_components/detail/index.ts | 1 + .../_components/{PostHero.tsx => hero/Hero.tsx} | 0 .../posts/[postId]/_components/hero/index.ts | 1 + .../posts/[postId]/_components/index.ts | 4 ++-- 6 files changed, 12 insertions(+), 11 deletions(-) rename src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/{PostDetail.tsx => detail/Detail.tsx} (86%) create mode 100644 src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/delete-dialog/index.ts create mode 100644 src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/index.ts rename src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/{PostHero.tsx => hero/Hero.tsx} (100%) create mode 100644 src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/hero/index.ts diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/PostDetail.tsx b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/Detail.tsx similarity index 86% rename from src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/PostDetail.tsx rename to src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/Detail.tsx index d976e1ae..eba73b52 100644 --- a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/PostDetail.tsx +++ b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/Detail.tsx @@ -2,12 +2,14 @@ import { useMutation } from '@tanstack/react-query' import { format } from 'date-fns' import { usePathname, useRouter } from 'next/navigation' -import { Button, Separator, useToast } from '@/components/ui' +import { Separator, useToast } from '@/components/ui' import { queryClient } from '@/lib/query-client' import { activityPostQuries, deleteActivityPostApi } from '@/service/api' import { PostWithBoardResponseDto } from '@/service/models' import { useMyInfoStore } from '@/store/myInfo' +import { DeletePostDialog } from './delete-dialog' + type ActivityPostDetailProps = { boardId: number post: PostWithBoardResponseDto @@ -17,7 +19,7 @@ export const ActivityPostDetail = ({ boardId, post, }: ActivityPostDetailProps) => { - const { userName } = useMyInfoStore((state) => state.getMyInfo()) + const { userId } = useMyInfoStore((state) => state.getMyInfo()) const { mutate: deleteActivityPost, isPending } = useMutation({ mutationFn: deleteActivityPostApi, @@ -46,15 +48,11 @@ export const ActivityPostDetail = ({
{post.postTitle}
- {userName === post.userName && ( - + /> )}
diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/delete-dialog/index.ts b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/delete-dialog/index.ts new file mode 100644 index 00000000..0863412b --- /dev/null +++ b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/delete-dialog/index.ts @@ -0,0 +1 @@ +export { DeletePostDialog } from './DeleteDialog' diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/index.ts b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/index.ts new file mode 100644 index 00000000..5413e910 --- /dev/null +++ b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/index.ts @@ -0,0 +1 @@ +export { ActivityPostDetail } from './Detail' diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/PostHero.tsx b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/hero/Hero.tsx similarity index 100% rename from src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/PostHero.tsx rename to src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/hero/Hero.tsx diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/hero/index.ts b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/hero/index.ts new file mode 100644 index 00000000..131427f0 --- /dev/null +++ b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/hero/index.ts @@ -0,0 +1 @@ +export { ActivityPostHero } from './Hero' diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/index.ts b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/index.ts index 51e56595..6fbc2338 100644 --- a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/index.ts +++ b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/index.ts @@ -1,2 +1,2 @@ -export { ActivityPostDetail } from './PostDetail' -export { ActivityPostHero } from './PostHero' +export * from './hero' +export * from './detail' From 22491918258a117cd6c1badb8313965a9267828e Mon Sep 17 00:00:00 2001 From: ajin Date: Fri, 10 Jan 2025 22:31:03 +0900 Subject: [PATCH 14/18] =?UTF-8?q?Refactor(notice):=20=EA=B3=B5=EC=A7=80?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20API=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notice/create-post/_components/Form.tsx | 2 +- .../posts/[postId]/_components/PostDetail.tsx | 6 +- src/app/(main)/notice/posts/[postId]/page.tsx | 4 +- src/components/feature/post/table/Table.tsx | 6 +- src/schema/post.ts | 2 +- src/service/api/post/activity.ts | 4 +- src/service/api/post/index.ts | 1 - src/service/api/post/notice.ts | 40 +++-- src/service/api/post/post.ts | 22 --- src/service/models/Notices.ts | 143 +++++++++++++++ src/service/models/Posts.ts | 121 ------------- src/service/models/data-contracts.ts | 170 ++++++++++-------- src/service/models/index.ts | 1 - 13 files changed, 275 insertions(+), 247 deletions(-) delete mode 100644 src/service/api/post/post.ts create mode 100644 src/service/models/Notices.ts delete mode 100644 src/service/models/Posts.ts diff --git a/src/app/(main)/notice/create-post/_components/Form.tsx b/src/app/(main)/notice/create-post/_components/Form.tsx index bd78f1cf..56fe3360 100644 --- a/src/app/(main)/notice/create-post/_components/Form.tsx +++ b/src/app/(main)/notice/create-post/_components/Form.tsx @@ -27,7 +27,7 @@ export const CreateNoticePostForm = () => { defaultValues: { postTitle: '', postContent: '', - postType: 'NOTICE', + postImageIds: [], }, }) diff --git a/src/app/(main)/notice/posts/[postId]/_components/PostDetail.tsx b/src/app/(main)/notice/posts/[postId]/_components/PostDetail.tsx index 1b9cd392..11dcbf15 100644 --- a/src/app/(main)/notice/posts/[postId]/_components/PostDetail.tsx +++ b/src/app/(main)/notice/posts/[postId]/_components/PostDetail.tsx @@ -5,11 +5,11 @@ import { useRouter } from 'next/navigation' import { Button, Separator, useToast } from '@/components/ui' import { queryClient } from '@/lib/query-client' import { NoticePostQuries, deleteNoticePostApi } from '@/service/api' -import { PostResponseDto } from '@/service/models' +import { BasePostResponseDto } from '@/service/models' import { useMyInfoStore } from '@/store/myInfo' type NoticePostDetailProps = { - post: PostResponseDto + post: BasePostResponseDto } export const NoticePostDetail = ({ post }: NoticePostDetailProps) => { @@ -40,7 +40,7 @@ export const NoticePostDetail = ({ post }: NoticePostDetailProps) => {
{post.userName}
- {format(new Date(post.postCreateDate), 'yyyy-MM-dd')} + {format(new Date(post.postRegDate), 'yyyy-MM-dd')}
조회 {post.postViews}
{role === 'ROLE_ADMIN' && ( diff --git a/src/app/(main)/notice/posts/[postId]/page.tsx b/src/app/(main)/notice/posts/[postId]/page.tsx index aac0ca16..718ed8de 100644 --- a/src/app/(main)/notice/posts/[postId]/page.tsx +++ b/src/app/(main)/notice/posts/[postId]/page.tsx @@ -4,7 +4,7 @@ import { useQuery } from '@tanstack/react-query' import { Spinner } from '@/components/common' import { BoardNavigationButton, PostContent } from '@/components/feature' -import { PostQuries } from '@/service/api' +import { NoticePostQuries } from '@/service/api' import { NoticePostDetail, NoticePostHero } from './_components' @@ -16,7 +16,7 @@ type NoticePostPageParams = { const NoticePostPage = ({ params }: NoticePostPageParams) => { const { data: post, status } = useQuery( - PostQuries.detail({ postId: Number(params.postId) }), + NoticePostQuries.detail({ postId: Number(params.postId) }), ) if (status === 'pending' || !post) return diff --git a/src/components/feature/post/table/Table.tsx b/src/components/feature/post/table/Table.tsx index 43566626..f404bf99 100644 --- a/src/components/feature/post/table/Table.tsx +++ b/src/components/feature/post/table/Table.tsx @@ -7,21 +7,21 @@ import { } from '@tanstack/react-table' import { - PostSummaryResponseDto, + BasePostSummaryResponseDto, PostWithBoardSummaryResponseDto, } from '@/service/models' import { PostTableContent } from './TableContent' type PostTableProps = { - posts: PostSummaryResponseDto[] | PostWithBoardSummaryResponseDto[] + posts: BasePostSummaryResponseDto[] | PostWithBoardSummaryResponseDto[] pageNumber: number pageSize: number } export const PostTable = ({ posts, pageNumber, pageSize }: PostTableProps) => { const columns: ColumnDef< - PostSummaryResponseDto | PostWithBoardSummaryResponseDto + BasePostSummaryResponseDto | PostWithBoardSummaryResponseDto >[] = [ { header: '번호', diff --git a/src/schema/post.ts b/src/schema/post.ts index 36d8ee34..f8e82f81 100644 --- a/src/schema/post.ts +++ b/src/schema/post.ts @@ -22,7 +22,7 @@ export const CreateNoticePostSchema = z.object({ .min(1, { message: '게시글 제목을 입력해주세요.' }) .max(50, { message: '게시글 제목은 50자 이내여야 합니다.' }), postContent: z.string().min(1, { message: '게시글 내용을 입력해주세요.' }), - postType: z.string(), + postImageIds: z.number().array(), }) export type CreateNoticePost = z.infer diff --git a/src/service/api/post/activity.ts b/src/service/api/post/activity.ts index d77e9fba..a987ef1f 100644 --- a/src/service/api/post/activity.ts +++ b/src/service/api/post/activity.ts @@ -14,8 +14,6 @@ import { } from '@/service/models' import { Paging } from '@/types/paging' -import { PostQuries } from './post' - type PostPagingResponse = { posts: PostWithBoardSummaryResponseDto[] } & Paging @@ -68,7 +66,7 @@ const getActivityPostDetail = async ({ } export const activityPostQuries = { - all: () => [...PostQuries.all(), 'activity'], + all: () => ['post', 'activity'], board: (boardId: number) => [...activityPostQuries.all(), boardId], list: ({ boardId, page, size }: ActivityPostPagingRequest) => queryOptions({ diff --git a/src/service/api/post/index.ts b/src/service/api/post/index.ts index ecb1654c..f35e93f5 100644 --- a/src/service/api/post/index.ts +++ b/src/service/api/post/index.ts @@ -1,3 +1,2 @@ -export * from './post' export * from './activity' export * from './notice' diff --git a/src/service/api/post/notice.ts b/src/service/api/post/notice.ts index ddfae651..5410f169 100644 --- a/src/service/api/post/notice.ts +++ b/src/service/api/post/notice.ts @@ -6,26 +6,24 @@ import { queryOptions } from '@tanstack/react-query' import { AUTHORIZATION_API, BACKEND_API } from '@/service/config' import { AddNoticePostRequest, + BasePostSummaryResponseDto, DeleteNoticePostRequest, + GetNoticePostDetailRequest, NoticePostPagingRequest, - PostSummaryResponseDto, - Posts, } from '@/service/models' +import { Notices } from '@/service/models/Notices' import { Paging } from '@/types/paging' -import { PostQuries } from './post' - type NoticePostPagingResponse = { - posts: PostSummaryResponseDto[] + posts: BasePostSummaryResponseDto[] } & Paging const noticePostPaging = async ({ page, size = 10, }: NoticePostPagingRequest): Promise => { - const postClient = new Posts(BACKEND_API) - const response = await postClient.getActivityPosts({ - postType: 'NOTICE', + const noticeClient = new Notices(BACKEND_API) + const response = await noticeClient.getNoticePosts({ page, size, }) @@ -34,7 +32,7 @@ const noticePostPaging = async ({ const posts = data.content.map((post) => { const formatCreateDate = formatDateDistanceFromToday( - new Date(post.postCreateDate), + new Date(post.postRegDate), ) if (!formatCreateDate) return post @@ -59,27 +57,39 @@ const noticePostPaging = async ({ } } +const getNoticePostDetail = async ({ postId }: GetNoticePostDetailRequest) => { + const noticeClient = new Notices(BACKEND_API) + const response = await noticeClient.getNoticePost(postId) + + return response.data +} + export const NoticePostQuries = { - all: () => [...PostQuries.all(), 'notice'], + all: () => ['post', 'notice'], list: ({ page, size }: NoticePostPagingRequest) => queryOptions({ - queryKey: [...PostQuries.all(), page], + queryKey: [...NoticePostQuries.all(), page], queryFn: async () => noticePostPaging({ page, size }), }), + detail: ({ postId }: GetNoticePostDetailRequest) => + queryOptions({ + queryKey: [...NoticePostQuries.all(), postId], + queryFn: () => getNoticePostDetail({ postId }), + }), } export const deleteNoticePostApi = async ({ postId, }: DeleteNoticePostRequest) => { - const postClient = new Posts(AUTHORIZATION_API) - const response = await postClient.deleteNoticePost(postId) + const noticeClient = new Notices(AUTHORIZATION_API) + const response = await noticeClient.removeNoticePost(postId) return response.data } export const addNoticePostApi = async ({ data }: AddNoticePostRequest) => { - const postClient = new Posts(AUTHORIZATION_API) - const response = await postClient.addNoticePost(data) + const noticeClient = new Notices(AUTHORIZATION_API) + const response = await noticeClient.registerNoticePost(data) return response.data } diff --git a/src/service/api/post/post.ts b/src/service/api/post/post.ts deleted file mode 100644 index f384b293..00000000 --- a/src/service/api/post/post.ts +++ /dev/null @@ -1,22 +0,0 @@ -'use client' - -import { queryOptions } from '@tanstack/react-query' - -import { BACKEND_API } from '@/service/config' -import { GetPostDetailRequest, Posts } from '@/service/models' - -const getPostDetail = async ({ postId }: GetPostDetailRequest) => { - const postClient = new Posts(BACKEND_API) - const response = await postClient.getPost(postId) - - return response.data -} - -export const PostQuries = { - all: () => ['posts'], - detail: ({ postId }: GetPostDetailRequest) => - queryOptions({ - queryKey: [...PostQuries.all(), postId], - queryFn: async () => getPostDetail({ postId }), - }), -} diff --git a/src/service/models/Notices.ts b/src/service/models/Notices.ts new file mode 100644 index 00000000..b25a2b4d --- /dev/null +++ b/src/service/models/Notices.ts @@ -0,0 +1,143 @@ +/* eslint-disable */ + +/* tslint:disable */ + +/* + * --------------------------------------------------------------- + * ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ## + * ## ## + * ## AUTHOR: acacode ## + * ## SOURCE: https://github.com/acacode/swagger-typescript-api ## + * --------------------------------------------------------------- + */ +import { CustomHttpClient } from '../config' +import { + BasePostRequestDto, + GetNoticePostData, + GetNoticePostsData, + RegisterNoticePostData, + RemoveNoticePostData, + UpdateNoticePostData, +} from './data-contracts' +import { ContentType, RequestParams } from './http-client' + +export class Notices< + SecurityDataType = unknown, +> extends CustomHttpClient { + /** + * No description + * + * @tags 게시글 API + * @name GetNoticePost + * @summary 공지사항 게시글 단일 조회 + * @request GET:/notices/{postId} + * @secure + * @response `200` `GetNoticePostData` OK + * @response `404` `void` + */ + getNoticePost = (postId: number, params: RequestParams = {}) => + this.request({ + path: `/notices/${postId}`, + method: 'GET', + secure: true, + ...params, + }) + /** + * No description + * + * @tags 게시글 API + * @name UpdateNoticePost + * @summary 공지사항 게시글 수정 + * @request PUT:/notices/{postId} + * @secure + * @response `200` `UpdateNoticePostData` + * @response `404` `void` + */ + updateNoticePost = ( + postId: number, + data: BasePostRequestDto, + params: RequestParams = {}, + ) => + this.request({ + path: `/notices/${postId}`, + method: 'PUT', + body: data, + secure: true, + type: ContentType.Json, + format: 'json', + ...params, + }) + /** + * No description + * + * @tags 게시글 API + * @name RemoveNoticePost + * @summary 공지사항 삭제 + * @request DELETE:/notices/{postId} + * @secure + * @response `200` `RemoveNoticePostData` + * @response `404` `void` + */ + removeNoticePost = (postId: number, params: RequestParams = {}) => + this.request({ + path: `/notices/${postId}`, + method: 'DELETE', + secure: true, + format: 'json', + ...params, + }) + /** + * No description + * + * @tags 게시글 API + * @name GetNoticePosts + * @summary 공지사항 게시글 목록 조회 + * @request GET:/notices + * @secure + * @response `200` `GetNoticePostsData` OK + */ + getNoticePosts = ( + query?: { + /** + * @format int32 + * @default 0 + */ + page?: number + /** + * @format int32 + * @default 10 + */ + size?: number + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/notices`, + method: 'GET', + query: query, + secure: true, + ...params, + }) + /** + * No description + * + * @tags 게시글 API + * @name RegisterNoticePost + * @summary 공지사항 게시글 생성 + * @request POST:/notices + * @secure + * @response `200` `RegisterNoticePostData` OK + * @response `201` `void` + * @response `401` `void` + * @response `404` `void` + */ + registerNoticePost = (data: BasePostRequestDto, params: RequestParams = {}) => + this.request({ + path: `/notices`, + method: 'POST', + body: data, + secure: true, + type: ContentType.Json, + ...params, + }) +} diff --git a/src/service/models/Posts.ts b/src/service/models/Posts.ts deleted file mode 100644 index 24ddfde5..00000000 --- a/src/service/models/Posts.ts +++ /dev/null @@ -1,121 +0,0 @@ -/* eslint-disable */ - -/* tslint:disable */ - -/* - * --------------------------------------------------------------- - * ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ## - * ## ## - * ## AUTHOR: acacode ## - * ## SOURCE: https://github.com/acacode/swagger-typescript-api ## - * --------------------------------------------------------------- - */ -import { CustomHttpClient } from '../config' -import { - AddNoticePostData, - CreatePostRequestDto, - DeleteNoticePostData, - GetActivityPostsData, - GetPostData, -} from './data-contracts' -import { ContentType, RequestParams } from './http-client' - -export class Posts< - SecurityDataType = unknown, -> extends CustomHttpClient { - /** - * No description - * - * @tags 게시글 API - * @name GetActivityPosts - * @summary 공지사항, 이벤트 게시글 목록 조회 - * @request GET:/posts - * @secure - * @response `200` `GetActivityPostsData` OK - * @response `404` `void` - */ - getActivityPosts = ( - query: { - postType: string - /** - * 조회 할 page, default: 0 - * @format int32 - * @default 0 - */ - page?: number - /** - * 한 번에 조회 할 page 수, default: 10 - * @format int32 - * @default 10 - */ - size?: number - }, - params: RequestParams = {}, - ) => - this.request({ - path: `/posts`, - method: 'GET', - query: query, - secure: true, - ...params, - }) - /** - * No description - * - * @tags 게시글 API - * @name AddNoticePost - * @summary 공지사항, 이벤트 게시글 생성 - * @request POST:/posts - * @secure - * @response `200` `AddNoticePostData` OK - * @response `201` `void` - * @response `400` `void` - * @response `404` `void` - */ - addNoticePost = (data: CreatePostRequestDto, params: RequestParams = {}) => - this.request({ - path: `/posts`, - method: 'POST', - body: data, - secure: true, - type: ContentType.Json, - ...params, - }) - /** - * No description - * - * @tags 게시글 API - * @name GetPost - * @summary 게시글 단일 조회 - * @request GET:/posts/{postId} - * @secure - * @response `200` `GetPostData` OK - * @response `404` `void` - */ - getPost = (postId: number, params: RequestParams = {}) => - this.request({ - path: `/posts/${postId}`, - method: 'GET', - secure: true, - ...params, - }) - /** - * No description - * - * @tags 게시글 API - * @name DeleteNoticePost - * @summary 공지사항, 이벤트 게시글 삭제 - * @request DELETE:/posts/{postId} - * @secure - * @response `200` `DeleteNoticePostData` - * @response `404` `void` - */ - deleteNoticePost = (postId: number, params: RequestParams = {}) => - this.request({ - path: `/posts/${postId}`, - method: 'DELETE', - secure: true, - format: 'json', - ...params, - }) -} diff --git a/src/service/models/data-contracts.ts b/src/service/models/data-contracts.ts index 27e771d8..1e499f27 100644 --- a/src/service/models/data-contracts.ts +++ b/src/service/models/data-contracts.ts @@ -93,6 +93,80 @@ export interface PostWithBoardRequestDto { postActivityEndDate?: string } +export interface BasePostSummaryResponseDto { + /** + * 게시글 id + * @format int64 + */ + postId: number + /** 게시글 제목 */ + postTitle: string + /** + * 게시글 조회수 + * @format int64 + */ + postViews: number + /** + * 유저 아이디 + * @example "haedal12" + */ + userId: string + /** + * 유저 이름 + * @example "조대성" + */ + userName: string + /** + * 게시글 타입 + * @example "(NOTICE, ACTIVITY)" + */ + postType: 'ACTIVITY' | 'NOTICE' + /** + * 게시글 생성일 + * @format date-time + */ + postRegDate: string +} + +export interface PageBasePostSummaryResponseDto { + /** @format int32 */ + totalPages: number + /** @format int64 */ + totalElements: number + /** @format int32 */ + size?: number + content: BasePostSummaryResponseDto[] + /** @format int32 */ + number?: number + sort?: SortObject[] + /** @format int32 */ + numberOfElements?: number + pageable: PageableObject + first?: boolean + last?: boolean + empty?: boolean +} + +export interface BasePostRequestDto { + /** + * 게시글 이름 + * @minLength 1 + * @maxLength 50 + * @example "게시글1" + */ + postTitle?: string + /** + * @minLength 1 + * @maxLength 200000 + */ + postContent?: string + /** + * 게시글 이미지 ID + * @example [1,2] + */ + postImageIds?: number[] +} + export interface PostWithBoardResponseDto { /** * 게시글 id @@ -145,36 +219,6 @@ export interface PostWithBoardResponseDto { postActivityEndDate?: string } -export interface CreatePostRequestDto { - /** - * 게시글 이름 - * @minLength 1 - * @maxLength 50 - * @example "게시글1" - */ - postTitle: string - /** - * @minLength 1 - * @maxLength 200000 - */ - postContent: string - /** - * 활동 시작일 (이벤트와 활동은 필수, 공지사항은 생략) - * @example "yyyy-MM-dd (2024-07-24)" - */ - postActivityStartDate?: string - /** - * 활동 종료일 (생략 가능) - * @example "yyyy-MM-dd (2024-07-24)" - */ - postActivityEndDate?: string - /** - * 게시글 타입 - * @example "(ACTIVITY, NOTICE)" - */ - postType: string -} - export interface LoginRequestDto { /** * 유저 아이디 @@ -411,25 +455,6 @@ export interface ActivityResponseDto { semesterId: number } -export interface PagePostSummaryResponseDto { - /** @format int32 */ - totalPages: number - /** @format int64 */ - totalElements: number - /** @format int32 */ - size?: number - content: PostSummaryResponseDto[] - /** @format int32 */ - number?: number - sort?: SortObject[] - /** @format int32 */ - numberOfElements?: number - pageable: PageableObject - first?: boolean - last?: boolean - empty?: boolean -} - export interface PagePostWithBoardSummaryResponseDto { /** @format int32 */ totalPages: number @@ -449,7 +474,7 @@ export interface PagePostWithBoardSummaryResponseDto { empty?: boolean } -export interface PostSummaryResponseDto { +export interface BasePostResponseDto { /** * 게시글 id * @format int64 @@ -457,31 +482,23 @@ export interface PostSummaryResponseDto { postId: number /** 게시글 제목 */ postTitle: string - /** - * 게시글 대표 이미지 파일 Url - * @format url - */ - postImageUrl?: string + /** 게시글 내용 */ + postContent: string /** * 게시글 조회수 * @format int64 */ postViews: number /** - * 활동 시작일 - * @format date - */ - postActivityStartDate?: string - /** - * 활동 종료일 - * @format date + * 게시글 타입 + * @example "(NOTICE, ACTIVITY)" */ - postActivityEndDate?: string + postType: 'ACTIVITY' | 'NOTICE' /** * 게시글 생성일 * @format date-time */ - postCreateDate: string + postRegDate: string /** * 유저 아이디 * @example "haedal12" @@ -492,13 +509,6 @@ export interface PostSummaryResponseDto { * @example "조대성" */ userName: string - /** - * 게시판 id - * @format int64 - */ - boardId?: number - /** 게시판 이름 */ - boardName?: string } export interface PostWithBoardSummaryResponseDto { @@ -703,14 +713,16 @@ export interface UpdateBoardImagePayload { export type GetPostWithBoardData = PostWithBoardResponseDto +export type GetNoticePostData = BasePostResponseDto + export type UpdateBoardImageData = any export type ReissueData = any -export type GetActivityPostsData = PagePostSummaryResponseDto - export type AddNoticePostData = SuccessResponse +export type RegisterNoticePostData = SuccessResponse + export type SignInData = any export type SignIn1Data = any @@ -727,6 +739,8 @@ export type CommonErrorCodeDefinitionData = any export type GetPostsWithBoardData = PagePostWithBoardSummaryResponseDto +export type GetNoticePostsData = PageBasePostSummaryResponseDto + export type RegisterPostWithBoardData = SuccessResponse export type RegisterSemesterData = SuccessResponse @@ -783,6 +797,10 @@ export type RemoveSemesterData = any export type RemoveActivityData = any +export type RemoveNoticePostData = any + +export type UpdateNoticePostData = any + /** request type */ export interface GetActivitiesRequest { semesterId: number @@ -871,7 +889,7 @@ export interface DeleteNoticePostRequest { } export interface AddNoticePostRequest { - data: CreatePostRequestDto + data: BasePostRequestDto } export interface ActivityPostPagingRequest { @@ -906,3 +924,7 @@ export interface GetSemesterRequest { export interface GetUserRequest { userId: string } + +export interface GetNoticePostDetailRequest { + postId: number +} diff --git a/src/service/models/index.ts b/src/service/models/index.ts index 6ad3e112..45d5612d 100644 --- a/src/service/models/index.ts +++ b/src/service/models/index.ts @@ -5,7 +5,6 @@ export * from './CommonErrorCode' export * from './Join' export * from './Login' export * from './Logout' -export * from './Posts' export * from './Private' export * from './Reissue' export * from './Semesters' From 461ff34e381aebe6d52b4fd20419cb163b8ddcf5 Mon Sep 17 00:00:00 2001 From: ajin Date: Fri, 10 Jan 2025 22:37:16 +0900 Subject: [PATCH 15/18] =?UTF-8?q?Refactor:=20=EA=B2=8C=EC=8B=9C=EA=B8=80?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C=20=ED=99=95=EC=9D=B8=EC=B0=BD=20=EA=B3=B5?= =?UTF-8?q?=ED=86=B5=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=EB=A1=9C=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../[postId]/_components/detail/Detail.tsx | 3 +-- .../posts/[postId]/_components/PostDetail.tsx | 21 +++++++++---------- .../post}/delete-dialog/DeleteDialog.tsx | 0 .../feature/post}/delete-dialog/index.ts | 0 src/components/feature/post/index.ts | 1 + 5 files changed, 12 insertions(+), 13 deletions(-) rename src/{app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail => components/feature/post}/delete-dialog/DeleteDialog.tsx (100%) rename src/{app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail => components/feature/post}/delete-dialog/index.ts (100%) diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/Detail.tsx b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/Detail.tsx index eba73b52..0af1b82c 100644 --- a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/Detail.tsx +++ b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/Detail.tsx @@ -2,14 +2,13 @@ import { useMutation } from '@tanstack/react-query' import { format } from 'date-fns' import { usePathname, useRouter } from 'next/navigation' +import { DeletePostDialog } from '@/components/feature' import { Separator, useToast } from '@/components/ui' import { queryClient } from '@/lib/query-client' import { activityPostQuries, deleteActivityPostApi } from '@/service/api' import { PostWithBoardResponseDto } from '@/service/models' import { useMyInfoStore } from '@/store/myInfo' -import { DeletePostDialog } from './delete-dialog' - type ActivityPostDetailProps = { boardId: number post: PostWithBoardResponseDto diff --git a/src/app/(main)/notice/posts/[postId]/_components/PostDetail.tsx b/src/app/(main)/notice/posts/[postId]/_components/PostDetail.tsx index 11dcbf15..0a085e85 100644 --- a/src/app/(main)/notice/posts/[postId]/_components/PostDetail.tsx +++ b/src/app/(main)/notice/posts/[postId]/_components/PostDetail.tsx @@ -2,7 +2,8 @@ import { useMutation } from '@tanstack/react-query' import { format } from 'date-fns' import { useRouter } from 'next/navigation' -import { Button, Separator, useToast } from '@/components/ui' +import { DeletePostDialog } from '@/components/feature' +import { Separator, useToast } from '@/components/ui' import { queryClient } from '@/lib/query-client' import { NoticePostQuries, deleteNoticePostApi } from '@/service/api' import { BasePostResponseDto } from '@/service/models' @@ -36,6 +37,14 @@ export const NoticePostDetail = ({ post }: NoticePostDetailProps) => { return (
{post.postTitle}
+
+ {role === 'ROLE_ADMIN' && ( + deleteNoticePost({ postId: post.postId })} + disabled={isPending} + /> + )} +
{post.userName}
@@ -43,16 +52,6 @@ export const NoticePostDetail = ({ post }: NoticePostDetailProps) => { {format(new Date(post.postRegDate), 'yyyy-MM-dd')}
조회 {post.postViews}
- {role === 'ROLE_ADMIN' && ( - - )}
diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/delete-dialog/DeleteDialog.tsx b/src/components/feature/post/delete-dialog/DeleteDialog.tsx similarity index 100% rename from src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/delete-dialog/DeleteDialog.tsx rename to src/components/feature/post/delete-dialog/DeleteDialog.tsx diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/delete-dialog/index.ts b/src/components/feature/post/delete-dialog/index.ts similarity index 100% rename from src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/delete-dialog/index.ts rename to src/components/feature/post/delete-dialog/index.ts diff --git a/src/components/feature/post/index.ts b/src/components/feature/post/index.ts index 123b742f..4ec20f9e 100644 --- a/src/components/feature/post/index.ts +++ b/src/components/feature/post/index.ts @@ -3,3 +3,4 @@ export * from './form-field' export * from './table' export * from './content' export * from './image-input' +export * from './delete-dialog' From f55c2acd5f323d72053c18fb387f67070104395a Mon Sep 17 00:00:00 2001 From: ajin Date: Fri, 10 Jan 2025 22:48:29 +0900 Subject: [PATCH 16/18] =?UTF-8?q?Fix:=20=EA=B3=B5=ED=86=B5=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20PostDeleteDialog=EC=97=90=20'use-?= =?UTF-8?q?client'=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/feature/post/delete-dialog/DeleteDialog.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/feature/post/delete-dialog/DeleteDialog.tsx b/src/components/feature/post/delete-dialog/DeleteDialog.tsx index 54ab522f..2e6ee66b 100644 --- a/src/components/feature/post/delete-dialog/DeleteDialog.tsx +++ b/src/components/feature/post/delete-dialog/DeleteDialog.tsx @@ -1,3 +1,5 @@ +'use client' + import { useState } from 'react' import { From 92e140839f717fb6085f08284d44c14f3acd37ab Mon Sep 17 00:00:00 2001 From: ajin Date: Fri, 10 Jan 2025 22:56:27 +0900 Subject: [PATCH 17/18] =?UTF-8?q?Fix:=20props=20=ED=83=80=EC=9E=85=20inter?= =?UTF-8?q?face=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../[boardId]/posts/[postId]/_components/detail/Detail.tsx | 2 +- src/app/(main)/notice/posts/[postId]/_components/PostDetail.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/Detail.tsx b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/Detail.tsx index 0af1b82c..bee45778 100644 --- a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/Detail.tsx +++ b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/posts/[postId]/_components/detail/Detail.tsx @@ -9,7 +9,7 @@ import { activityPostQuries, deleteActivityPostApi } from '@/service/api' import { PostWithBoardResponseDto } from '@/service/models' import { useMyInfoStore } from '@/store/myInfo' -type ActivityPostDetailProps = { +interface ActivityPostDetailProps { boardId: number post: PostWithBoardResponseDto } diff --git a/src/app/(main)/notice/posts/[postId]/_components/PostDetail.tsx b/src/app/(main)/notice/posts/[postId]/_components/PostDetail.tsx index 0a085e85..8da210a6 100644 --- a/src/app/(main)/notice/posts/[postId]/_components/PostDetail.tsx +++ b/src/app/(main)/notice/posts/[postId]/_components/PostDetail.tsx @@ -9,7 +9,7 @@ import { NoticePostQuries, deleteNoticePostApi } from '@/service/api' import { BasePostResponseDto } from '@/service/models' import { useMyInfoStore } from '@/store/myInfo' -type NoticePostDetailProps = { +interface NoticePostDetailProps { post: BasePostResponseDto } From 8ab4f74c56dae132aead78aa73a0196a0c2122cb Mon Sep 17 00:00:00 2001 From: ajin Date: Fri, 10 Jan 2025 22:57:10 +0900 Subject: [PATCH 18/18] =?UTF-8?q?Fix:=20props=20=ED=83=80=EC=9E=85=20inter?= =?UTF-8?q?face=EB=A1=9C=20=EB=B3=80=EA=B2=BD2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../boards/[boardId]/create-post/_components/form/Form.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/form/Form.tsx b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/form/Form.tsx index d43cbddf..c36d96df 100644 --- a/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/form/Form.tsx +++ b/src/app/(main)/activity/[semesterId]/[activityId]/boards/[boardId]/create-post/_components/form/Form.tsx @@ -25,7 +25,7 @@ import { activityPostQuries, addActivityPostApi } from '@/service/api' import { ActivityDateFieldDialog } from './date-field-dialog' -type CreateActivityPostFormProps = { +interface CreateActivityPostFormProps { boardId: number }