From a62aa9bae81b2845fcb737961cec9ba909de14be Mon Sep 17 00:00:00 2001 From: merrycoral Date: Wed, 29 Oct 2025 15:03:37 +0900 Subject: [PATCH] =?UTF-8?q?=EC=9D=B4=EB=B2=A4=ED=8A=B8=20API=20=EB=B0=8F?= =?UTF-8?q?=20=ED=83=80=EC=9E=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../events/create/steps/ApprovalStep.tsx | 93 ++++++++++++++++++- src/entities/event/api/eventApi.ts | 49 ++++++++++ src/entities/event/model/types.ts | 25 +++++ 3 files changed, 162 insertions(+), 5 deletions(-) diff --git a/src/app/(main)/events/create/steps/ApprovalStep.tsx b/src/app/(main)/events/create/steps/ApprovalStep.tsx index 465029e..5f5b536 100644 --- a/src/app/(main)/events/create/steps/ApprovalStep.tsx +++ b/src/app/(main)/events/create/steps/ApprovalStep.tsx @@ -20,6 +20,7 @@ import { import { ArrowBack, CheckCircle, Edit, RocketLaunch, Save, People, AttachMoney, TrendingUp } from '@mui/icons-material'; import { EventData } from '../page'; import { cardStyles, colors, responsiveText } from '@/shared/lib/button-styles'; +import { eventApi } from '@/entities/event/api/eventApi'; interface ApprovalStepProps { eventData: EventData; @@ -33,16 +34,98 @@ export default function ApprovalStep({ eventData, onApprove, onBack }: ApprovalS const [successDialogOpen, setSuccessDialogOpen] = useState(false); const [isDeploying, setIsDeploying] = useState(false); - const handleApprove = () => { + const handleApprove = async () => { if (!agreeTerms) return; setIsDeploying(true); - // ๋ฐฐํฌ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ - setTimeout(() => { + try { + // 1. ์ด๋ฒคํŠธ ์ƒ์„ฑ API ํ˜ธ์ถœ + console.log('๐Ÿ“ž Creating event with objective:', eventData.objective); + + // objective ๋งคํ•‘ (Frontend โ†’ Backend) + const objectiveMap: Record = { + 'new_customer': 'CUSTOMER_ACQUISITION', + 'revisit': 'Customer Retention', + 'sales': 'Sales Promotion', + 'awareness': 'awareness', + }; + + const backendObjective = objectiveMap[eventData.objective || 'new_customer'] || 'CUSTOMER_ACQUISITION'; + + const createResponse = await eventApi.createEvent({ + objective: backendObjective, + }); + + console.log('โœ… Event created:', createResponse); + + if (createResponse.success && createResponse.data) { + const eventId = createResponse.data.eventId; + console.log('๐ŸŽฏ Event ID:', eventId); + + // 2. ์ด๋ฒคํŠธ ์ƒ์„ธ ์ •๋ณด ์—…๋ฐ์ดํŠธ + console.log('๐Ÿ“ž Updating event details:', eventId); + + // ์ด๋ฒคํŠธ๋ช… ๊ฐ€์ ธ์˜ค๊ธฐ (contentEdit.title ๋˜๋Š” recommendation.title) + const eventName = eventData.contentEdit?.title || eventData.recommendation?.title || '์ด๋ฒคํŠธ'; + + // ๋‚ ์งœ ์„ค์ • (์˜ค๋Š˜๋ถ€ํ„ฐ 30์ผ๊ฐ„) + const today = new Date(); + const endDate = new Date(today); + endDate.setDate(endDate.getDate() + 30); + + const startDateStr = today.toISOString().split('T')[0]; // YYYY-MM-DD + const endDateStr = endDate.toISOString().split('T')[0]; + + await eventApi.updateEvent(eventId, { + eventName: eventName, + description: eventData.contentEdit?.guide || eventData.recommendation?.participationMethod, + startDate: startDateStr, + endDate: endDateStr, + }); + console.log('โœ… Event details updated'); + + // 3. ๋ฐฐํฌ ์ฑ„๋„ ์„ ํƒ + if (eventData.channels && eventData.channels.length > 0) { + console.log('๐Ÿ“ž Selecting channels:', eventData.channels); + + // ์ฑ„๋„๋ช… ๋งคํ•‘ (Frontend โ†’ Backend) + const channelMap: Record = { + 'uriTV': 'WEBSITE', + 'ringoBiz': 'EMAIL', + 'genieTV': 'KAKAO', + 'sns': 'INSTAGRAM', + }; + + const backendChannels = eventData.channels.map(ch => channelMap[ch] || ch.toUpperCase()); + + await eventApi.selectChannels(eventId, { + channels: backendChannels, + }); + console.log('โœ… Channels selected'); + } + + // 4. TODO: ์ด๋ฏธ์ง€ ์„ ํƒ + // ํ˜„์žฌ frontend์—์„œ selectedImageId๋ฅผ ์ถ”์ ํ•˜์ง€ ์•Š์Œ + // ํ–ฅํ›„ contentPreview ๋‹จ๊ณ„์—์„œ ์„ ํƒ๋œ ์ด๋ฏธ์ง€ ID๋ฅผ eventData์— ์ €์žฅ ํ•„์š” + console.log('โš ๏ธ Image selection skipped - imageId not tracked in frontend'); + + // 5. ์ด๋ฒคํŠธ ๋ฐฐํฌ API ํ˜ธ์ถœ + console.log('๐Ÿ“ž Publishing event:', eventId); + const publishResponse = await eventApi.publishEvent(eventId); + console.log('โœ… Event published:', publishResponse); + + // ์„ฑ๊ณต ๋‹ค์ด์–ผ๋กœ๊ทธ ํ‘œ์‹œ + setIsDeploying(false); + setSuccessDialogOpen(true); + } else { + throw new Error('Event creation failed: No event ID returned'); + } + } catch (error) { + console.error('โŒ Event deployment failed:', error); setIsDeploying(false); - setSuccessDialogOpen(true); - }, 2000); + alert('์ด๋ฒคํŠธ ๋ฐฐํฌ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ์‹œ๋„ํ•ด ์ฃผ์„ธ์š”.'); + } }; const handleSaveDraft = () => { diff --git a/src/entities/event/api/eventApi.ts b/src/entities/event/api/eventApi.ts index 929eefe..6820d7a 100644 --- a/src/entities/event/api/eventApi.ts +++ b/src/entities/event/api/eventApi.ts @@ -10,6 +10,9 @@ import type { JobAcceptedResponse, ImageGenerationRequest, ImageGenerationResponse, + UpdateEventRequest, + SelectChannelsRequest, + SelectImageRequest, } from '../model/types'; /** @@ -193,6 +196,52 @@ export const eventApi = { ); return response.data; }, + + /** + * ์ด๋ฒคํŠธ ์ˆ˜์ • + */ + updateEvent: async ( + eventId: string, + data: UpdateEventRequest + ): Promise> => { + console.log('๐Ÿ“ž eventApi.updateEvent ํ˜ธ์ถœ', eventId, data); + const response = await eventApiClient.put>( + `${EVENT_API_BASE}/${eventId}`, + data + ); + return response.data; + }, + + /** + * ๋ฐฐํฌ ์ฑ„๋„ ์„ ํƒ + */ + selectChannels: async ( + eventId: string, + data: SelectChannelsRequest + ): Promise> => { + console.log('๐Ÿ“ž eventApi.selectChannels ํ˜ธ์ถœ', eventId, data); + const response = await eventApiClient.put>( + `${EVENT_API_BASE}/${eventId}/channels`, + data + ); + return response.data; + }, + + /** + * ์ด๋ฏธ์ง€ ์„ ํƒ + */ + selectImage: async ( + eventId: string, + imageId: string, + data: SelectImageRequest + ): Promise> => { + console.log('๐Ÿ“ž eventApi.selectImage ํ˜ธ์ถœ', eventId, imageId, data); + const response = await eventApiClient.put>( + `${EVENT_API_BASE}/${eventId}/images/${imageId}/select`, + data + ); + return response.data; + }, }; export default eventApi; diff --git a/src/entities/event/model/types.ts b/src/entities/event/model/types.ts index b3de860..c9d9b37 100644 --- a/src/entities/event/model/types.ts +++ b/src/entities/event/model/types.ts @@ -171,3 +171,28 @@ export interface ImageGenerationResponse { eventId: string; status: string; } + +/** + * ์ด๋ฒคํŠธ ์ˆ˜์ • ์š”์ฒญ + */ +export interface UpdateEventRequest { + eventName?: string; + description?: string; + startDate?: string; + endDate?: string; + discountRate?: number; +} + +/** + * ๋ฐฐํฌ ์ฑ„๋„ ์„ ํƒ ์š”์ฒญ + */ +export interface SelectChannelsRequest { + channels: string[]; +} + +/** + * ์ด๋ฏธ์ง€ ์„ ํƒ ์š”์ฒญ + */ +export interface SelectImageRequest { + selectedImageId: string; +}