diff --git a/app/components/PaymentButton.tsx b/app/components/PaymentButton.tsx
index 37ebc6d..250f017 100644
--- a/app/components/PaymentButton.tsx
+++ b/app/components/PaymentButton.tsx
@@ -38,7 +38,7 @@ export default function PaymentButton({ productId, className, style, children, r
await supabase.from('profiles').upsert({ id: user.id, email: user.email }, { onConflict: 'id' });
// 3. Supabase에 order 생성
- const paymentId = `order_${Date.now()}_${crypto.randomUUID().slice(0, 8)}`;
+ const paymentId = crypto.randomUUID();
const { error: orderError } = await supabase
.from('orders')
.insert({
@@ -53,10 +53,8 @@ export default function PaymentButton({ productId, className, style, children, r
if (orderError) throw new Error('주문 생성 실패: ' + orderError.message);
// 4. 포트원 V2 결제 요청
- const storeId = process.env.NEXT_PUBLIC_PORTONE_STORE_ID!;
-
const response = await PortOne.requestPayment({
- storeId,
+ storeId: process.env.NEXT_PUBLIC_PORTONE_STORE_ID ?? '',
channelKey: channel.channelKey,
paymentId,
orderName: product.name,
@@ -122,7 +120,7 @@ export default function PaymentButton({ productId, className, style, children, r
if (!product) return null;
- const isTestMode = process.env.NEXT_PUBLIC_PORTONE_STORE_ID?.includes('test')
+ const isTestMode = !process.env.NEXT_PUBLIC_PORTONE_STORE_ID
|| process.env.NODE_ENV === 'development';
return (
diff --git a/app/components/Sidebar.tsx b/app/components/Sidebar.tsx
index 85c6897..dbc4323 100644
--- a/app/components/Sidebar.tsx
+++ b/app/components/Sidebar.tsx
@@ -5,76 +5,134 @@ import { usePathname, useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
import { createClient } from '@/lib/supabase/client';
-const navItems = [
+/* ── 3구역 네비게이션 구조 ─────────────────────────────────── */
+
+interface NavItem {
+ href: string;
+ label: string;
+ badge?: string;
+ icon: React.ReactNode;
+}
+
+interface NavGroup {
+ title: string;
+ items: NavItem[];
+}
+
+const navGroups: NavGroup[] = [
{
- href: '/',
- label: '홈',
- icon: (
-
- ),
+ title: 'AI 상품',
+ items: [
+ {
+ href: '/services/prompt',
+ label: '프롬프트 스토어',
+ badge: 'HOT',
+ icon: (
+
+ ),
+ },
+ {
+ href: '/services/automation',
+ label: '업무 자동화',
+ icon: (
+
+ ),
+ },
+ {
+ href: '/services/ai-kit',
+ label: 'AI 자동화 키트',
+ badge: '구독',
+ icon: (
+
+ ),
+ },
+ ],
},
{
- href: '/services/website',
- label: '홈페이지 제작',
- badge: 'NEW',
- icon: (
-
- ),
+ title: '무료 도구',
+ items: [
+ {
+ href: '/saju',
+ label: 'AI 사주 분석',
+ badge: '무료',
+ icon: (
+
+ ),
+ },
+ {
+ href: '/services/lotto',
+ label: '로또 번호 추천',
+ badge: '무료',
+ icon: (
+
+ ),
+ },
+ {
+ href: '/tools',
+ label: '도구 쇼케이스',
+ badge: 'DEMO',
+ icon: (
+
+ ),
+ },
+ ],
},
{
- href: '/services/automation',
- label: '업무 자동화',
- icon: (
-
- ),
- },
- {
- href: '/services/prompt',
- label: '프롬프트 엔지니어링',
- icon: (
-
- ),
- },
- {
- href: '/services/ai-kit',
- label: 'AI 자동화 키트',
- badge: 'NEW',
- icon: (
-
- ),
- },
- {
- href: '/saju',
- label: 'AI 사주 분석',
- icon: (
-
- ),
- },
- {
- href: '/tools',
- label: '여긴 뭐 만들어요?',
- badge: 'DEMO',
- icon: (
-
- ),
+ title: '외주 의뢰',
+ items: [
+ {
+ href: '/freelance',
+ label: '외주 개발 문의',
+ icon: (
+
+ ),
+ },
+ {
+ href: '/services/website',
+ label: '홈페이지 제작',
+ icon: (
+
+ ),
+ },
+ ],
},
];
+/* ── 배지 색상 ─────────────────────────────────────────────── */
+function badgeStyle(badge: string) {
+ switch (badge) {
+ case 'HOT':
+ return 'bg-rose-500/15 text-rose-400';
+ case '구독':
+ return 'bg-violet-500/15 text-violet-400';
+ case '무료':
+ return 'bg-sky-500/15 text-sky-400';
+ case 'DEMO':
+ return 'bg-amber-500/15 text-amber-400';
+ default:
+ return 'bg-emerald-500/15 text-emerald-400';
+ }
+}
+
+/* ── 컴포넌트 ──────────────────────────────────────────────── */
+
interface SidebarProps {
isOpen: boolean;
onClose: () => void;
@@ -129,7 +187,7 @@ export default function Sidebar({ isOpen, onClose }: SidebarProps) {
쟁승메이드
-
박재오의 개발 공방
+
AI 프롬프트 · 자동화 스토어
@@ -137,34 +195,68 @@ export default function Sidebar({ isOpen, onClose }: SidebarProps) {
{/* Navigation */}
-