develop : 환경 설정 초기 셋팅

This commit is contained in:
cherry2250 2025-10-27 11:44:25 +09:00
parent 01a77fe7a8
commit e1fefc2dad

View File

@ -1,16 +1,7 @@
'use client'; 'use client';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import { import { Box, Container, Typography, Grid, Card, CardContent, Button, Fab } from '@mui/material';
Box,
Container,
Typography,
Grid,
Card,
CardContent,
Button,
Fab,
} from '@mui/material';
import { import {
Add, Add,
Celebration, Celebration,
@ -22,7 +13,12 @@ import {
CheckCircle, CheckCircle,
} from '@mui/icons-material'; } from '@mui/icons-material';
import Header from '@/shared/ui/Header'; import Header from '@/shared/ui/Header';
import { getGradientButtonStyle, responsiveText, cardStyles, colors } from '@/shared/lib/button-styles'; import {
getGradientButtonStyle,
responsiveText,
cardStyles,
colors,
} from '@/shared/lib/button-styles';
// Mock 사용자 데이터 (API 연동 전까지 임시 사용) // Mock 사용자 데이터 (API 연동 전까지 임시 사용)
const mockUser = { const mockUser = {
@ -64,9 +60,10 @@ export default function HomePage() {
// KPI 계산 // KPI 계산
const activeEvents = mockEvents.filter((e) => e.status === '진행중'); const activeEvents = mockEvents.filter((e) => e.status === '진행중');
const totalParticipants = mockEvents.reduce((sum, e) => sum + e.participants, 0); const totalParticipants = mockEvents.reduce((sum, e) => sum + e.participants, 0);
const avgROI = mockEvents.length > 0 const avgROI =
? Math.round(mockEvents.reduce((sum, e) => sum + e.roi, 0) / mockEvents.length) mockEvents.length > 0
: 0; ? Math.round(mockEvents.reduce((sum, e) => sum + e.roi, 0) / mockEvents.length)
: 0;
const handleCreateEvent = () => { const handleCreateEvent = () => {
router.push('/events/create'); router.push('/events/create');
@ -92,379 +89,439 @@ export default function HomePage() {
}} }}
> >
<Container maxWidth="lg" sx={{ pt: 5, pb: 4, px: { xs: 3, sm: 4, md: 5 } }}> <Container maxWidth="lg" sx={{ pt: 5, pb: 4, px: { xs: 3, sm: 4, md: 5 } }}>
{/* Welcome Section */} {/* Welcome Section */}
<Box sx={{ mb: 6 }}> <Box sx={{ mb: 6 }}>
<Typography <Typography
variant="h3" variant="h3"
sx={{
...responsiveText.h2,
mb: 2,
}}
>
, {mockUser.name}! 👋
</Typography>
<Typography variant="body1" sx={{ ...responsiveText.body1 }}>
</Typography>
</Box>
{/* KPI Cards */}
<Grid container spacing={4} sx={{ mb: 6 }}>
<Grid item xs={12} sm={4}>
<Card
elevation={0}
sx={{ sx={{
...cardStyles.default, ...responsiveText.h2,
background: `linear-gradient(135deg, ${colors.purple} 0%, ${colors.purpleLight} 100%)`, mb: 2,
borderColor: 'transparent',
}} }}
> >
<CardContent sx={{ textAlign: 'center', py: 4, px: 3 }}> , {mockUser.name}! 👋
<Box </Typography>
sx={{ <Typography variant="body1" sx={{ ...responsiveText.body1 }}>
width: 64,
height: 64,
borderRadius: '50%',
bgcolor: 'rgba(255, 255, 255, 0.2)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
margin: '0 auto',
mb: 2,
}}
>
<Celebration sx={{ fontSize: 32, color: 'white' }} />
</Box>
<Typography
variant="body2"
sx={{ mb: 1, color: 'rgba(255, 255, 255, 0.9)', fontWeight: 500, fontSize: '0.875rem' }}
>
</Typography>
<Typography variant="h3" sx={{ fontWeight: 700, color: 'white', fontSize: '2.5rem' }}>
{activeEvents.length}
</Typography>
</CardContent>
</Card>
</Grid>
<Grid item xs={12} sm={4}>
<Card
elevation={0}
sx={{
...cardStyles.default,
background: `linear-gradient(135deg, ${colors.mint} 0%, ${colors.mintLight} 100%)`,
borderColor: 'transparent',
}}
>
<CardContent sx={{ textAlign: 'center', py: 4, px: 3 }}>
<Box
sx={{
width: 64,
height: 64,
borderRadius: '50%',
bgcolor: 'rgba(255, 255, 255, 0.2)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
margin: '0 auto',
mb: 2,
}}
>
<Group sx={{ fontSize: 32, color: 'white' }} />
</Box>
<Typography
variant="body2"
sx={{ mb: 1, color: 'rgba(255, 255, 255, 0.9)', fontWeight: 500, fontSize: '0.875rem' }}
>
</Typography>
<Typography variant="h3" sx={{ fontWeight: 700, color: 'white', fontSize: '2.5rem' }}>
{totalParticipants.toLocaleString()}
</Typography>
</CardContent>
</Card>
</Grid>
<Grid item xs={12} sm={4}>
<Card
elevation={0}
sx={{
...cardStyles.default,
background: `linear-gradient(135deg, ${colors.blue} 0%, ${colors.blueLight} 100%)`,
borderColor: 'transparent',
}}
>
<CardContent sx={{ textAlign: 'center', py: 4, px: 3 }}>
<Box
sx={{
width: 64,
height: 64,
borderRadius: '50%',
bgcolor: 'rgba(255, 255, 255, 0.2)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
margin: '0 auto',
mb: 2,
}}
>
<TrendingUp sx={{ fontSize: 32, color: 'white' }} />
</Box>
<Typography
variant="body2"
sx={{ mb: 1, color: 'rgba(255, 255, 255, 0.9)', fontWeight: 500, fontSize: '0.875rem' }}
>
ROI
</Typography>
<Typography variant="h3" sx={{ fontWeight: 700, color: 'white', fontSize: '2.5rem' }}>
{avgROI}%
</Typography>
</CardContent>
</Card>
</Grid>
</Grid>
{/* Quick Actions */}
<Box sx={{ mb: 6 }}>
<Typography variant="h5" sx={{ ...responsiveText.h3, mb: 4 }}>
</Typography>
<Grid container spacing={4}>
<Grid item xs={6} sm={6}>
<Card
elevation={0}
sx={{
...cardStyles.clickable,
}}
onClick={handleCreateEvent}
>
<CardContent sx={{ textAlign: 'center', py: 5 }}>
<Box
sx={{
width: 72,
height: 72,
borderRadius: '20px',
background: `linear-gradient(135deg, ${colors.purple} 0%, ${colors.blue} 100%)`,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
margin: '0 auto',
mb: 2.5,
boxShadow: '0 4px 14px 0 rgba(167, 139, 250, 0.39)',
}}
>
<Add sx={{ fontSize: 36, color: 'white' }} />
</Box>
<Typography variant="body1" sx={{ fontWeight: 600, color: colors.gray[900] }}>
</Typography>
</CardContent>
</Card>
</Grid>
<Grid item xs={6} sm={6}>
<Card
elevation={0}
sx={{
...cardStyles.clickable,
}}
onClick={handleViewAnalytics}
>
<CardContent sx={{ textAlign: 'center', py: 5 }}>
<Box
sx={{
width: 72,
height: 72,
borderRadius: '20px',
background: `linear-gradient(135deg, ${colors.blue} 0%, ${colors.mint} 100%)`,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
margin: '0 auto',
mb: 2.5,
boxShadow: '0 4px 14px 0 rgba(96, 165, 250, 0.39)',
}}
>
<Analytics sx={{ fontSize: 36, color: 'white' }} />
</Box>
<Typography variant="body1" sx={{ fontWeight: 600, color: colors.gray[900] }}>
</Typography>
</CardContent>
</Card>
</Grid>
</Grid>
</Box>
{/* Active Events */}
<Box sx={{ mb: 6 }}>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 4 }}>
<Typography variant="h5" sx={{ ...responsiveText.h3 }}>
</Typography> </Typography>
<Button
size="medium"
endIcon={<span className="material-icons">chevron_right</span>}
onClick={() => router.push('/events')}
sx={{
color: colors.purple,
fontWeight: 600,
'&:hover': { bgcolor: 'rgba(167, 139, 250, 0.08)' },
}}
>
</Button>
</Box> </Box>
{activeEvents.length === 0 ? ( {/* KPI Cards */}
<Card <Grid container spacing={4} sx={{ mb: 6 }}>
elevation={0} <Grid item xs={12} sm={4}>
sx={{ <Card
...cardStyles.default, elevation={0}
}} sx={{
> ...cardStyles.default,
<CardContent sx={{ textAlign: 'center', py: 10 }}> background: `linear-gradient(135deg, ${colors.purple} 0%, ${colors.purpleLight} 100%)`,
<Box sx={{ color: colors.gray[300], mb: 3 }}> borderColor: 'transparent',
<span className="material-icons" style={{ fontSize: 72 }}> }}
event_busy >
</span> <CardContent sx={{ textAlign: 'center', py: 4, px: 3 }}>
</Box> <Box
<Typography variant="h6" sx={{ mb: 2, color: colors.gray[700] }}> sx={{
width: 64,
</Typography> height: 64,
<Typography variant="body2" sx={{ mb: 4, color: colors.gray[500] }}> borderRadius: '50%',
bgcolor: 'rgba(255, 255, 255, 0.2)',
</Typography> display: 'flex',
<Button alignItems: 'center',
variant="contained" justifyContent: 'center',
startIcon={<Add />} margin: '0 auto',
onClick={handleCreateEvent} mb: 2,
sx={{ }}
py: { xs: 1.5, sm: 1.75 }, >
px: { xs: 3, sm: 4 }, <Celebration sx={{ fontSize: 32, color: 'white' }} />
fontSize: { xs: 15, sm: 16 }, </Box>
...getGradientButtonStyle('primary'), <Typography
}} variant="body2"
> sx={{
mb: 1,
</Button> color: 'rgba(255, 255, 255, 0.9)',
</CardContent> fontWeight: 500,
</Card> fontSize: '0.875rem',
) : ( }}
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 4 }}> >
{activeEvents.map((event) => (
</Typography>
<Typography
variant="h3"
sx={{ fontWeight: 700, color: 'white', fontSize: '2.5rem' }}
>
{activeEvents.length}
</Typography>
</CardContent>
</Card>
</Grid>
<Grid item xs={12} sm={4}>
<Card
elevation={0}
sx={{
...cardStyles.default,
background: `linear-gradient(135deg, ${colors.mint} 0%, ${colors.mintLight} 100%)`,
borderColor: 'transparent',
}}
>
<CardContent sx={{ textAlign: 'center', py: 4, px: 3 }}>
<Box
sx={{
width: 64,
height: 64,
borderRadius: '50%',
bgcolor: 'rgba(255, 255, 255, 0.2)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
margin: '0 auto',
mb: 2,
}}
>
<Group sx={{ fontSize: 32, color: 'white' }} />
</Box>
<Typography
variant="body2"
sx={{
mb: 1,
color: 'rgba(255, 255, 255, 0.9)',
fontWeight: 500,
fontSize: '0.875rem',
}}
>
</Typography>
<Typography
variant="h3"
sx={{ fontWeight: 700, color: 'white', fontSize: '2.5rem' }}
>
{totalParticipants.toLocaleString()}
</Typography>
</CardContent>
</Card>
</Grid>
<Grid item xs={12} sm={4}>
<Card
elevation={0}
sx={{
...cardStyles.default,
background: `linear-gradient(135deg, ${colors.blue} 0%, ${colors.blueLight} 100%)`,
borderColor: 'transparent',
}}
>
<CardContent sx={{ textAlign: 'center', py: 4, px: 3 }}>
<Box
sx={{
width: 64,
height: 64,
borderRadius: '50%',
bgcolor: 'rgba(255, 255, 255, 0.2)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
margin: '0 auto',
mb: 2,
}}
>
<TrendingUp sx={{ fontSize: 32, color: 'white' }} />
</Box>
<Typography
variant="body2"
sx={{
mb: 1,
color: 'rgba(255, 255, 255, 0.9)',
fontWeight: 500,
fontSize: '0.875rem',
}}
>
ROI
</Typography>
<Typography
variant="h3"
sx={{ fontWeight: 700, color: 'white', fontSize: '2.5rem' }}
>
{avgROI}%
</Typography>
</CardContent>
</Card>
</Grid>
</Grid>
{/* Quick Actions */}
<Box sx={{ mb: 6 }}>
<Typography variant="h5" sx={{ ...responsiveText.h3, mb: 4 }}>
</Typography>
<Grid container spacing={4}>
<Grid item xs={6} sm={6}>
<Card <Card
key={event.id}
elevation={0} elevation={0}
sx={{ sx={{
...cardStyles.clickable, ...cardStyles.clickable,
}} }}
onClick={() => handleEventClick(event.id)} onClick={handleCreateEvent}
> >
<CardContent sx={{ p: { xs: 3, sm: 4 } }}> <CardContent sx={{ textAlign: 'center', py: 5 }}>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'start', mb: 3 }}> <Box
<Typography variant="h6" sx={{ fontWeight: 700, color: colors.gray[900] }}> sx={{
{event.title} width: 72,
</Typography> height: 72,
<Box borderRadius: '20px',
sx={{ background: `linear-gradient(135deg, ${colors.purple} 0%, ${colors.blue} 100%)`,
px: 2.5, display: 'flex',
py: 0.75, alignItems: 'center',
bgcolor: colors.mint, justifyContent: 'center',
color: 'white', margin: '0 auto',
borderRadius: 2, mb: 2.5,
fontSize: '0.875rem', boxShadow: '0 4px 14px 0 rgba(167, 139, 250, 0.39)',
fontWeight: 600, }}
}} >
> <Add sx={{ fontSize: 36, color: 'white' }} />
{event.status}
</Box>
</Box> </Box>
<Typography variant="body2" sx={{ mb: 3, color: colors.gray[600], display: 'flex', alignItems: 'center', gap: 1 }}> <Typography variant="body1" sx={{ fontWeight: 600, color: colors.gray[900] }}>
<span>📅</span>
<span>{event.startDate} ~ {event.endDate}</span>
</Typography> </Typography>
<Box sx={{ display: 'flex', gap: 6 }}>
<Box>
<Typography variant="body2" sx={{ mb: 0.5, color: colors.gray[600], fontWeight: 500 }}>
</Typography>
<Typography variant="h5" sx={{ fontWeight: 700, color: colors.gray[900] }}>
{event.participants.toLocaleString()}
<Typography component="span" variant="body2" sx={{ ml: 0.5, color: colors.gray[600] }}>
</Typography>
</Typography>
</Box>
<Box>
<Typography variant="body2" sx={{ mb: 0.5, color: colors.gray[600], fontWeight: 500 }}>
ROI
</Typography>
<Typography variant="h5" sx={{ fontWeight: 700, color: colors.mint }}>
{event.roi}%
</Typography>
</Box>
</Box>
</CardContent> </CardContent>
</Card> </Card>
))} </Grid>
</Box> <Grid item xs={6} sm={6}>
)} <Card
</Box> elevation={0}
{/* Recent Activity */}
<Box sx={{ mb: 6 }}>
<Typography variant="h5" sx={{ ...responsiveText.h3, mb: 4 }}>
</Typography>
<Card
elevation={0}
sx={{
...cardStyles.default,
}}
>
<CardContent sx={{ p: { xs: 3, sm: 4 } }}>
{mockActivities.map((activity, index) => (
<Box
key={index}
sx={{ sx={{
display: 'flex', ...cardStyles.clickable,
gap: 3,
pt: index > 0 ? 3.5 : 0,
mt: index > 0 ? 3.5 : 0,
borderTop: index > 0 ? 1 : 0,
borderColor: colors.gray[200],
}} }}
onClick={handleViewAnalytics}
> >
<Box <CardContent sx={{ textAlign: 'center', py: 5 }}>
<Box
sx={{
width: 72,
height: 72,
borderRadius: '20px',
background: `linear-gradient(135deg, ${colors.blue} 0%, ${colors.mint} 100%)`,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
margin: '0 auto',
mb: 2.5,
boxShadow: '0 4px 14px 0 rgba(96, 165, 250, 0.39)',
}}
>
<Analytics sx={{ fontSize: 36, color: 'white' }} />
</Box>
<Typography variant="body1" sx={{ fontWeight: 600, color: colors.gray[900] }}>
</Typography>
</CardContent>
</Card>
</Grid>
</Grid>
</Box>
{/* Active Events */}
<Box sx={{ mb: 6 }}>
<Box
sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 4 }}
>
<Typography variant="h5" sx={{ ...responsiveText.h3 }}>
</Typography>
<Button
size="medium"
endIcon={<span className="material-icons">chevron_right</span>}
onClick={() => router.push('/events')}
sx={{
color: colors.purple,
fontWeight: 600,
'&:hover': { bgcolor: 'rgba(167, 139, 250, 0.08)' },
}}
>
</Button>
</Box>
{activeEvents.length === 0 ? (
<Card
elevation={0}
sx={{
...cardStyles.default,
}}
>
<CardContent sx={{ textAlign: 'center', py: 10 }}>
<Box sx={{ color: colors.gray[300], mb: 3 }}>
<span className="material-icons" style={{ fontSize: 72 }}>
event_busy
</span>
</Box>
<Typography variant="h6" sx={{ mb: 2, color: colors.gray[700] }}>
</Typography>
<Typography variant="body2" sx={{ mb: 4, color: colors.gray[500] }}>
</Typography>
<Button
variant="contained"
startIcon={<Add />}
onClick={handleCreateEvent}
sx={{ sx={{
width: 48, py: { xs: 1.5, sm: 1.75 },
height: 48, px: { xs: 3, sm: 4 },
borderRadius: '14px', fontSize: { xs: 15, sm: 16 },
background: `linear-gradient(135deg, ${colors.purple} 0%, ${colors.purpleLight} 100%)`, ...getGradientButtonStyle('primary'),
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
flexShrink: 0,
}} }}
> >
<activity.icon sx={{ fontSize: 24, color: 'white' }} />
</Box> </Button>
<Box sx={{ flex: 1 }}> </CardContent>
<Typography variant="body1" sx={{ fontWeight: 600, color: colors.gray[900], mb: 0.5 }}> </Card>
{activity.text} ) : (
</Typography> <Box sx={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
<Typography variant="body2" sx={{ color: colors.gray[500] }}> {activeEvents.map((event) => (
{activity.time} <Card
</Typography> key={event.id}
</Box> elevation={0}
</Box> sx={{
))} ...cardStyles.clickable,
</CardContent> }}
</Card> onClick={() => handleEventClick(event.id)}
</Box> >
</Container> <CardContent sx={{ p: { xs: 3, sm: 4 } }}>
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'start',
mb: 3,
}}
>
<Typography variant="h6" sx={{ fontWeight: 700, color: colors.gray[900] }}>
{event.title}
</Typography>
<Box
sx={{
px: 2.5,
py: 0.75,
bgcolor: colors.mint,
color: 'white',
borderRadius: 2,
fontSize: '0.875rem',
fontWeight: 600,
}}
>
{event.status}
</Box>
</Box>
<Typography
variant="body2"
sx={{
mb: 3,
color: colors.gray[600],
display: 'flex',
alignItems: 'center',
gap: 1,
}}
>
<span>📅</span>
<span>
{event.startDate} ~ {event.endDate}
</span>
</Typography>
<Box sx={{ display: 'flex', gap: 6 }}>
<Box>
<Typography
variant="body2"
sx={{ mb: 0.5, color: colors.gray[600], fontWeight: 500 }}
>
</Typography>
<Typography
variant="h5"
sx={{ fontWeight: 700, color: colors.gray[900] }}
>
{event.participants.toLocaleString()}
<Typography
component="span"
variant="body2"
sx={{ ml: 0.5, color: colors.gray[600] }}
>
</Typography>
</Typography>
</Box>
<Box>
<Typography
variant="body2"
sx={{ mb: 0.5, color: colors.gray[600], fontWeight: 500 }}
>
ROI
</Typography>
<Typography variant="h5" sx={{ fontWeight: 700, color: colors.mint }}>
{event.roi}%
</Typography>
</Box>
</Box>
</CardContent>
</Card>
))}
</Box>
)}
</Box>
{/* Floating Action Button */} {/* Recent Activity */}
<Fab <Box sx={{ mb: 6 }}>
<Typography variant="h5" sx={{ ...responsiveText.h3, mb: 4 }}>
</Typography>
<Card
elevation={0}
sx={{
...cardStyles.default,
}}
>
<CardContent sx={{ p: { xs: 3, sm: 4 } }}>
{mockActivities.map((activity, index) => (
<Box
key={index}
sx={{
display: 'flex',
gap: 3,
pt: index > 0 ? 3.5 : 0,
mt: index > 0 ? 3.5 : 0,
borderTop: index > 0 ? 1 : 0,
borderColor: colors.gray[200],
}}
>
<Box
sx={{
width: 48,
height: 48,
borderRadius: '14px',
background: `linear-gradient(135deg, ${colors.purple} 0%, ${colors.purpleLight} 100%)`,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
flexShrink: 0,
}}
>
<activity.icon sx={{ fontSize: 24, color: 'white' }} />
</Box>
<Box sx={{ flex: 1 }}>
<Typography
variant="body1"
sx={{ fontWeight: 600, color: colors.gray[900], mb: 0.5 }}
>
{activity.text}
</Typography>
<Typography variant="body2" sx={{ color: colors.gray[500] }}>
{activity.time}
</Typography>
</Box>
</Box>
))}
</CardContent>
</Card>
</Box>
</Container>
{/* Floating Action Button */}
<Fab
sx={{ sx={{
position: 'fixed', position: 'fixed',
bottom: { xs: 80, sm: 90 }, bottom: { xs: 80, sm: 90 },
@ -472,9 +529,11 @@ export default function HomePage() {
width: { xs: 64, sm: 72 }, width: { xs: 64, sm: 72 },
height: { xs: 64, sm: 72 }, height: { xs: 64, sm: 72 },
...getGradientButtonStyle('primary'), ...getGradientButtonStyle('primary'),
boxShadow: '0 10px 25px -5px rgba(167, 139, 250, 0.5), 0 8px 10px -6px rgba(167, 139, 250, 0.5)', boxShadow:
'0 10px 25px -5px rgba(167, 139, 250, 0.5), 0 8px 10px -6px rgba(167, 139, 250, 0.5)',
'&:hover': { '&:hover': {
boxShadow: '0 20px 35px -5px rgba(167, 139, 250, 0.6), 0 12px 15px -6px rgba(167, 139, 250, 0.6)', boxShadow:
'0 20px 35px -5px rgba(167, 139, 250, 0.6), 0 12px 15px -6px rgba(167, 139, 250, 0.6)',
}, },
}} }}
onClick={handleCreateEvent} onClick={handleCreateEvent}