+ {/* ── 입금자명 입력 ── */}
+
+
+ {/* ── 예시 이미지 ── */}
+
+
예시
+
+
+ Toss 앱 입금자명 설정 예시 이미지
+
+
+
+
+ {/* ── 안내 가이드 (Frame 2612440) ── */}
+
+ {/* 유의사항 */}
+
+
유의사항
+
+ 코매칭에 보내실 입금자명을 입력해 주세요. 입금자명은 한글이나
+ 영문자로 6자 이내입니다. 특수문자는 사용할 수 없습니다. Toss 앱에
+ 사전 설정된 입금자명을 입력하시면 간편합니다. 나중에 다시 수정할 수
+ 있어요!
+
+
+
+ {/* FAQ */}
+
+
+ 왜 입금자명을 설정해야 하나요?
+
+
+ 모든 포인트 충전은 계좌이체로 진행되고 있어요. 충전 간 복잡함을
+ 줄이기 위해, 사전에 입금자명을 설정하시면 더욱 편리하고 쾌적한
+ 코매칭을 즐기실 수 있습니다.
+
+
+
+
+ );
+}
diff --git a/components/common/charge/QuickBundleCard.tsx b/components/common/charge/QuickBundleCard.tsx
new file mode 100644
index 0000000..b7f26c5
--- /dev/null
+++ b/components/common/charge/QuickBundleCard.tsx
@@ -0,0 +1,51 @@
+"use client";
+
+import React from "react";
+import Image from "next/image";
+import { ICON_SIZE } from "@/lib/constants/charge";
+
+interface QuickBundleCardProps {
+ title: string;
+ icon: string;
+ description: string;
+ bonus: string;
+ price: string;
+}
+
+export default function QuickBundleCard({
+ title,
+ icon,
+ description,
+ bonus,
+ price,
+}: QuickBundleCardProps) {
+ return (
+
+ {/* ── 보유현황 카드 ── */}
+
+
+ {/* ── 빠른 구매 ── */}
+
+
빠른 구매
+
+ {QUICK_BUNDLES.map((bundle) => (
+
+ ))}
+
+
+
+ {/* ── 전체 ── */}
+
+
전체
+
+ {INDIVIDUAL_ITEMS.map((item) => (
+
+
+ {item.label}
+
+
+
+ ))}
+
+
+
+ {/* ── 번들 ── */}
+
+
번들
+
+ {BUNDLE_ITEMS.map((item) => (
+
+
+
+
+ {item.title}
+
+
+ {item.description}
+
+
+
+ {item.bonus}
+
+
+
+
+ ))}
+
+
+
+ {/* ── 이용안내 ── */}
+
+
이용안내
+
+
+ {USAGE_INFO}
+
+
+ {BUSINESS_INFO}
+
+
+
+
+ );
+}
diff --git a/components/ui/drawer.tsx b/components/ui/drawer.tsx
index 0e50b52..ae1eaa4 100644
--- a/components/ui/drawer.tsx
+++ b/components/ui/drawer.tsx
@@ -65,7 +65,7 @@ function DrawerContent({
className={cn(
"group/drawer-content bg-background fixed z-50 flex h-auto flex-col",
"data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:max-h-[96vh] data-[vaul-drawer-direction=top]:rounded-b-lg data-[vaul-drawer-direction=top]:border-b",
- "data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:max-h-[96vh] data-[vaul-drawer-direction=bottom]:rounded-t-lg data-[vaul-drawer-direction=bottom]:border-t",
+ "data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mx-auto data-[vaul-drawer-direction=bottom]:max-h-[96vh] data-[vaul-drawer-direction=bottom]:max-w-[430px] data-[vaul-drawer-direction=bottom]:rounded-t-lg data-[vaul-drawer-direction=bottom]:border-t",
"data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=right]:sm:max-w-sm",
"data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=left]:sm:max-w-sm",
"after:hidden",
diff --git a/lib/constants/charge.ts b/lib/constants/charge.ts
new file mode 100644
index 0000000..9228882
--- /dev/null
+++ b/lib/constants/charge.ts
@@ -0,0 +1,136 @@
+/* ── 아이콘 사이즈 ── */
+export const ICON_SIZE = {
+ sm: 24,
+ lg: 80,
+} as const;
+
+/* ── 보유현황 아이콘·라벨 ── */
+export const INVENTORY_ROWS = [
+ {
+ icon: "/main/coin.png",
+ alt: "coin",
+ label: "보유 뽑기권",
+ key: "matching",
+ },
+ {
+ icon: "/main/elec-bulb.png",
+ alt: "bulb",
+ label: "보유 아이템",
+ key: "option",
+ },
+] as const;
+
+/* ── 구매 가능 한도 (임시) ── */
+export const PURCHASE_LIMITS = {
+ matching: { current: 18, max: 30, label: "뽑기권" },
+ option: { current: 42, max: 60, label: "아이템" },
+} as const;
+
+/* ── 빠른 구매 번들 카드 ── */
+export const QUICK_BUNDLES = [
+ {
+ title: "실속 번들",
+ icon: "/main/coin.png",
+ description: "뽑기권 5개+옵션권 2개",
+ bonus: "옵션권 1개 무료 증정!",
+ price: "5,000원",
+ },
+ {
+ title: "슈퍼 번들",
+ icon: "/main/coin.png",
+ description: "뽑기권 10개+옵션권 10개",
+ bonus: "옵션권 5개 무료 증정!",
+ price: "10,000원",
+ },
+] as const;
+
+/* ── 가격 상수 ── */
+export const ITEM_PRICES = {
+ matching: 1000,
+ option: 200,
+} as const;
+
+/* ── 전체(개별) 아이템 ── */
+export const INDIVIDUAL_ITEMS = [
+ {
+ label: "뽑기권 1개",
+ price: `${ITEM_PRICES.matching.toLocaleString()}원`,
+ },
+ {
+ label: "옵션권 1개",
+ price: `${ITEM_PRICES.option.toLocaleString()}원`,
+ },
+] as const;
+
+/* ── 번들 아이템 ── */
+export const BUNDLE_ITEMS = [
+ {
+ title: "미니 번들",
+ description: "옵션권 3개",
+ bonus: "옵션권 1개 무료 증정!",
+ price: "2,500원",
+ },
+ {
+ title: "실속 번들",
+ description: "뽑기권 5개+옵션권 2개",
+ bonus: "옵션권 1개 무료 증정!",
+ price: "5,000원",
+ },
+ {
+ title: "슈퍼 번들",
+ description: "뽑기권 10개+옵션권 10개",
+ bonus: "옵션권 5개 무료 증정!",
+ price: "10,000원",
+ },
+] as const;
+
+/* ── 이용안내 및 사업자 정보 ── */
+export const USAGE_INFO = `충전된 포인트의 소멸시효 기한은 충전 후 5년입니다.
+1 포인트는 1원입니다.
+충전한 포인트로 서비스를 이용할 수 있습니다.
+포인트는 이벤트 포인트 먼저 사용되고, 유상 포인트가 사용됩니다.
+이벤트 포인트는 유효기한이 임박한 순으로 먼저 사용됩니다.
+유효기간은 포인트 충전내역을 통해 확인하실 수 있습니다.`;
+
+export const NOTICE_INFO = "결제 혹은 환불에 필요한 유의사항을 적습니다.";
+
+export const BUSINESS_INFO =
+ "대표이사 천승환 | 호스팅서비스사업자 코매칭 | 사업자 등록번호 843-27-01742 | 통신판매신고 2024-부천원미-2812 | 대표전화 010-3039-7387 | 경기도 부천시 조마루로 366번길 27, 401호";
+
+/* ── 충전 내역 (임시) ── */
+export const CHARGE_HISTORY = [
+ {
+ id: 1,
+ date: "2024.03.20",
+ orderId: "20240320-0001",
+ points: "뽑기권 5개",
+ paymentAmount: "5,000원",
+ status: "success",
+ statusLabel: "결제완료",
+ },
+ {
+ id: 2,
+ date: "2024.03.18",
+ orderId: "20240318-0042",
+ points: "옵션권 10개",
+ paymentAmount: "5,000원",
+ status: "cancelled",
+ statusLabel: "결제취소",
+ },
+ {
+ id: 3,
+ date: "2024.03.15",
+ orderId: "20240315-0012",
+ points: "뽑기권 1개 (이벤트)",
+ paymentAmount: "0원",
+ status: "event",
+ statusLabel: "이벤트 증정",
+ },
+] as const;
+
+/* ── 탭 정의 ── */
+export const TABS = [
+ { label: "상점", title: "상점" },
+ { label: "충전내역", title: "충전내역" },
+ { label: "입금자명 설정", title: "입금자명 설정" },
+] as const;
diff --git a/lib/validators.ts b/lib/validators.ts
index aabcecf..daeca7a 100644
--- a/lib/validators.ts
+++ b/lib/validators.ts
@@ -14,3 +14,8 @@ export const validatePasswordPattern = (password: string): boolean => {
/^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]+$/;
return passwordRegex.test(password);
};
+
+export const isValidDepositorName = (text: string): boolean => {
+ const regex = /^[a-zA-Z가-힣ㄱ-ㅎㅏ-ㅣ]*$/;
+ return regex.test(text);
+};