cherry2250 8e2376dc57 create 페이지 전체 색상 시스템 통일 및 ChannelStep 체크박스 디자인 개선
- 메인/이벤트 페이지와 동일한 색상 시스템을 모든 create 페이지에 적용
- ObjectiveStep: 아이콘, 카드 선택 상태, 그라데이션 버튼에 통일된 색상 적용
- RecommendationStep: AI 트렌드 아이콘, 카드 선택/호버 상태에 purple 색상 적용
- ChannelStep: 모든 채널 카드 및 체크박스에 통일된 디자인 시스템 적용
  - 선택된 카드: purple 테두리, purpleLight 배경, 강조된 그림자
  - 모든 체크박스: purple 색상 적용 (메인 체크박스 + SNS 하위 체크박스)
  - 선택 상태에 따른 폰트 굵기 변화로 시각적 피드백 강화
- ContentPreviewStep, ContentEditStep, ApprovalStep: 색상 시스템 추가 (향후 사용 준비)
- 총 예상 노출 텍스트: purple 색상 적용

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 15:19:31 +09:00

366 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';
// 디자인 시스템 색상
const colors = {
pink: '#F472B6',
purple: '#C084FC',
purpleLight: '#E9D5FF',
blue: '#60A5FA',
mint: '#34D399',
orange: '#FB923C',
yellow: '#FBBF24',
gray: {
900: '#1A1A1A',
700: '#4A4A4A',
500: '#9E9E9E',
300: '#D9D9D9',
100: '#F5F5F5',
},
};
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: 20 }}>
<Container maxWidth="md" sx={{ pt: 8, pb: 8, px: { xs: 6, sm: 6, md: 8 } }}>
{/* Header */}
<Box sx={{ display: 'flex', alignItems: 'center', gap: 3, mb: 8 }}>
<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: 4 }}>
<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: 4 }}>
<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: 4 }}>
<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: 4 }}>
<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: 4 }}>
<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: 4, 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>
);
}