From a416b5df583062c37c08fda6ccf61a66178699b0 Mon Sep 17 00:00:00 2001 From: JAESEON PARK Date: Wed, 28 Jan 2026 19:01:50 +0900 Subject: [PATCH 01/12] =?UTF-8?q?chore:=20=EA=B8=80=EB=A1=9C=EB=B2=8C=20st?= =?UTF-8?q?yle=20=EC=84=B8=ED=8C=85(shadcn=ED=85=8C=EB=A7=88,=20=ED=8F=B0?= =?UTF-8?q?=ED=8A=B8,=20=ED=86=A0=ED=81=B0,=20=EA=B8=B0=EB=B3=B8=20?= =?UTF-8?q?=ED=83=80=EC=9D=B4=ED=8F=AC=EC=84=B8=ED=8C=85)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.css | 129 +--------------------------------- src/main.tsx | 20 +++--- src/styles/globals.css | 156 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 167 insertions(+), 138 deletions(-) create mode 100644 src/styles/globals.css diff --git a/src/index.css b/src/index.css index cef01c9..ef25362 100644 --- a/src/index.css +++ b/src/index.css @@ -1,128 +1 @@ -@import "tailwindcss"; -@import "tw-animate-css"; - -@custom-variant dark (&:is(.dark *)); - -@theme inline { - --radius-sm: calc(var(--radius) - 4px); - --radius-md: calc(var(--radius) - 2px); - --radius-lg: var(--radius); - --radius-xl: calc(var(--radius) + 4px); - --radius-2xl: calc(var(--radius) + 8px); - --radius-3xl: calc(var(--radius) + 12px); - --radius-4xl: calc(var(--radius) + 16px); - --color-background: var(--background); - --color-foreground: var(--foreground); - --color-card: var(--card); - --color-card-foreground: var(--card-foreground); - --color-popover: var(--popover); - --color-popover-foreground: var(--popover-foreground); - --color-primary: var(--primary); - --color-primary-foreground: var(--primary-foreground); - --color-secondary: var(--secondary); - --color-secondary-foreground: var(--secondary-foreground); - --color-muted: var(--muted); - --color-muted-foreground: var(--muted-foreground); - --color-accent: var(--accent); - --color-accent-foreground: var(--accent-foreground); - --color-destructive: var(--destructive); - --color-border: var(--border); - --color-input: var(--input); - --color-ring: var(--ring); - --color-chart-1: var(--chart-1); - --color-chart-2: var(--chart-2); - --color-chart-3: var(--chart-3); - --color-chart-4: var(--chart-4); - --color-chart-5: var(--chart-5); - --color-sidebar: var(--sidebar); - --color-sidebar-foreground: var(--sidebar-foreground); - --color-sidebar-primary: var(--sidebar-primary); - --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); - --color-sidebar-accent: var(--sidebar-accent); - --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); - --color-sidebar-border: var(--sidebar-border); - --color-sidebar-ring: var(--sidebar-ring); -} - -:root { - --radius: 0.625rem; - --background: oklch(1 0 0); - --foreground: oklch(0.13 0.028 261.692); - --card: oklch(1 0 0); - --card-foreground: oklch(0.13 0.028 261.692); - --popover: oklch(1 0 0); - --popover-foreground: oklch(0.13 0.028 261.692); - --primary: oklch(0.21 0.034 264.665); - --primary-foreground: oklch(0.985 0.002 247.839); - --secondary: oklch(0.967 0.003 264.542); - --secondary-foreground: oklch(0.21 0.034 264.665); - --muted: oklch(0.967 0.003 264.542); - --muted-foreground: oklch(0.551 0.027 264.364); - --accent: oklch(0.967 0.003 264.542); - --accent-foreground: oklch(0.21 0.034 264.665); - --destructive: oklch(0.577 0.245 27.325); - --border: oklch(0.928 0.006 264.531); - --input: oklch(0.928 0.006 264.531); - --ring: oklch(0.707 0.022 261.325); - --chart-1: oklch(0.646 0.222 41.116); - --chart-2: oklch(0.6 0.118 184.704); - --chart-3: oklch(0.398 0.07 227.392); - --chart-4: oklch(0.828 0.189 84.429); - --chart-5: oklch(0.769 0.188 70.08); - --sidebar: oklch(0.985 0.002 247.839); - --sidebar-foreground: oklch(0.13 0.028 261.692); - --sidebar-primary: oklch(0.21 0.034 264.665); - --sidebar-primary-foreground: oklch(0.985 0.002 247.839); - --sidebar-accent: oklch(0.967 0.003 264.542); - --sidebar-accent-foreground: oklch(0.21 0.034 264.665); - --sidebar-border: oklch(0.928 0.006 264.531); - --sidebar-ring: oklch(0.707 0.022 261.325); -} - -.dark { - --background: oklch(0.13 0.028 261.692); - --foreground: oklch(0.985 0.002 247.839); - --card: oklch(0.21 0.034 264.665); - --card-foreground: oklch(0.985 0.002 247.839); - --popover: oklch(0.21 0.034 264.665); - --popover-foreground: oklch(0.985 0.002 247.839); - --primary: oklch(0.928 0.006 264.531); - --primary-foreground: oklch(0.21 0.034 264.665); - --secondary: oklch(0.278 0.033 256.848); - --secondary-foreground: oklch(0.985 0.002 247.839); - --muted: oklch(0.278 0.033 256.848); - --muted-foreground: oklch(0.707 0.022 261.325); - --accent: oklch(0.278 0.033 256.848); - --accent-foreground: oklch(0.985 0.002 247.839); - --destructive: oklch(0.704 0.191 22.216); - --border: oklch(1 0 0 / 10%); - --input: oklch(1 0 0 / 15%); - --ring: oklch(0.551 0.027 264.364); - --chart-1: oklch(0.488 0.243 264.376); - --chart-2: oklch(0.696 0.17 162.48); - --chart-3: oklch(0.769 0.188 70.08); - --chart-4: oklch(0.627 0.265 303.9); - --chart-5: oklch(0.645 0.246 16.439); - --sidebar: oklch(0.21 0.034 264.665); - --sidebar-foreground: oklch(0.985 0.002 247.839); - --sidebar-primary: oklch(0.488 0.243 264.376); - --sidebar-primary-foreground: oklch(0.985 0.002 247.839); - --sidebar-accent: oklch(0.278 0.033 256.848); - --sidebar-accent-foreground: oklch(0.985 0.002 247.839); - --sidebar-border: oklch(1 0 0 / 10%); - --sidebar-ring: oklch(0.551 0.027 264.364); -} - -@layer base { - * { - @apply border-border outline-ring/50; - } - body { - @apply bg-background text-foreground; - } -} - -body { - word-break: keep-all; - overflow-wrap: break-word; -} +@import "./styles/globals.css"; diff --git a/src/main.tsx b/src/main.tsx index 10ed13e..3b139b0 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,10 +1,10 @@ -import { StrictMode } from "react"; -import { createRoot } from "react-dom/client"; -import "./index.css"; -import App from "./App.tsx"; - -createRoot(document.getElementById("root")!).render( - - - -); +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import "./index.css"; +import App from "./App.tsx"; + +createRoot(document.getElementById("root")!).render( + + + , +); diff --git a/src/styles/globals.css b/src/styles/globals.css new file mode 100644 index 0000000..a66c7a1 --- /dev/null +++ b/src/styles/globals.css @@ -0,0 +1,156 @@ +@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700&display=swap"); +@import "tailwindcss"; +@import "tw-animate-css"; + +@custom-variant dark (&:is(.dark *)); + +@theme inline { + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); + --radius-2xl: calc(var(--radius) + 8px); + --radius-3xl: calc(var(--radius) + 12px); + --radius-4xl: calc(var(--radius) + 16px); + --color-background: var(--background); + --color-foreground: var(--foreground); + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); +} + +:root { + --radius: 0.625rem; + --background: oklch(1 0 0); + --foreground: oklch(0.13 0.028 261.692); + --card: oklch(1 0 0); + --card-foreground: oklch(0.13 0.028 261.692); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.13 0.028 261.692); + --primary: oklch(0.21 0.034 264.665); + --primary-foreground: oklch(0.985 0.002 247.839); + --secondary: oklch(0.967 0.003 264.542); + --secondary-foreground: oklch(0.21 0.034 264.665); + --muted: oklch(0.967 0.003 264.542); + --muted-foreground: oklch(0.551 0.027 264.364); + --accent: oklch(0.967 0.003 264.542); + --accent-foreground: oklch(0.21 0.034 264.665); + --destructive: oklch(0.577 0.245 27.325); + --border: oklch(0.928 0.006 264.531); + --input: oklch(0.928 0.006 264.531); + --ring: oklch(0.707 0.022 261.325); + --chart-1: oklch(0.646 0.222 41.116); + --chart-2: oklch(0.6 0.118 184.704); + --chart-3: oklch(0.398 0.07 227.392); + --chart-4: oklch(0.828 0.189 84.429); + --chart-5: oklch(0.769 0.188 70.08); + --sidebar: oklch(0.985 0.002 247.839); + --sidebar-foreground: oklch(0.13 0.028 261.692); + --sidebar-primary: oklch(0.21 0.034 264.665); + --sidebar-primary-foreground: oklch(0.985 0.002 247.839); + --sidebar-accent: oklch(0.967 0.003 264.542); + --sidebar-accent-foreground: oklch(0.21 0.034 264.665); + --sidebar-border: oklch(0.928 0.006 264.531); + --sidebar-ring: oklch(0.707 0.022 261.325); +} + +.dark { + --background: oklch(0.13 0.028 261.692); + --foreground: oklch(0.985 0.002 247.839); + --card: oklch(0.21 0.034 264.665); + --card-foreground: oklch(0.985 0.002 247.839); + --popover: oklch(0.21 0.034 264.665); + --popover-foreground: oklch(0.985 0.002 247.839); + --primary: oklch(0.928 0.006 264.531); + --primary-foreground: oklch(0.21 0.034 264.665); + --secondary: oklch(0.278 0.033 256.848); + --secondary-foreground: oklch(0.985 0.002 247.839); + --muted: oklch(0.278 0.033 256.848); + --muted-foreground: oklch(0.707 0.022 261.325); + --accent: oklch(0.278 0.033 256.848); + --accent-foreground: oklch(0.985 0.002 247.839); + --destructive: oklch(0.704 0.191 22.216); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 15%); + --ring: oklch(0.551 0.027 264.364); + --chart-1: oklch(0.488 0.243 264.376); + --chart-2: oklch(0.696 0.17 162.48); + --chart-3: oklch(0.769 0.188 70.08); + --chart-4: oklch(0.627 0.265 303.9); + --chart-5: oklch(0.645 0.246 16.439); + --sidebar: oklch(0.21 0.034 264.665); + --sidebar-foreground: oklch(0.985 0.002 247.839); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.985 0.002 247.839); + --sidebar-accent: oklch(0.278 0.033 256.848); + --sidebar-accent-foreground: oklch(0.985 0.002 247.839); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.551 0.027 264.364); +} + +@layer base { + * { + @apply border-border outline-ring/50; + } + :where(:not(:has([class*=" text-"]), :not(:has([class^="text-"])))) { + h1 { + font-size: 1.5rem; + font-weight: 700; + line-height: 1.5; + } /* text-2xl */ + h2 { + font-size: 1.25rem; + font-weight: 600; + line-height: 1.5; + } /* text-xl */ + h3 { + font-size: 1.125rem; + font-weight: 600; + line-height: 1.5; + } /* text-lg */ + p { + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + } /* text-base */ + } + + body { + @apply bg-background text-foreground; + font-family: + "Noto Sans KR", + -apple-system, + BlinkMacSystemFont, + system-ui, + Roboto, + sans-serif; + word-break: keep-all; + overflow-wrap: break-word; + } +} From a57d8f3213d6ebdeb8791abd9f5d586ab681bf18 Mon Sep 17 00:00:00 2001 From: JAESEON PARK Date: Wed, 28 Jan 2026 21:08:55 +0900 Subject: [PATCH 02/12] =?UTF-8?q?chore:=20cn=20=EC=9C=A0=ED=8B=B8=EB=A6=AC?= =?UTF-8?q?=ED=8B=B0=EB=A5=BC=20lib/utils=EB=A1=9C=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/modals/paymentAddModal.tsx | 53 ++++++++--- src/layouts/myPageLayout.tsx | 4 +- src/lib/cn.ts | 3 - src/pages/myPage/paymentPage.tsx | 41 ++++----- src/pages/myPage/reservationPage.tsx | 96 +++++++++++++++----- src/pages/myPage/settingPage.tsx | 90 ++++++++++++------- src/pages/myPage/storePage.tsx | 105 +++++++++++++++++----- src/pages/myPage/subscriptionPage.tsx | 94 ++++++++++++++----- 8 files changed, 349 insertions(+), 137 deletions(-) delete mode 100644 src/lib/cn.ts diff --git a/src/components/modals/paymentAddModal.tsx b/src/components/modals/paymentAddModal.tsx index c5441c8..8eda5a6 100644 --- a/src/components/modals/paymentAddModal.tsx +++ b/src/components/modals/paymentAddModal.tsx @@ -1,6 +1,6 @@ import { X } from "lucide-react"; import { useState } from "react"; -import { cn } from "../../lib/cn"; +import { cn } from "@/lib/utils"; interface Props { isOpen: boolean; @@ -12,10 +12,10 @@ type PaymentType = "kakao" | "toss"; export default function PaymentAddModal({ isOpen, onClose }: Props) { const [selectedType, setSelectedType] = useState("kakao"); - const handleAddSubmit = () =>{ + const handleAddSubmit = () => { alert("결제수단이 성공적으로 추가되었습니다."); onClose(); - } + }; if (!isOpen) return null; @@ -24,7 +24,10 @@ export default function PaymentAddModal({ isOpen, onClose }: Props) {

결제수단 추가

-
@@ -52,8 +55,13 @@ export default function PaymentAddModal({ isOpen, onClose }: Props) { {/* 하단 옵션 및 버튼 */}
@@ -63,8 +71,10 @@ export default function PaymentAddModal({ isOpen, onClose }: Props) { > 취소 -
@@ -75,17 +85,36 @@ export default function PaymentAddModal({ isOpen, onClose }: Props) { ); } -function PaymentTypeButton({ active, onClick, label, icon }: { active: boolean; onClick: () => void; label: string; icon: React.ReactNode }) { +function PaymentTypeButton({ + active, + onClick, + label, + icon, +}: { + active: boolean; + onClick: () => void; + label: string; + icon: React.ReactNode; +}) { return ( ); -} \ No newline at end of file +} diff --git a/src/layouts/myPageLayout.tsx b/src/layouts/myPageLayout.tsx index f1aef85..d9340d2 100644 --- a/src/layouts/myPageLayout.tsx +++ b/src/layouts/myPageLayout.tsx @@ -7,7 +7,7 @@ import { Store, User, } from "lucide-react"; -import { cn } from "../lib/cn"; +import { cn } from "@/lib/utils"; const sidebarItems = [ { to: "/mypage/info", label: "내 정보", icon: User }, @@ -56,7 +56,7 @@ export default function MyPageLayout() { "relative flex h-12 items-center gap-3 px-5 py-7 text-md font-medium transition", isActive ? "bg-blue-50 text-blue-600" - : "text-gray-700 hover:bg-gray-100" + : "text-gray-700 hover:bg-gray-100", ) } > diff --git a/src/lib/cn.ts b/src/lib/cn.ts deleted file mode 100644 index f9816e0..0000000 --- a/src/lib/cn.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function cn(...classes: (string | undefined | false)[]) { - return classes.filter(Boolean).join(" "); -} diff --git a/src/pages/myPage/paymentPage.tsx b/src/pages/myPage/paymentPage.tsx index 22ef05f..04b220c 100644 --- a/src/pages/myPage/paymentPage.tsx +++ b/src/pages/myPage/paymentPage.tsx @@ -1,6 +1,6 @@ -import { Plus, Trash2, CreditCard } from "lucide-react"; +import { Plus, Trash2 } from "lucide-react"; import { useState } from "react"; -import { cn } from "../../lib/cn"; +import { cn } from "@/lib/utils"; import PaymentAddModal from "@/components/modals/paymentAddModal"; interface PaymentMethod { @@ -34,7 +34,7 @@ export default function PaymentPage() { methods.map((m) => ({ ...m, isDefault: m.id === id, - })) + })), ); }; @@ -46,10 +46,14 @@ export default function PaymentPage() {

결제수단 관리

-

예약 시 사용할 결제수단을 관리하세요

+

+ 예약 시 사용할 결제수단을 관리하세요 +

- @@ -62,16 +66,15 @@ export default function PaymentPage() { key={method.id} className={cn( "group relative flex items-center justify-between rounded-lg border border-2 p-3 transition-all", - method.isDefault - ? "border-blue-500 bg-blue-50" - : "border-gray-100 bg-white hover:border-gray-200" + method.isDefault + ? "border-blue-500 bg-blue-50" + : "border-gray-100 bg-white hover:border-gray-200", )} >
{/* 아이콘 영역 */}
- 💛 - + 💛
{/* 정보 영역 */} @@ -85,23 +88,21 @@ export default function PaymentPage() { )}
-

- 간편결제 -

+

간편결제

{/* 액션 버튼 영역 */}
{!method.isDefault && ( - )} -
- setIsModalOpen(false)} + setIsModalOpen(false)} /> {methods.length === 0 && ( @@ -124,4 +125,4 @@ export default function PaymentPage() { )} ); -} \ No newline at end of file +} diff --git a/src/pages/myPage/reservationPage.tsx b/src/pages/myPage/reservationPage.tsx index ed8285c..2dd82dc 100644 --- a/src/pages/myPage/reservationPage.tsx +++ b/src/pages/myPage/reservationPage.tsx @@ -1,6 +1,6 @@ import { Calendar, Clock, User, CreditCard, Pencil, X } from "lucide-react"; import { useState } from "react"; -import { cn } from "../../lib/cn"; +import { cn } from "@/lib/utils"; type ReservationStatus = "전체" | "예정된 예약" | "방문 완료" | "취소된 예약"; @@ -71,7 +71,9 @@ export default function ReservationPage() {

예약 현황

-

내 예약 내역을 확인하고 관리하세요

+

+ 내 예약 내역을 확인하고 관리하세요 +

{/* 탭 메뉴 */} @@ -82,7 +84,9 @@ export default function ReservationPage() { onClick={() => setActiveTab(tab as ReservationStatus)} className={cn( "cursor-pointer pb-4 text-sm font-medium transition-all relative", - activeTab === tab ? "text-blue-600" : "text-gray-800 hover:text-gray-600" + activeTab === tab + ? "text-blue-600" + : "text-gray-800 hover:text-gray-600", )} > {tab} @@ -97,17 +101,25 @@ export default function ReservationPage() {
{filteredReservations.length > 0 ? ( filteredReservations.map((res) => ( -
+

{res.shopName}

- + {res.status}
@@ -117,18 +129,41 @@ export default function ReservationPage() { {/* 상세 정보 그리드 */}
- } label="예약 날짜" value={res.date} /> - } label="예약 시간" value={res.time} /> - } label="인원" value={res.people} /> - } label="결제 정보" value={`${res.payment}\n${res.method}`} isMultiLine /> + } + label="예약 날짜" + value={res.date} + /> + } + label="예약 시간" + value={res.time} + /> + } + label="인원" + value={res.people} + /> + } + label="결제 정보" + value={`${res.payment}\n${res.method}`} + isMultiLine + />
{/* 하단 버튼 영역 */}
- {res.step} + + {res.step} +
{res.status === "예약 확정" && ( <> @@ -160,18 +195,31 @@ export default function ReservationPage() { } // 정보 아이템 컴포넌트 -function InfoItem({ icon, label, value, isMultiLine = false }: { icon: React.ReactNode, label: string, value: string, isMultiLine?: boolean }) { +function InfoItem({ + icon, + label, + value, + isMultiLine = false, +}: { + icon: React.ReactNode; + label: string; + value: string; + isMultiLine?: boolean; +}) { return (
-
- {icon} -
+
{icon}

{label}

-

+

{value}

); -} \ No newline at end of file +} diff --git a/src/pages/myPage/settingPage.tsx b/src/pages/myPage/settingPage.tsx index 547432d..7aa6ed1 100644 --- a/src/pages/myPage/settingPage.tsx +++ b/src/pages/myPage/settingPage.tsx @@ -1,6 +1,6 @@ import { Lock, Bell, Trash2 } from "lucide-react"; import { useState } from "react"; -import { cn } from "../../lib/cn"; +import { cn } from "@/lib/utils"; export default function SettingsPage() { // 알림 설정을 위한 상태 관리 @@ -28,8 +28,12 @@ export default function SettingsPage() {
-

비밀번호 변경

-

정기적인 비밀번호 변경으로 계정을 안전하게 보호하세요

+

+ 비밀번호 변경 +

+

+ 정기적인 비밀번호 변경으로 계정을 안전하게 보호하세요 +

); -} \ No newline at end of file +} diff --git a/src/pages/myPage/storePage.tsx b/src/pages/myPage/storePage.tsx index b0a455e..22b5682 100644 --- a/src/pages/myPage/storePage.tsx +++ b/src/pages/myPage/storePage.tsx @@ -1,11 +1,36 @@ -import { Store, Calendar, Star, Plus, ChevronRight, BarChart3 } from "lucide-react"; -import { cn } from "../../lib/cn"; +import { + Store, + Calendar, + Star, + Plus, + ChevronRight, + BarChart3, +} from "lucide-react"; +import { cn } from "@/lib/utils"; export default function StorePage() { const stats = [ - { label: "총 가게 수", value: "3개", icon: , bgColor: "bg-blue-50", iconColor: "text-blue-500" }, - { label: "총 예약 수", value: "2126건", icon: , bgColor: "bg-indigo-50", iconColor: "text-indigo-500" }, - { label: "평균 평점", value: "4.8", icon: , bgColor: "bg-green-50", iconColor: "text-yellow-500" }, + { + label: "총 가게 수", + value: "3개", + icon: , + bgColor: "bg-blue-50", + iconColor: "text-blue-500", + }, + { + label: "총 예약 수", + value: "2126건", + icon: , + bgColor: "bg-indigo-50", + iconColor: "text-indigo-500", + }, + { + label: "평균 평점", + value: "4.8", + icon: , + bgColor: "bg-green-50", + iconColor: "text-yellow-500", + }, ]; const shops = [ @@ -38,7 +63,8 @@ export default function StorePage() { totalReservations: "-", rating: "-", reviews: "-", - notice: "가게 승인 대기 중입니다. 영업일 기준 1-2일 내에 승인이 완료됩니다.", + notice: + "가게 승인 대기 중입니다. 영업일 기준 1-2일 내에 승인이 완료됩니다.", }, ]; @@ -47,7 +73,9 @@ export default function StorePage() {

내 가게 관리

-

등록한 식당을 관리하고 대시보드로 이동하세요

+

+ 등록한 식당을 관리하고 대시보드로 이동하세요 +

); -} \ No newline at end of file +} diff --git a/src/pages/myPage/subscriptionPage.tsx b/src/pages/myPage/subscriptionPage.tsx index 40ce119..c31b2ee 100644 --- a/src/pages/myPage/subscriptionPage.tsx +++ b/src/pages/myPage/subscriptionPage.tsx @@ -1,9 +1,11 @@ import { Check, Crown } from "lucide-react"; import { useState } from "react"; -import { cn } from "../../lib/cn"; +import { cn } from "@/lib/utils"; export default function SubscriptionPage() { - const [billingCycle, setBillingCycle] = useState<"monthly" | "yearly">("monthly"); + const [billingCycle, setBillingCycle] = useState<"monthly" | "yearly">( + "monthly", + ); // 현재 사용 중인 플랜 이름을 관리하는 상태 (기본값: 무료) const [selectedPlan, setSelectedPlan] = useState("무료"); @@ -17,24 +19,50 @@ export default function SubscriptionPage() { { name: "무료", price: 0, - features: ["기본 예약 기능", "월 3회 예약 가능", "일반 리뷰 작성", "기본 알림"], + features: [ + "기본 예약 기능", + "월 3회 예약 가능", + "일반 리뷰 작성", + "기본 알림", + ], }, { name: "베이직", price: billingCycle === "monthly" ? 9900 : 99000, - features: ["무제한 예약", "우선 예약 혜택", "리뷰 작성 포인트 적립", "실시간 알림", "예약 변경 수수료 면제"], + features: [ + "무제한 예약", + "우선 예약 혜택", + "리뷰 작성 포인트 적립", + "실시간 알림", + "예약 변경 수수료 면제", + ], }, { name: "프리미엄", price: billingCycle === "monthly" ? 19900 : 199000, - features: ["베이직 플랜 모든 혜택", "AI맞춤 식당 추천", "VIP 예약 우선권", "특별 할인 쿠폰", "프리미엄 고객 지원", "동반 1인 무료 혜택"], + features: [ + "베이직 플랜 모든 혜택", + "AI맞춤 식당 추천", + "VIP 예약 우선권", + "특별 할인 쿠폰", + "프리미엄 고객 지원", + "동반 1인 무료 혜택", + ], isRecommended: true, // 추천 플랜 표시를 위한 플래그 }, { name: "비즈니스 (사장님)", price: billingCycle === "monthly" ? 49900 : 499000, - features: ["식당 등록 및 관리", "통합 대시보드", "예약 관리 시스템", "결제 및 정산 기능", "AI 데이터 인사이트", "프리미엄 매장 노출", "24/7 전담 지원"], - } + features: [ + "식당 등록 및 관리", + "통합 대시보드", + "예약 관리 시스템", + "결제 및 정산 기능", + "AI 데이터 인사이트", + "프리미엄 매장 노출", + "24/7 전담 지원", + ], + }, ]; // 플랜 변경 핸들러 @@ -52,7 +80,11 @@ export default function SubscriptionPage() { }; const handleCancel = () => { - if (confirm("정말로 구독을 취소하시겠습니까? 다음 결제일부터는 혜택을 이용하실 수 없습니다.")) { + if ( + confirm( + "정말로 구독을 취소하시겠습니까? 다음 결제일부터는 혜택을 이용하실 수 없습니다.", + ) + ) { setSelectedPlan("무료"); // 취소 시 무료 플랜으로 변경 예시 alert("구독 취소가 완료되었습니다."); } @@ -62,19 +94,21 @@ export default function SubscriptionPage() {

구독 관리

-

나에게 맞는 플랜을 선택하세요

+

+ 나에게 맞는 플랜을 선택하세요 +

{/* 현재 플랜 요약 박스 */}
- + 현재 플랜

{selectedPlan}

- + {/* 결제일 정보: 무료 플랜이 아닐 때만 표시 */} {selectedPlan !== "무료" && (
@@ -83,7 +117,9 @@ export default function SubscriptionPage() {
)} {selectedPlan === "무료" && ( -

무료로 잇츠파인을 이용 중입니다

+

+ 무료로 잇츠파인을 이용 중입니다 +

)}
@@ -94,7 +130,7 @@ export default function SubscriptionPage() { onClick={() => setBillingCycle("monthly")} className={cn( "cursor-pointer relative z-10 px-6 py-2 text-sm font-medium transition-colors", - billingCycle === "monthly" ? "text-white" : "text-gray-500" + billingCycle === "monthly" ? "text-white" : "text-gray-500", )} > 월간 결제 @@ -103,7 +139,7 @@ export default function SubscriptionPage() { onClick={() => setBillingCycle("yearly")} className={cn( "cursor-pointer relative z-10 px-6 py-2 text-sm font-medium transition-colors", - billingCycle === "yearly" ? "text-white" : "text-gray-500" + billingCycle === "yearly" ? "text-white" : "text-gray-500", )} > 연간 결제 @@ -114,7 +150,7 @@ export default function SubscriptionPage() {
@@ -131,8 +167,11 @@ export default function SubscriptionPage() { key={plan.name} className={cn( "relative flex flex-col rounded-2xl border-2 p-5 transition-all", - isCurrent ? "border-blue-500 bg-blue-50 shadow-md" : - isRecommended ? "border-blue-400 bg-white shadow-sm" : "border-gray-100" + isCurrent + ? "border-blue-500 bg-blue-50 shadow-md" + : isRecommended + ? "border-blue-400 bg-white shadow-sm" + : "border-gray-100", )} > {isCurrent && ( @@ -140,7 +179,7 @@ export default function SubscriptionPage() { 현재 플랜
)} - + {!isCurrent && isRecommended && (
추천 @@ -153,13 +192,18 @@ export default function SubscriptionPage() { ₩{plan.price.toLocaleString()} - / {billingCycle === "monthly" ? "월" : "년"} + + / {billingCycle === "monthly" ? "월" : "년"} +
    {plan.features.map((feature) => ( -
  • +
  • {feature}
  • @@ -174,8 +218,8 @@ export default function SubscriptionPage() { isCurrent ? "bg-gray-100 text-gray-400 cursor-default" : isRecommended - ? "bg-blue-500 text-white hover:bg-blue-600 shadow-md" - : "bg-white border-2 border-gray-200 text-gray-700 hover:bg-gray-50" + ? "bg-blue-500 text-white hover:bg-blue-600 shadow-md" + : "bg-white border-2 border-gray-200 text-gray-700 hover:bg-gray-50", )} > {isCurrent ? "현재 이용 중" : "플랜 선택"} @@ -190,7 +234,9 @@ export default function SubscriptionPage() {

    구독 관리

    -

    구독을 일시정지하거나 취소할 수 있습니다

    +

    + 구독을 일시정지하거나 취소할 수 있습니다 +