diff --git a/.storybook/main.ts b/.storybook/main.ts index 62192c92..66d909b4 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -13,6 +13,13 @@ const config: StorybookConfig = { name: '@storybook/nextjs-vite', options: {}, }, - staticDirs: ['..\\public'], + // staticDirs: ['../public'], + async viteFinal(config, { configType }) { + if (configType === 'PRODUCTION') { + config.base = '/storybook/'; + } + return config; + }, }; + export default config; diff --git a/package.json b/package.json index 28c357ce..ccb7b0fd 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "private": true, "scripts": { "dev": "next dev --turbopack", - "build": "next build", + "build": "next build && storybook build -o public/storybook", "start": "next start", "lint": "next lint", "type-check": "tsc --noEmit", diff --git a/src/app/(app)/error.tsx b/src/app/(app)/error.tsx index 55352da1..ff92ba16 100644 --- a/src/app/(app)/error.tsx +++ b/src/app/(app)/error.tsx @@ -47,7 +47,7 @@ export default function SegmentError({ error, reset }: ErrorPageProps) { }, [error]); return ( -
+

콘텐츠를 불러오지 못했습니다. diff --git a/src/app/api/test/error/route.ts b/src/app/api/test/error/route.ts index 149287c7..833ba556 100644 --- a/src/app/api/test/error/route.ts +++ b/src/app/api/test/error/route.ts @@ -50,7 +50,7 @@ export async function GET(request: NextRequest) { ); case '409': return NextResponse.json( - { message: '이미 사용 중인 이름입니다.' }, + { message: '이미 사용 중인 이메일입니다.' }, { status: 409 }, ); case '500': diff --git a/src/app/error.tsx b/src/app/error.tsx index 07327729..ce065863 100644 --- a/src/app/error.tsx +++ b/src/app/error.tsx @@ -48,7 +48,7 @@ export default function GlobalError({ error, reset }: ErrorPageProps) { }, [error]); return ( -
+

문제가 발생했습니다. diff --git a/src/app/storybook/page.tsx b/src/app/storybook/page.tsx new file mode 100644 index 00000000..430b95d4 --- /dev/null +++ b/src/app/storybook/page.tsx @@ -0,0 +1,12 @@ +'use client'; + +import { useRouter } from 'next/navigation'; +import { useEffect } from 'react'; + +export default function StorybookRedirect() { + const router = useRouter(); + useEffect(() => { + router.replace('/storybook/index.html'); + }, []); + return null; +} diff --git a/src/domain/Activity/components/detail/Review/ExpandableReview.tsx b/src/domain/Activity/components/detail/Review/ExpandableText.tsx similarity index 82% rename from src/domain/Activity/components/detail/Review/ExpandableReview.tsx rename to src/domain/Activity/components/detail/Review/ExpandableText.tsx index 667f3ba0..096cd75c 100644 --- a/src/domain/Activity/components/detail/Review/ExpandableReview.tsx +++ b/src/domain/Activity/components/detail/Review/ExpandableText.tsx @@ -6,9 +6,13 @@ import TriangleArrow from '@/shared/assets/icons/TriangleArrow'; interface ExpandableReviewProps { text: string; + maxHeight?: number; } -export default function ExpandableReview({ text }: ExpandableReviewProps) { +export default function ExpandableText({ + text, + maxHeight = 1000, +}: ExpandableReviewProps) { const [isExpanded, setIsExpanded] = useState(false); const [showToggle, setShowToggle] = useState(false); const contentRef = useRef(null); @@ -45,15 +49,12 @@ export default function ExpandableReview({ text }: ExpandableReviewProps) {
{text} - - {/* 말줄임용 그라디언트 */} - {!isExpanded && showToggle && ( -
- )}
{/* 더보기 버튼 */} diff --git a/src/domain/Activity/components/detail/Review/ReviewCard.tsx b/src/domain/Activity/components/detail/Review/ReviewCard.tsx index 3ccf19ea..fa951a95 100644 --- a/src/domain/Activity/components/detail/Review/ReviewCard.tsx +++ b/src/domain/Activity/components/detail/Review/ReviewCard.tsx @@ -1,6 +1,7 @@ import { Star } from 'lucide-react'; -import ExpandableReview from '@/domain/Activity/components/detail/Review/ExpandableReview'; +import ExpandableText from '@/domain/Activity/components/detail/Review/ExpandableText'; +import Avatar from '@/shared/components/ui/avatar'; import { Review } from '../../../types/detail/types'; import { getTimeAgo } from '../../../utils/getTimeAgo'; @@ -37,8 +38,9 @@ export default function ReviewCard(review: Review) { return (
-
+
+ {user.nickname} @@ -61,7 +63,7 @@ export default function ReviewCard(review: Review) { })}
- +
); } diff --git a/src/domain/Activity/components/detail/activity-summary/ActivityDropdown.tsx b/src/domain/Activity/components/detail/activity-summary/ActivityDropdown.tsx index a2b00ff1..796052bd 100644 --- a/src/domain/Activity/components/detail/activity-summary/ActivityDropdown.tsx +++ b/src/domain/Activity/components/detail/activity-summary/ActivityDropdown.tsx @@ -57,6 +57,7 @@ export default function ActivityDropdown({ try { await deleteActivity(id); queryClient.invalidateQueries({ queryKey: activitiesKeys.all }); + queryClient.invalidateQueries({ queryKey: ['carousel-activities'] }); router.push('/activities'); } catch (e) { console.error(e); diff --git a/src/domain/Activity/components/detail/description/DescriptionSection.tsx b/src/domain/Activity/components/detail/description/DescriptionSection.tsx index 4b8ca1cd..2fed032f 100644 --- a/src/domain/Activity/components/detail/description/DescriptionSection.tsx +++ b/src/domain/Activity/components/detail/description/DescriptionSection.tsx @@ -1,3 +1,5 @@ +import ExpandableText from '@/domain/Activity/components/detail/Review/ExpandableText'; + /** * DescriptionSection * 체험 상세 페이지에서 체험 설명을 보여주는 컴포넌트 @@ -16,9 +18,7 @@ export default function DescriptionSection({ return (

체험 설명

-

- {description} -

+
); } diff --git a/src/domain/Reservation/components/my-activity-card/DeleteMyActivityModal.tsx b/src/domain/Reservation/components/my-activity-card/DeleteMyActivityModal.tsx index 565397f1..b716f2ed 100644 --- a/src/domain/Reservation/components/my-activity-card/DeleteMyActivityModal.tsx +++ b/src/domain/Reservation/components/my-activity-card/DeleteMyActivityModal.tsx @@ -29,6 +29,7 @@ export default function DeleteMyActivityModal({ }, onSettled: () => { queryClient.invalidateQueries({ queryKey: ['my-activities'] }); + queryClient.invalidateQueries({ queryKey: ['carousel-activities'] }); }, }); diff --git a/src/domain/Reservation/components/reservation-calendar/DayCell.tsx b/src/domain/Reservation/components/reservation-calendar/DayCell.tsx index bb1f8903..7ca4d26c 100644 --- a/src/domain/Reservation/components/reservation-calendar/DayCell.tsx +++ b/src/domain/Reservation/components/reservation-calendar/DayCell.tsx @@ -205,7 +205,13 @@ export default function DayCell({ status: 'declined', }), onSuccess: () => { - queryClient.invalidateQueries({ queryKey: ['reservationsBySchedule'] }); + queryClient.invalidateQueries({ + queryKey: [ + 'allReservationsByDate', + selectedActivityId, + day.format('YYYY-MM-DD'), + ], + }); queryClient.invalidateQueries({ queryKey: ['schedules'] }); queryClient.invalidateQueries({ queryKey: ['reservationDashboard'] }); }, diff --git a/src/middleware.ts b/src/middleware.ts index 08237855..579d61f5 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -1,5 +1,6 @@ import { NextRequest, NextResponse } from 'next/server'; +import setAuthCookies from '@/domain/Auth/utils/setAuthCookies'; import { ERROR_CODES, ROUTES } from '@/shared/constants/routes'; import { BRIDGE_API } from './shared/constants/bridgeEndpoints'; @@ -139,21 +140,14 @@ export async function middleware(request: NextRequest) { signal: AbortSignal.timeout(30000), }); - const finalResponse = new NextResponse(response.body, { - status: response.status, - statusText: response.statusText, - headers: response.headers, - }); - - finalResponse.cookies.set('accessToken', newAccessToken, { - httpOnly: true, - secure: process.env.NODE_ENV === 'production', - path: '/', - maxAge: 60 * 60, - sameSite: 'lax', - }); - - return finalResponse; + return setAuthCookies( + new NextResponse(response.body, { + status: response.status, + statusText: response.statusText, + headers: response.headers, + }), + tokens, + ); } else { console.log( '[Middleware] Refresh Token 만료 또는 갱신 실패. 로그인 페이지로 리다이렉트합니다.', diff --git a/vercel.json b/vercel.json new file mode 100644 index 00000000..afb1d559 --- /dev/null +++ b/vercel.json @@ -0,0 +1,8 @@ +{ + "rewrites": [ + { + "source": "/storybook", + "destination": "/_next/static/storybook/index.html" + } + ] +}