mirror of
https://github.com/ktds-dg0501/kt-event-marketing-fe.git
synced 2025-12-06 09:36:23 +00:00
348 lines
12 KiB
TypeScript
348 lines
12 KiB
TypeScript
import { useState } from 'react';
|
|
import {
|
|
Box,
|
|
Container,
|
|
Typography,
|
|
Card,
|
|
CardContent,
|
|
Button,
|
|
Checkbox,
|
|
FormControlLabel,
|
|
Chip,
|
|
Grid,
|
|
IconButton,
|
|
Dialog,
|
|
DialogTitle,
|
|
DialogContent,
|
|
DialogActions,
|
|
Link,
|
|
} from '@mui/material';
|
|
import { ArrowBack, CheckCircle, Edit, RocketLaunch, Save } from '@mui/icons-material';
|
|
import { EventData } from '../page';
|
|
|
|
interface ApprovalStepProps {
|
|
eventData: EventData;
|
|
onApprove: () => void;
|
|
onBack: () => void;
|
|
}
|
|
|
|
export default function ApprovalStep({ eventData, onApprove, onBack }: ApprovalStepProps) {
|
|
const [agreeTerms, setAgreeTerms] = useState(false);
|
|
const [termsDialogOpen, setTermsDialogOpen] = useState(false);
|
|
const [successDialogOpen, setSuccessDialogOpen] = useState(false);
|
|
const [isDeploying, setIsDeploying] = useState(false);
|
|
|
|
const handleApprove = () => {
|
|
if (!agreeTerms) return;
|
|
|
|
setIsDeploying(true);
|
|
|
|
// 배포 시뮬레이션
|
|
setTimeout(() => {
|
|
setIsDeploying(false);
|
|
setSuccessDialogOpen(true);
|
|
}, 2000);
|
|
};
|
|
|
|
const handleSaveDraft = () => {
|
|
// TODO: 임시저장 API 연동
|
|
alert('임시저장되었습니다');
|
|
};
|
|
|
|
const getChannelNames = (channels?: string[]) => {
|
|
const channelMap: Record<string, string> = {
|
|
uriTV: '우리동네TV',
|
|
ringoBiz: '링고비즈',
|
|
genieTV: '지니TV',
|
|
sns: 'SNS',
|
|
};
|
|
|
|
return channels?.map((ch) => channelMap[ch] || ch) || [];
|
|
};
|
|
|
|
return (
|
|
<Box sx={{ minHeight: '100vh', bgcolor: 'background.default', pb: 10 }}>
|
|
<Container maxWidth="md" sx={{ pt: 4, pb: 4, px: { xs: 3, sm: 3, md: 4 } }}>
|
|
{/* Header */}
|
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2, mb: 4 }}>
|
|
<IconButton onClick={onBack}>
|
|
<ArrowBack />
|
|
</IconButton>
|
|
<Typography variant="h5" sx={{ fontWeight: 700 }}>
|
|
최종 승인
|
|
</Typography>
|
|
</Box>
|
|
|
|
{/* Title Section */}
|
|
<Box sx={{ textAlign: 'center', mb: 5 }}>
|
|
<CheckCircle sx={{ fontSize: 64, color: 'success.main', mb: 2 }} />
|
|
<Typography variant="h5" sx={{ fontWeight: 700, mb: 1 }}>
|
|
이벤트를 확인해주세요
|
|
</Typography>
|
|
<Typography variant="body1" color="text.secondary">
|
|
모든 정보를 검토한 후 배포하세요
|
|
</Typography>
|
|
</Box>
|
|
|
|
{/* Event Summary Card */}
|
|
<Card elevation={0} sx={{ mb: 4, borderRadius: 3 }}>
|
|
<CardContent sx={{ p: 4 }}>
|
|
<Typography variant="h6" sx={{ fontWeight: 700, mb: 2 }}>
|
|
{eventData.recommendation?.title || '이벤트 제목'}
|
|
</Typography>
|
|
|
|
<Box sx={{ display: 'flex', gap: 1, mb: 3 }}>
|
|
<Chip label="배포 대기" color="warning" size="small" />
|
|
<Chip label="AI 추천" color="info" size="small" />
|
|
</Box>
|
|
|
|
<Grid container spacing={2} sx={{ pt: 2, borderTop: 1, borderColor: 'divider' }}>
|
|
<Grid item xs={6}>
|
|
<Typography variant="caption" color="text.secondary">
|
|
이벤트 기간
|
|
</Typography>
|
|
<Typography variant="body2" sx={{ fontWeight: 600 }}>
|
|
2025.02.01 ~ 2025.02.28
|
|
</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="caption" color="text.secondary">
|
|
목표 참여자
|
|
</Typography>
|
|
<Typography variant="body2" sx={{ fontWeight: 600 }}>
|
|
{eventData.recommendation?.expectedParticipants || 0}명
|
|
</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="caption" color="text.secondary">
|
|
예상 비용
|
|
</Typography>
|
|
<Typography variant="body2" sx={{ fontWeight: 600 }}>
|
|
{eventData.recommendation?.estimatedCost.toLocaleString() || 0}원
|
|
</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="caption" color="text.secondary">
|
|
예상 ROI
|
|
</Typography>
|
|
<Typography variant="body2" sx={{ fontWeight: 600, color: 'error.main' }}>
|
|
{eventData.recommendation?.roi || 0}%
|
|
</Typography>
|
|
</Grid>
|
|
</Grid>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Event Details */}
|
|
<Typography variant="h6" sx={{ fontWeight: 700, mb: 3 }}>
|
|
이벤트 상세
|
|
</Typography>
|
|
|
|
<Card elevation={0} sx={{ mb: 2, borderRadius: 3 }}>
|
|
<CardContent sx={{ p: 3 }}>
|
|
<Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 2 }}>
|
|
<Box sx={{ flex: 1 }}>
|
|
<Typography variant="caption" color="text.secondary">
|
|
이벤트 제목
|
|
</Typography>
|
|
<Typography variant="body1" sx={{ fontWeight: 600 }}>
|
|
{eventData.recommendation?.title}
|
|
</Typography>
|
|
</Box>
|
|
<IconButton size="small">
|
|
<Edit fontSize="small" />
|
|
</IconButton>
|
|
</Box>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card elevation={0} sx={{ mb: 2, borderRadius: 3 }}>
|
|
<CardContent sx={{ p: 3 }}>
|
|
<Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 2 }}>
|
|
<Box sx={{ flex: 1 }}>
|
|
<Typography variant="caption" color="text.secondary">
|
|
경품
|
|
</Typography>
|
|
<Typography variant="body1" sx={{ fontWeight: 600 }}>
|
|
{eventData.recommendation?.prize}
|
|
</Typography>
|
|
</Box>
|
|
<IconButton size="small">
|
|
<Edit fontSize="small" />
|
|
</IconButton>
|
|
</Box>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card elevation={0} sx={{ mb: 2, borderRadius: 3 }}>
|
|
<CardContent sx={{ p: 3 }}>
|
|
<Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 2 }}>
|
|
<Box sx={{ flex: 1 }}>
|
|
<Typography variant="caption" color="text.secondary">
|
|
참여 방법
|
|
</Typography>
|
|
<Typography variant="body1" sx={{ fontWeight: 600 }}>
|
|
{eventData.recommendation?.participationMethod}
|
|
</Typography>
|
|
</Box>
|
|
</Box>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Distribution Channels */}
|
|
<Typography variant="h6" sx={{ fontWeight: 700, mb: 3, mt: 4 }}>
|
|
배포 채널
|
|
</Typography>
|
|
|
|
<Card elevation={0} sx={{ mb: 4, borderRadius: 3 }}>
|
|
<CardContent sx={{ p: 3 }}>
|
|
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 1, mb: 2 }}>
|
|
{getChannelNames(eventData.channels).map((channel) => (
|
|
<Chip key={channel} label={channel} color="primary" variant="outlined" />
|
|
))}
|
|
</Box>
|
|
<Button
|
|
size="small"
|
|
startIcon={<Edit />}
|
|
sx={{ color: 'primary.main' }}
|
|
>
|
|
채널 수정하기
|
|
</Button>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Terms Agreement */}
|
|
<Card elevation={0} sx={{ mb: 5, borderRadius: 3, bgcolor: 'grey.50' }}>
|
|
<CardContent sx={{ p: 3 }}>
|
|
<FormControlLabel
|
|
control={
|
|
<Checkbox
|
|
checked={agreeTerms}
|
|
onChange={(e) => setAgreeTerms(e.target.checked)}
|
|
/>
|
|
}
|
|
label={
|
|
<Typography variant="body2">
|
|
이벤트 약관 및 개인정보 처리방침에 동의합니다{' '}
|
|
<span style={{ color: 'red' }}>(필수)</span>
|
|
</Typography>
|
|
}
|
|
/>
|
|
<Link
|
|
component="button"
|
|
variant="body2"
|
|
onClick={() => setTermsDialogOpen(true)}
|
|
sx={{ color: 'error.main', ml: 4, mt: 1 }}
|
|
>
|
|
약관 보기
|
|
</Link>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Action Buttons */}
|
|
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
|
|
<Button
|
|
fullWidth
|
|
variant="contained"
|
|
size="large"
|
|
disabled={!agreeTerms || isDeploying}
|
|
onClick={handleApprove}
|
|
startIcon={isDeploying ? null : <RocketLaunch />}
|
|
sx={{ py: 1.5 }}
|
|
>
|
|
{isDeploying ? '배포 중...' : '배포하기'}
|
|
</Button>
|
|
<Button
|
|
fullWidth
|
|
variant="outlined"
|
|
size="large"
|
|
onClick={handleSaveDraft}
|
|
startIcon={<Save />}
|
|
sx={{ py: 1.5 }}
|
|
>
|
|
임시저장
|
|
</Button>
|
|
</Box>
|
|
</Container>
|
|
|
|
{/* Terms Dialog */}
|
|
<Dialog
|
|
open={termsDialogOpen}
|
|
onClose={() => setTermsDialogOpen(false)}
|
|
maxWidth="sm"
|
|
fullWidth
|
|
>
|
|
<DialogTitle>이벤트 약관</DialogTitle>
|
|
<DialogContent>
|
|
<Typography variant="h6" sx={{ mb: 2 }}>
|
|
제1조 (목적)
|
|
</Typography>
|
|
<Typography variant="body2" sx={{ mb: 3 }}>
|
|
본 약관은 KT AI 이벤트 마케팅 서비스를 통해 진행되는 이벤트의 참여 및 개인정보 처리에 관한
|
|
사항을 규정합니다.
|
|
</Typography>
|
|
|
|
<Typography variant="h6" sx={{ mb: 2 }}>
|
|
제2조 (개인정보 수집 및 이용)
|
|
</Typography>
|
|
<Typography variant="body2" sx={{ mb: 1 }}>
|
|
수집 항목: 이름, 전화번호, 이메일
|
|
</Typography>
|
|
<Typography variant="body2" sx={{ mb: 1 }}>
|
|
이용 목적: 이벤트 참여 확인 및 경품 제공
|
|
</Typography>
|
|
<Typography variant="body2" sx={{ mb: 3 }}>
|
|
보유 기간: 이벤트 종료 후 6개월
|
|
</Typography>
|
|
|
|
<Typography variant="h6" sx={{ mb: 2 }}>
|
|
제3조 (당첨자 발표)
|
|
</Typography>
|
|
<Typography variant="body2">
|
|
당첨자는 이벤트 종료 후 7일 이내 개별 연락 드립니다.
|
|
</Typography>
|
|
</DialogContent>
|
|
<DialogActions>
|
|
<Button onClick={() => setTermsDialogOpen(false)} variant="contained">
|
|
확인
|
|
</Button>
|
|
</DialogActions>
|
|
</Dialog>
|
|
|
|
{/* Success Dialog */}
|
|
<Dialog
|
|
open={successDialogOpen}
|
|
onClose={() => {
|
|
setSuccessDialogOpen(false);
|
|
onApprove();
|
|
}}
|
|
>
|
|
<DialogContent sx={{ textAlign: 'center', py: 6, px: 4 }}>
|
|
<CheckCircle sx={{ fontSize: 80, color: 'success.main', mb: 2 }} />
|
|
<Typography variant="h5" sx={{ fontWeight: 700, mb: 1 }}>
|
|
배포 완료!
|
|
</Typography>
|
|
<Typography variant="body1" color="text.secondary" sx={{ mb: 4 }}>
|
|
이벤트가 성공적으로 배포되었습니다.
|
|
<br />
|
|
실시간으로 참여자를 확인할 수 있습니다.
|
|
</Typography>
|
|
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
|
|
<Button
|
|
fullWidth
|
|
variant="contained"
|
|
size="large"
|
|
onClick={() => {
|
|
setSuccessDialogOpen(false);
|
|
onApprove();
|
|
}}
|
|
>
|
|
대시보드로 이동
|
|
</Button>
|
|
</Box>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</Box>
|
|
);
|
|
}
|