merrycoral b09fac2396 이벤트 생성 플로우 개선 및 API 통합
- RecommendationStep 컴포넌트 확장 및 기능 개선
- 이벤트 API 및 AI API 연동 강화
- 인증 관련 훅 기능 확장
- 타입 정의 및 에러 처리 개선

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 15:58:56 +09:00

190 lines
5.5 KiB
TypeScript

'use client';
import { useFunnel } from '@use-funnel/browser';
import { useRouter } from 'next/navigation';
import ObjectiveStep from './steps/ObjectiveStep';
import RecommendationStep from './steps/RecommendationStep';
import ContentPreviewStep from './steps/ContentPreviewStep';
import ContentEditStep from './steps/ContentEditStep';
import ChannelStep from './steps/ChannelStep';
import ApprovalStep from './steps/ApprovalStep';
// 이벤트 생성 데이터 타입
export type EventObjective = 'new_customer' | 'revisit' | 'sales' | 'awareness';
export type BudgetLevel = 'low' | 'medium' | 'high';
export type EventMethod = 'online' | 'offline';
export interface EventData {
eventDraftId?: number;
eventId?: string;
objective?: EventObjective;
recommendation?: {
recommendation: {
optionNumber: number;
concept: string;
title: string;
description: string;
targetAudience: string;
duration: {
recommendedDays: number;
recommendedPeriod?: string;
};
mechanics: {
type: 'DISCOUNT' | 'GIFT' | 'STAMP' | 'EXPERIENCE' | 'LOTTERY' | 'COMBO';
details: string;
};
promotionChannels: string[];
estimatedCost: {
min: number;
max: number;
breakdown?: {
material?: number;
promotion?: number;
discount?: number;
};
};
expectedMetrics: {
newCustomers: { min: number; max: number };
repeatVisits?: { min: number; max: number };
revenueIncrease: { min: number; max: number };
roi: { min: number; max: number };
socialEngagement?: {
estimatedPosts: number;
estimatedReach: number;
};
};
differentiator: string;
};
eventId: string;
};
contentPreview?: {
imageStyle: string;
images?: any[];
};
contentEdit?: {
title: string;
prize: string;
guide: string;
};
channels?: string[];
}
export default function EventCreatePage() {
const router = useRouter();
const funnel = useFunnel<{
objective: EventData;
recommendation: EventData;
contentPreview: EventData;
contentEdit: EventData;
channel: EventData;
approval: EventData;
}>({
id: 'event-creation',
initial: {
step: 'objective',
context: {},
},
});
const handleComplete = () => {
// 이벤트 생성 완료 후 대시보드로 이동
router.push('/');
};
return (
<funnel.Render
objective={({ history }) => (
<ObjectiveStep
onNext={({ objective, eventId }) => {
history.push('recommendation', { objective, eventId });
}}
/>
)}
recommendation={({ context, history }) => (
<RecommendationStep
eventId={context.eventId}
objective={context.objective}
onNext={(recommendation) => {
history.push('channel', { ...context, recommendation });
}}
onBack={() => {
history.go(-1);
}}
/>
)}
channel={({ context, history }) => (
<ChannelStep
onNext={(channels) => {
// 우리동네TV, 지니TV, SNS 중 하나라도 포함되어 있으면 contentPreview로
const needsContent = channels.some((ch) =>
['uriTV', 'genieTV', 'sns'].includes(ch)
);
if (needsContent) {
// localStorage에 이벤트 정보 저장
const eventData = {
eventDraftId: context.recommendation?.eventId || String(Date.now()), // eventId 사용
eventTitle: context.recommendation?.recommendation.title || '',
eventDescription: context.recommendation?.recommendation.description || '',
industry: '',
location: '',
trends: context.recommendation?.recommendation.promotionChannels || [],
prize: '',
};
localStorage.setItem('eventCreationData', JSON.stringify(eventData));
history.push('contentPreview', { ...context, channels });
} else {
history.push('approval', { ...context, channels });
}
}}
onBack={() => {
history.go(-1);
}}
/>
)}
contentPreview={({ context, history }) => (
<ContentPreviewStep
eventId={context.recommendation?.eventId}
eventTitle={context.recommendation?.recommendation.title}
eventDescription={context.recommendation?.recommendation.description}
onNext={(imageStyle, images) => {
history.push('contentEdit', {
...context,
contentPreview: { imageStyle, images },
});
}}
onSkip={() => {
history.push('approval', context);
}}
onBack={() => {
history.go(-1);
}}
/>
)}
contentEdit={({ context, history }) => (
<ContentEditStep
initialTitle={context.recommendation?.recommendation.title || ''}
initialPrize={''}
onNext={(contentEdit) => {
history.push('approval', { ...context, contentEdit });
}}
onBack={() => {
history.go(-1);
}}
/>
)}
approval={({ context, history }) => (
<ApprovalStep
eventData={context}
onApprove={handleComplete}
onBack={() => {
history.go(-1);
}}
/>
)}
/>
);
}