참고 디자인을 기반으로 전면 리디자인 완료

## 주요 변경사항

### 디자인 시스템 개선
- 새로운 색상 팔레트 적용 (민트, 보라, 파랑 기반)
- Tailwind CSS 스타일 그림자 시스템
- 개선된 카드 스타일 (1px 테두리, 큰 border-radius)
- 부드러운 애니메이션 (cubic-bezier)
- 타이포그래피 개선 (letter-spacing, 색상 계층)

### 메인 대시보드 리디자인
- KPI 카드: 그라디언트 배경, 원형 아이콘 컨테이너, 큰 숫자
- 빠른 시작: 개선된 아이콘 크기와 그림자
- 진행 중인 이벤트: 깔끔한 레이아웃, 민트 배지
- 최근 활동: 그라디언트 아이콘, 더 큰 간격
- FAB 버튼: 보라색 글로우 효과

### 레이아웃 개선
- 더 넓은 여백과 간격 (mb: 6, spacing: 4)
- 밝은 회색 배경 적용
- 화이트 카드 배경
- 개선된 반응형 패딩

### Header 오버레이 수정
- 모든 페이지에 적절한 상단 패딩 추가
- containerStyles.page에 pt 추가

🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
cherry2250 2025-10-27 11:42:44 +09:00
parent edcd0cd559
commit 01a77fe7a8
7 changed files with 419 additions and 173 deletions

View File

@ -21,6 +21,7 @@ import {
import { Visibility, VisibilityOff, Email, Lock, ChatBubble } from '@mui/icons-material'; import { Visibility, VisibilityOff, Email, Lock, ChatBubble } from '@mui/icons-material';
import { useAuthStore } from '@/stores/authStore'; import { useAuthStore } from '@/stores/authStore';
import { useUIStore } from '@/stores/uiStore'; import { useUIStore } from '@/stores/uiStore';
import { getGradientButtonStyle, responsiveText } from '@/shared/lib/button-styles';
// 유효성 검사 스키마 // 유효성 검사 스키마
const loginSchema = z.object({ const loginSchema = z.object({
@ -132,7 +133,7 @@ export default function LoginPage() {
> >
<Typography sx={{ fontSize: 32 }}>🎉</Typography> <Typography sx={{ fontSize: 32 }}>🎉</Typography>
</Box> </Box>
<Typography variant="h4" sx={{ fontWeight: 700, mb: 1 }}> <Typography variant="h4" sx={{ ...responsiveText.h2, mb: 1 }}>
KT AI KT AI
</Typography> </Typography>
<Typography variant="body2" color="text.secondary"> <Typography variant="body2" color="text.secondary">
@ -227,9 +228,9 @@ export default function LoginPage() {
size="large" size="large"
sx={{ sx={{
mb: 2, mb: 2,
py: 1.5, py: { xs: 1.5, sm: 1.75 },
fontSize: 16, fontSize: { xs: 15, sm: 16 },
fontWeight: 600, ...getGradientButtonStyle('primary'),
}} }}
> >

View File

@ -27,6 +27,7 @@ import { ArrowBack, Visibility, VisibilityOff, CheckCircle } from '@mui/icons-ma
import { useState, useEffect, Suspense } from 'react'; import { useState, useEffect, Suspense } from 'react';
import { useUIStore } from '@/stores/uiStore'; import { useUIStore } from '@/stores/uiStore';
import { useAuthStore } from '@/stores/authStore'; import { useAuthStore } from '@/stores/authStore';
import { getGradientButtonStyle, responsiveText } from '@/shared/lib/button-styles';
// 각 단계별 유효성 검사 스키마 // 각 단계별 유효성 검사 스키마
const step1Schema = z const step1Schema = z
@ -289,7 +290,7 @@ function RegisterForm() {
{/* Step 1: 계정정보 */} {/* Step 1: 계정정보 */}
{currentStep === 1 && ( {currentStep === 1 && (
<Box> <Box>
<Typography variant="h5" sx={{ fontWeight: 700, mb: 1 }}> <Typography variant="h5" sx={{ ...responsiveText.h3, mb: 1 }}>
</Typography> </Typography>
<Typography variant="body2" color="text.secondary" sx={{ mb: 4 }}> <Typography variant="body2" color="text.secondary" sx={{ mb: 4 }}>
@ -359,7 +360,12 @@ function RegisterForm() {
variant="contained" variant="contained"
size="large" size="large"
onClick={handleNext} onClick={handleNext}
sx={{ mt: 2, py: 1.5, fontSize: 16, fontWeight: 600 }} sx={{
mt: 2,
py: { xs: 1.5, sm: 1.75 },
fontSize: { xs: 15, sm: 16 },
...getGradientButtonStyle('primary'),
}}
> >
</Button> </Button>
@ -383,7 +389,7 @@ function RegisterForm() {
{/* Step 2: 개인정보 */} {/* Step 2: 개인정보 */}
{currentStep === 2 && ( {currentStep === 2 && (
<Box> <Box>
<Typography variant="h5" sx={{ fontWeight: 700, mb: 1 }}> <Typography variant="h5" sx={{ ...responsiveText.h3, mb: 1 }}>
</Typography> </Typography>
<Typography variant="body2" color="text.secondary" sx={{ mb: 4 }}> <Typography variant="body2" color="text.secondary" sx={{ mb: 4 }}>
@ -421,7 +427,13 @@ function RegisterForm() {
variant="outlined" variant="outlined"
size="large" size="large"
onClick={handleBack} onClick={handleBack}
sx={{ flex: 1, py: 1.5, fontSize: 16, fontWeight: 600 }} sx={{
flex: 1,
py: { xs: 1.5, sm: 1.75 },
fontSize: { xs: 15, sm: 16 },
fontWeight: 600,
borderWidth: 2,
}}
> >
</Button> </Button>
@ -429,7 +441,12 @@ function RegisterForm() {
variant="contained" variant="contained"
size="large" size="large"
onClick={handleNext} onClick={handleNext}
sx={{ flex: 1, py: 1.5, fontSize: 16, fontWeight: 600 }} sx={{
flex: 1,
py: { xs: 1.5, sm: 1.75 },
fontSize: { xs: 15, sm: 16 },
...getGradientButtonStyle('primary'),
}}
> >
</Button> </Button>
@ -441,7 +458,7 @@ function RegisterForm() {
{/* Step 3: 사업장정보 */} {/* Step 3: 사업장정보 */}
{currentStep === 3 && ( {currentStep === 3 && (
<Box> <Box>
<Typography variant="h5" sx={{ fontWeight: 700, mb: 1 }}> <Typography variant="h5" sx={{ ...responsiveText.h3, mb: 1 }}>
</Typography> </Typography>
<Typography variant="body2" color="text.secondary" sx={{ mb: 4 }}> <Typography variant="body2" color="text.secondary" sx={{ mb: 4 }}>
@ -627,7 +644,13 @@ function RegisterForm() {
variant="outlined" variant="outlined"
size="large" size="large"
onClick={handleBack} onClick={handleBack}
sx={{ flex: 1, py: 1.5, fontSize: 16, fontWeight: 600 }} sx={{
flex: 1,
py: { xs: 1.5, sm: 1.75 },
fontSize: { xs: 15, sm: 16 },
fontWeight: 600,
borderWidth: 2,
}}
> >
</Button> </Button>
@ -635,7 +658,12 @@ function RegisterForm() {
variant="contained" variant="contained"
size="large" size="large"
onClick={handleNext} onClick={handleNext}
sx={{ flex: 1, py: 1.5, fontSize: 16, fontWeight: 600 }} sx={{
flex: 1,
py: { xs: 1.5, sm: 1.75 },
fontSize: { xs: 15, sm: 16 },
...getGradientButtonStyle('success'),
}}
> >
</Button> </Button>
@ -665,7 +693,12 @@ function RegisterForm() {
variant="contained" variant="contained"
size="large" size="large"
onClick={handleSuccessDialogClose} onClick={handleSuccessDialogClose}
sx={{ minWidth: 200, py: 1.5, fontSize: 16, fontWeight: 600 }} sx={{
minWidth: 200,
py: { xs: 1.5, sm: 1.75 },
fontSize: { xs: 15, sm: 16 },
...getGradientButtonStyle('success'),
}}
> >
</Button> </Button>

View File

@ -98,7 +98,7 @@ export default function AnalyticsPage() {
return ( return (
<> <>
<Header title="성과 분석" showBack={true} showMenu={false} showProfile={true} /> <Header title="성과 분석" showBack={true} showMenu={false} showProfile={true} />
<Box sx={{ minHeight: '100vh', bgcolor: 'background.default', pb: 10 }}> <Box sx={{ pt: { xs: 7, sm: 8 }, minHeight: '100vh', bgcolor: 'background.default', pb: 10 }}>
<Container maxWidth="lg" sx={{ pt: 4, pb: 4, px: { xs: 3, sm: 3, md: 4 } }}> <Container maxWidth="lg" sx={{ pt: 4, pb: 4, px: { xs: 3, sm: 3, md: 4 } }}>
{/* Title with Real-time Indicator */} {/* Title with Real-time Indicator */}
<Box <Box

View File

@ -143,7 +143,7 @@ export default function EventsPage() {
return ( return (
<> <>
<Header title="이벤트 목록" showBack={true} showMenu={false} showProfile={true} /> <Header title="이벤트 목록" showBack={true} showMenu={false} showProfile={true} />
<Box sx={{ minHeight: '100vh', bgcolor: 'background.default', pb: 10 }}> <Box sx={{ pt: { xs: 7, sm: 8 }, minHeight: '100vh', bgcolor: 'background.default', pb: 10 }}>
<Container maxWidth="lg" sx={{ pt: 4, pb: 4, px: { xs: 3, sm: 3, md: 4 } }}> <Container maxWidth="lg" sx={{ pt: 4, pb: 4, px: { xs: 3, sm: 3, md: 4 } }}>
{/* Search Section */} {/* Search Section */}
<Box sx={{ mb: 3 }}> <Box sx={{ mb: 3 }}>

View File

@ -22,6 +22,7 @@ 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';
// Mock 사용자 데이터 (API 연동 전까지 임시 사용) // Mock 사용자 데이터 (API 연동 전까지 임시 사용)
const mockUser = { const mockUser = {
@ -84,98 +85,137 @@ export default function HomePage() {
<Header title="대시보드" showBack={false} showMenu={false} showProfile={true} /> <Header title="대시보드" showBack={false} showMenu={false} showProfile={true} />
<Box <Box
sx={{ sx={{
pt: { xs: 7, sm: 8 },
pb: 10, pb: 10,
bgcolor: 'background.default', bgcolor: colors.gray[50],
minHeight: '100vh', minHeight: '100vh',
}} }}
> >
<Container maxWidth="lg" sx={{ pt: 4, pb: 4, px: { xs: 3, sm: 3, md: 4 } }}> <Container maxWidth="lg" sx={{ pt: 5, pb: 4, px: { xs: 3, sm: 4, md: 5 } }}>
{/* Welcome Section */} {/* Welcome Section */}
<Box sx={{ mb: 5 }}> <Box sx={{ mb: 6 }}>
<Typography <Typography
variant="h4" variant="h3"
sx={{ sx={{
fontWeight: 700, ...responsiveText.h2,
mb: 1, mb: 2,
color: 'text.primary',
}} }}
> >
, {mockUser.name}! , {mockUser.name}! 👋
</Typography> </Typography>
<Typography variant="body1" sx={{ color: 'text.secondary', fontWeight: 500 }}> <Typography variant="body1" sx={{ ...responsiveText.body1 }}>
</Typography> </Typography>
</Box> </Box>
{/* KPI Cards */} {/* KPI Cards */}
<Grid container spacing={3} sx={{ mb: 5 }}> <Grid container spacing={4} sx={{ mb: 6 }}>
<Grid item xs={4}> <Grid item xs={12} sm={4}>
<Card <Card
elevation={0} elevation={0}
sx={{ sx={{
bgcolor: 'primary.main', ...cardStyles.default,
borderRadius: 3, background: `linear-gradient(135deg, ${colors.purple} 0%, ${colors.purpleLight} 100%)`,
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)', borderColor: 'transparent',
}} }}
> >
<CardContent sx={{ textAlign: 'center', py: 3, px: 2 }}> <CardContent sx={{ textAlign: 'center', py: 4, px: 3 }}>
<Celebration sx={{ fontSize: 40, mb: 1.5, color: 'white' }} /> <Box
<Typography sx={{
variant="caption" width: 64,
display="block" height: 64,
sx={{ mb: 0.5, color: 'white', fontWeight: 600 }} 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>
<Typography variant="h5" sx={{ fontWeight: 700, color: 'white' }}> <Typography variant="h3" sx={{ fontWeight: 700, color: 'white', fontSize: '2.5rem' }}>
{activeEvents.length} {activeEvents.length}
</Typography> </Typography>
</CardContent> </CardContent>
</Card> </Card>
</Grid> </Grid>
<Grid item xs={4}> <Grid item xs={12} sm={4}>
<Card <Card
elevation={0} elevation={0}
sx={{ sx={{
bgcolor: 'secondary.main', ...cardStyles.default,
borderRadius: 3, background: `linear-gradient(135deg, ${colors.mint} 0%, ${colors.mintLight} 100%)`,
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)', borderColor: 'transparent',
}} }}
> >
<CardContent sx={{ textAlign: 'center', py: 3, px: 2 }}> <CardContent sx={{ textAlign: 'center', py: 4, px: 3 }}>
<Group sx={{ fontSize: 40, mb: 1.5, color: 'white' }} /> <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 <Typography
variant="caption" variant="body2"
display="block" sx={{ mb: 1, color: 'rgba(255, 255, 255, 0.9)', fontWeight: 500, fontSize: '0.875rem' }}
sx={{ mb: 0.5, color: 'white', fontWeight: 600 }}
> >
</Typography> </Typography>
<Typography variant="h5" sx={{ fontWeight: 700, color: 'white' }}> <Typography variant="h3" sx={{ fontWeight: 700, color: 'white', fontSize: '2.5rem' }}>
{totalParticipants.toLocaleString()} {totalParticipants.toLocaleString()}
</Typography> </Typography>
</CardContent> </CardContent>
</Card> </Card>
</Grid> </Grid>
<Grid item xs={4}> <Grid item xs={12} sm={4}>
<Card <Card
elevation={0} elevation={0}
sx={{ sx={{
bgcolor: 'info.main', ...cardStyles.default,
borderRadius: 3, background: `linear-gradient(135deg, ${colors.blue} 0%, ${colors.blueLight} 100%)`,
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)', borderColor: 'transparent',
}} }}
> >
<CardContent sx={{ textAlign: 'center', py: 3, px: 2 }}> <CardContent sx={{ textAlign: 'center', py: 4, px: 3 }}>
<TrendingUp sx={{ fontSize: 40, mb: 1.5, color: 'white' }} /> <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 <Typography
variant="caption" variant="body2"
display="block" sx={{ mb: 1, color: 'rgba(255, 255, 255, 0.9)', fontWeight: 500, fontSize: '0.875rem' }}
sx={{ mb: 0.5, color: 'white', fontWeight: 600 }}
> >
ROI ROI
</Typography> </Typography>
<Typography variant="h5" sx={{ fontWeight: 700, color: 'white' }}> <Typography variant="h3" sx={{ fontWeight: 700, color: 'white', fontSize: '2.5rem' }}>
{avgROI}% {avgROI}%
</Typography> </Typography>
</CardContent> </CardContent>
@ -184,81 +224,69 @@ export default function HomePage() {
</Grid> </Grid>
{/* Quick Actions */} {/* Quick Actions */}
<Box sx={{ mb: 5 }}> <Box sx={{ mb: 6 }}>
<Typography variant="h6" sx={{ fontWeight: 700, mb: 3, color: 'text.primary' }}> <Typography variant="h5" sx={{ ...responsiveText.h3, mb: 4 }}>
</Typography> </Typography>
<Grid container spacing={3}> <Grid container spacing={4}>
<Grid item xs={6}> <Grid item xs={6} sm={6}>
<Card <Card
elevation={0} elevation={0}
sx={{ sx={{
cursor: 'pointer', ...cardStyles.clickable,
borderRadius: 3,
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',
transition: 'all 0.2s ease',
'&:hover': {
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
transform: 'translateY(-2px)',
},
}} }}
onClick={handleCreateEvent} onClick={handleCreateEvent}
> >
<CardContent sx={{ textAlign: 'center', py: 4 }}> <CardContent sx={{ textAlign: 'center', py: 5 }}>
<Box <Box
sx={{ sx={{
width: 56, width: 72,
height: 56, height: 72,
borderRadius: '16px', borderRadius: '20px',
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', background: `linear-gradient(135deg, ${colors.purple} 0%, ${colors.blue} 100%)`,
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
margin: '0 auto', margin: '0 auto',
mb: 2, mb: 2.5,
boxShadow: '0 4px 14px 0 rgba(167, 139, 250, 0.39)',
}} }}
> >
<Add sx={{ fontSize: 32, color: 'white' }} /> <Add sx={{ fontSize: 36, color: 'white' }} />
</Box> </Box>
<Typography variant="body2" sx={{ fontWeight: 600, color: 'text.primary' }}> <Typography variant="body1" sx={{ fontWeight: 600, color: colors.gray[900] }}>
</Typography> </Typography>
</CardContent> </CardContent>
</Card> </Card>
</Grid> </Grid>
<Grid item xs={6}> <Grid item xs={6} sm={6}>
<Card <Card
elevation={0} elevation={0}
sx={{ sx={{
cursor: 'pointer', ...cardStyles.clickable,
borderRadius: 3,
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',
transition: 'all 0.2s ease',
'&:hover': {
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
transform: 'translateY(-2px)',
},
}} }}
onClick={handleViewAnalytics} onClick={handleViewAnalytics}
> >
<CardContent sx={{ textAlign: 'center', py: 4 }}> <CardContent sx={{ textAlign: 'center', py: 5 }}>
<Box <Box
sx={{ sx={{
width: 56, width: 72,
height: 56, height: 72,
borderRadius: '16px', borderRadius: '20px',
background: 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)', background: `linear-gradient(135deg, ${colors.blue} 0%, ${colors.mint} 100%)`,
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
margin: '0 auto', margin: '0 auto',
mb: 2, mb: 2.5,
boxShadow: '0 4px 14px 0 rgba(96, 165, 250, 0.39)',
}} }}
> >
<Analytics sx={{ fontSize: 32, color: 'white' }} /> <Analytics sx={{ fontSize: 36, color: 'white' }} />
</Box> </Box>
<Typography variant="body2" sx={{ fontWeight: 600, color: 'text.primary' }}> <Typography variant="body1" sx={{ fontWeight: 600, color: colors.gray[900] }}>
</Typography> </Typography>
</CardContent> </CardContent>
</Card> </Card>
@ -267,19 +295,19 @@ export default function HomePage() {
</Box> </Box>
{/* Active Events */} {/* Active Events */}
<Box sx={{ mb: 5 }}> <Box sx={{ mb: 6 }}>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 3 }}> <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 4 }}>
<Typography variant="h6" sx={{ fontWeight: 700, color: 'text.primary' }}> <Typography variant="h5" sx={{ ...responsiveText.h3 }}>
</Typography> </Typography>
<Button <Button
size="small" size="medium"
endIcon={<span className="material-icons">chevron_right</span>} endIcon={<span className="material-icons">chevron_right</span>}
onClick={() => router.push('/events')} onClick={() => router.push('/events')}
sx={{ sx={{
color: 'primary.main', color: colors.purple,
fontWeight: 600, fontWeight: 600,
'&:hover': { background: 'rgba(102, 126, 234, 0.08)' }, '&:hover': { bgcolor: 'rgba(167, 139, 250, 0.08)' },
}} }}
> >
@ -290,28 +318,30 @@ export default function HomePage() {
<Card <Card
elevation={0} elevation={0}
sx={{ sx={{
borderRadius: 3, ...cardStyles.default,
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',
}} }}
> >
<CardContent sx={{ textAlign: 'center', py: 8 }}> <CardContent sx={{ textAlign: 'center', py: 10 }}>
<Box sx={{ color: 'text.disabled', mb: 2 }}> <Box sx={{ color: colors.gray[300], mb: 3 }}>
<span className="material-icons" style={{ fontSize: 64 }}> <span className="material-icons" style={{ fontSize: 72 }}>
event_busy event_busy
</span> </span>
</Box> </Box>
<Typography variant="body1" color="text.secondary" sx={{ mb: 3 }}> <Typography variant="h6" sx={{ mb: 2, color: colors.gray[700] }}>
</Typography> </Typography>
<Typography variant="body2" sx={{ mb: 4, color: colors.gray[500] }}>
</Typography>
<Button <Button
variant="contained" variant="contained"
startIcon={<Add />} startIcon={<Add />}
onClick={handleCreateEvent} onClick={handleCreateEvent}
sx={{ sx={{
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', py: { xs: 1.5, sm: 1.75 },
'&:hover': { px: { xs: 3, sm: 4 },
background: 'linear-gradient(135deg, #5568d3 0%, #65408b 100%)', fontSize: { xs: 15, sm: 16 },
}, ...getGradientButtonStyle('primary'),
}} }}
> >
@ -319,59 +349,56 @@ export default function HomePage() {
</CardContent> </CardContent>
</Card> </Card>
) : ( ) : (
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}> <Box sx={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
{activeEvents.map((event) => ( {activeEvents.map((event) => (
<Card <Card
key={event.id} key={event.id}
elevation={0} elevation={0}
sx={{ sx={{
cursor: 'pointer', ...cardStyles.clickable,
borderRadius: 3,
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',
transition: 'all 0.2s ease',
'&:hover': {
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
transform: 'translateY(-2px)',
},
}} }}
onClick={() => handleEventClick(event.id)} onClick={() => handleEventClick(event.id)}
> >
<CardContent sx={{ p: 4 }}> <CardContent sx={{ p: { xs: 3, sm: 4 } }}>
<Box sx={{ display: 'flex', justifyContent: 'space-between', mb: 2 }}> <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'start', mb: 3 }}>
<Typography variant="subtitle1" sx={{ fontWeight: 700, color: 'text.primary' }}> <Typography variant="h6" sx={{ fontWeight: 700, color: colors.gray[900] }}>
{event.title} {event.title}
</Typography> </Typography>
<Box <Box
sx={{ sx={{
px: 2, px: 2.5,
py: 0.5, py: 0.75,
bgcolor: 'success.main', bgcolor: colors.mint,
color: 'white', color: 'white',
borderRadius: 2, borderRadius: 2,
fontSize: '0.75rem', fontSize: '0.875rem',
fontWeight: 700, fontWeight: 600,
}} }}
> >
{event.status} {event.status}
</Box> </Box>
</Box> </Box>
<Typography variant="body2" color="text.secondary" sx={{ mb: 2.5, fontWeight: 500 }}> <Typography variant="body2" sx={{ mb: 3, color: colors.gray[600], display: 'flex', alignItems: 'center', gap: 1 }}>
📅 {event.startDate} ~ {event.endDate} <span>📅</span>
<span>{event.startDate} ~ {event.endDate}</span>
</Typography> </Typography>
<Box sx={{ display: 'flex', gap: 5 }}> <Box sx={{ display: 'flex', gap: 6 }}>
<Box> <Box>
<Typography variant="caption" color="text.secondary" sx={{ fontWeight: 600 }}> <Typography variant="body2" sx={{ mb: 0.5, color: colors.gray[600], fontWeight: 500 }}>
</Typography> </Typography>
<Typography variant="h6" sx={{ fontWeight: 700, color: 'text.primary' }}> <Typography variant="h5" sx={{ fontWeight: 700, color: colors.gray[900] }}>
{event.participants.toLocaleString()} {event.participants.toLocaleString()}
<Typography component="span" variant="body2" sx={{ ml: 0.5, color: colors.gray[600] }}>
</Typography>
</Typography> </Typography>
</Box> </Box>
<Box> <Box>
<Typography variant="caption" color="text.secondary" sx={{ fontWeight: 600 }}> <Typography variant="body2" sx={{ mb: 0.5, color: colors.gray[600], fontWeight: 500 }}>
ROI ROI
</Typography> </Typography>
<Typography variant="h6" sx={{ fontWeight: 700, color: 'success.main' }}> <Typography variant="h5" sx={{ fontWeight: 700, color: colors.mint }}>
{event.roi}% {event.roi}%
</Typography> </Typography>
</Box> </Box>
@ -384,49 +411,48 @@ export default function HomePage() {
</Box> </Box>
{/* Recent Activity */} {/* Recent Activity */}
<Box sx={{ mb: 5 }}> <Box sx={{ mb: 6 }}>
<Typography variant="h6" sx={{ fontWeight: 700, mb: 3, color: 'text.primary' }}> <Typography variant="h5" sx={{ ...responsiveText.h3, mb: 4 }}>
</Typography> </Typography>
<Card <Card
elevation={0} elevation={0}
sx={{ sx={{
borderRadius: 3, ...cardStyles.default,
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',
}} }}
> >
<CardContent sx={{ p: 4 }}> <CardContent sx={{ p: { xs: 3, sm: 4 } }}>
{mockActivities.map((activity, index) => ( {mockActivities.map((activity, index) => (
<Box <Box
key={index} key={index}
sx={{ sx={{
display: 'flex', display: 'flex',
gap: 2.5, gap: 3,
pt: index > 0 ? 3 : 0, pt: index > 0 ? 3.5 : 0,
mt: index > 0 ? 3 : 0, mt: index > 0 ? 3.5 : 0,
borderTop: index > 0 ? 1 : 0, borderTop: index > 0 ? 1 : 0,
borderColor: 'divider', borderColor: colors.gray[200],
}} }}
> >
<Box <Box
sx={{ sx={{
width: 40, width: 48,
height: 40, height: 48,
borderRadius: '12px', borderRadius: '14px',
bgcolor: 'primary.main', background: `linear-gradient(135deg, ${colors.purple} 0%, ${colors.purpleLight} 100%)`,
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
flexShrink: 0, flexShrink: 0,
}} }}
> >
<activity.icon sx={{ fontSize: 20, color: 'white' }} /> <activity.icon sx={{ fontSize: 24, color: 'white' }} />
</Box> </Box>
<Box sx={{ flex: 1 }}> <Box sx={{ flex: 1 }}>
<Typography variant="body2" sx={{ fontWeight: 600, color: 'text.primary', mb: 0.5 }}> <Typography variant="body1" sx={{ fontWeight: 600, color: colors.gray[900], mb: 0.5 }}>
{activity.text} {activity.text}
</Typography> </Typography>
<Typography variant="caption" sx={{ color: 'text.secondary', fontWeight: 500 }}> <Typography variant="body2" sx={{ color: colors.gray[500] }}>
{activity.time} {activity.time}
</Typography> </Typography>
</Box> </Box>
@ -441,17 +467,19 @@ export default function HomePage() {
<Fab <Fab
sx={{ sx={{
position: 'fixed', position: 'fixed',
bottom: 80, bottom: { xs: 80, sm: 90 },
right: 16, right: { xs: 20, sm: 32 },
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', width: { xs: 64, sm: 72 },
transition: 'all 0.2s ease', height: { xs: 64, sm: 72 },
...getGradientButtonStyle('primary'),
boxShadow: '0 10px 25px -5px rgba(167, 139, 250, 0.5), 0 8px 10px -6px rgba(167, 139, 250, 0.5)',
'&:hover': { '&:hover': {
background: 'linear-gradient(135deg, #5568d3 0%, #65408b 100%)', 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}
> >
<Add sx={{ color: 'white' }} /> <Add sx={{ color: 'white', fontSize: { xs: 28, sm: 32 } }} />
</Fab> </Fab>
</Box> </Box>
</> </>

View File

@ -26,6 +26,7 @@ import {
import { Person, Visibility, VisibilityOff, CheckCircle } from '@mui/icons-material'; import { Person, Visibility, VisibilityOff, CheckCircle } from '@mui/icons-material';
import { useAuthStore } from '@/stores/authStore'; import { useAuthStore } from '@/stores/authStore';
import { useUIStore } from '@/stores/uiStore'; import { useUIStore } from '@/stores/uiStore';
import { getGradientButtonStyle, responsiveText, containerStyles } from '@/shared/lib/button-styles';
// 기본 정보 스키마 // 기본 정보 스키마
const basicInfoSchema = z.object({ const basicInfoSchema = z.object({
@ -185,8 +186,8 @@ export default function ProfilePage() {
}; };
return ( return (
<Box sx={{ minHeight: '100vh', bgcolor: 'background.default', pb: 10 }}> <Box sx={{ ...containerStyles.page }}>
<Box sx={{ maxWidth: 600, mx: 'auto', px: 3, py: 4 }}> <Box sx={{ maxWidth: 600, mx: 'auto', px: { xs: 3, sm: 4 }, py: { xs: 3, sm: 4 } }}>
{/* 사용자 정보 섹션 */} {/* 사용자 정보 섹션 */}
<Paper elevation={0} sx={{ p: 4, mb: 3, textAlign: 'center' }}> <Paper elevation={0} sx={{ p: 4, mb: 3, textAlign: 'center' }}>
<Avatar <Avatar
@ -201,7 +202,7 @@ export default function ProfilePage() {
> >
<Person sx={{ fontSize: 48 }} /> <Person sx={{ fontSize: 48 }} />
</Avatar> </Avatar>
<Typography variant="h5" sx={{ fontWeight: 700, mb: 0.5 }}> <Typography variant="h5" sx={{ ...responsiveText.h3, mb: 0.5 }}>
{user?.name} {user?.name}
</Typography> </Typography>
<Typography variant="body2" color="text.secondary"> <Typography variant="body2" color="text.secondary">
@ -211,7 +212,7 @@ export default function ProfilePage() {
{/* 기본 정보 */} {/* 기본 정보 */}
<Paper elevation={0} sx={{ p: 4, mb: 3 }}> <Paper elevation={0} sx={{ p: 4, mb: 3 }}>
<Typography variant="h6" sx={{ fontWeight: 700, mb: 3 }}> <Typography variant="h6" sx={{ ...responsiveText.h4, mb: 3 }}>
</Typography> </Typography>
@ -267,7 +268,7 @@ export default function ProfilePage() {
{/* 매장 정보 */} {/* 매장 정보 */}
<Paper elevation={0} sx={{ p: 4, mb: 3 }}> <Paper elevation={0} sx={{ p: 4, mb: 3 }}>
<Typography variant="h6" sx={{ fontWeight: 700, mb: 3 }}> <Typography variant="h6" sx={{ ...responsiveText.h4, mb: 3 }}>
</Typography> </Typography>
@ -336,7 +337,7 @@ export default function ProfilePage() {
{/* 비밀번호 변경 */} {/* 비밀번호 변경 */}
<Paper elevation={0} sx={{ p: 4, mb: 3 }}> <Paper elevation={0} sx={{ p: 4, mb: 3 }}>
<Typography variant="h6" sx={{ fontWeight: 700, mb: 3 }}> <Typography variant="h6" sx={{ ...responsiveText.h4, mb: 3 }}>
</Typography> </Typography>
@ -430,7 +431,13 @@ export default function ProfilePage() {
variant="outlined" variant="outlined"
size="large" size="large"
onClick={handlePasswordSubmit(onChangePassword)} onClick={handlePasswordSubmit(onChangePassword)}
sx={{ mt: 1 }} sx={{
mt: 1,
py: { xs: 1.5, sm: 1.75 },
fontSize: { xs: 15, sm: 16 },
fontWeight: 600,
borderWidth: 2,
}}
> >
</Button> </Button>
@ -444,7 +451,11 @@ export default function ProfilePage() {
variant="contained" variant="contained"
size="large" size="large"
onClick={handleSave} onClick={handleSave}
sx={{ py: 1.5 }} sx={{
py: { xs: 1.5, sm: 1.75 },
fontSize: { xs: 15, sm: 16 },
...getGradientButtonStyle('primary'),
}}
> >
</Button> </Button>
@ -454,7 +465,11 @@ export default function ProfilePage() {
size="large" size="large"
color="error" color="error"
onClick={() => setLogoutDialogOpen(true)} onClick={() => setLogoutDialogOpen(true)}
sx={{ py: 1.5 }} sx={{
py: { xs: 1.5, sm: 1.75 },
fontSize: { xs: 15, sm: 16 },
fontWeight: 600,
}}
> >
</Button> </Button>
@ -479,7 +494,11 @@ export default function ProfilePage() {
setSuccessDialogOpen(false); setSuccessDialogOpen(false);
window.location.reload(); window.location.reload();
}} }}
sx={{ minWidth: 120 }} sx={{
minWidth: 120,
py: { xs: 1.25, sm: 1.5 },
...getGradientButtonStyle('success'),
}}
> >
</Button> </Button>
@ -495,8 +514,17 @@ export default function ProfilePage() {
</Typography> </Typography>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setLogoutDialogOpen(false)}></Button> <Button
<Button variant="contained" onClick={handleLogout}> onClick={() => setLogoutDialogOpen(false)}
sx={{ fontWeight: 600 }}
>
</Button>
<Button
variant="contained"
onClick={handleLogout}
sx={{ ...getGradientButtonStyle('error') }}
>
</Button> </Button>
</DialogActions> </DialogActions>

View File

@ -0,0 +1,156 @@
// 새로운 디자인 시스템 색상 (참고 이미지 기반)
export const colors = {
mint: '#4DD6D3',
mintLight: '#7EE7E4',
purple: '#A78BFA',
purpleLight: '#C4B5FD',
blue: '#60A5FA',
blueLight: '#93C5FD',
pink: '#F472B6',
pinkLight: '#F9A8D4',
orange: '#FB923C',
orangeLight: '#FDBA74',
gray: {
50: '#F9FAFB',
100: '#F3F4F6',
200: '#E5E7EB',
300: '#D1D5DB',
400: '#9CA3AF',
500: '#6B7280',
600: '#4B5563',
700: '#374151',
800: '#1F2937',
900: '#111827',
},
};
// 공통 버튼 그라디언트 스타일
export const buttonGradients = {
primary: `linear-gradient(135deg, ${colors.purple} 0%, ${colors.blue} 100%)`,
primaryHover: `linear-gradient(135deg, ${colors.purpleLight} 0%, ${colors.blueLight} 100%)`,
secondary: `linear-gradient(135deg, ${colors.mint} 0%, ${colors.blue} 100%)`,
secondaryHover: `linear-gradient(135deg, ${colors.mintLight} 0%, ${colors.blueLight} 100%)`,
success: `linear-gradient(135deg, ${colors.mint} 0%, #34D399 100%)`,
successHover: `linear-gradient(135deg, ${colors.mintLight} 0%, #6EE7B7 100%)`,
error: `linear-gradient(135deg, #EF4444 0%, ${colors.pink} 100%)`,
errorHover: `linear-gradient(135deg, #F87171 0%, ${colors.pinkLight} 100%)`,
warning: `linear-gradient(135deg, ${colors.orange} 0%, #FBBF24 100%)`,
warningHover: `linear-gradient(135deg, ${colors.orangeLight} 0%, #FCD34D 100%)`,
info: `linear-gradient(135deg, ${colors.blue} 0%, ${colors.mint} 100%)`,
infoHover: `linear-gradient(135deg, ${colors.blueLight} 0%, ${colors.mintLight} 100%)`,
};
// 공통 버튼 스타일
export const getGradientButtonStyle = (variant: keyof typeof buttonGradients = 'primary') => ({
background: buttonGradients[variant],
color: 'white',
fontWeight: 600,
borderRadius: 3,
textTransform: 'none' as const,
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
boxShadow: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
'&:hover': {
background: buttonGradients[`${variant}Hover` as keyof typeof buttonGradients],
transform: 'translateY(-2px)',
boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
},
'&:active': {
transform: 'translateY(0)',
},
});
// 공통 카드 스타일
export const cardStyles = {
default: {
borderRadius: 4,
bgcolor: 'white',
boxShadow: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
border: '1px solid',
borderColor: colors.gray[100],
},
hover: {
'&:hover': {
boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
transform: 'translateY(-4px)',
borderColor: colors.gray[200],
},
},
clickable: {
cursor: 'pointer',
borderRadius: 4,
bgcolor: 'white',
boxShadow: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
border: '1px solid',
borderColor: colors.gray[100],
'&:hover': {
boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
transform: 'translateY(-4px)',
borderColor: colors.gray[200],
},
},
};
// 공통 컨테이너 스타일
export const containerStyles = {
page: {
pt: { xs: 7, sm: 8 },
minHeight: '100vh',
bgcolor: colors.gray[50],
pb: 10,
},
section: {
maxWidth: 'lg',
mx: 'auto',
px: { xs: 3, sm: 4, md: 5 },
py: { xs: 4, sm: 5 },
},
centeredForm: {
minHeight: '100vh',
display: 'flex',
flexDirection: 'column' as const,
justifyContent: 'center',
alignItems: 'center',
px: 3,
py: 8,
bgcolor: colors.gray[50],
},
};
// 공통 반응형 텍스트 스타일
export const responsiveText = {
h1: {
fontSize: { xs: '1.875rem', sm: '2.25rem', md: '3rem' },
fontWeight: 700,
color: colors.gray[900],
letterSpacing: '-0.025em',
},
h2: {
fontSize: { xs: '1.5rem', sm: '1.875rem', md: '2.25rem' },
fontWeight: 700,
color: colors.gray[900],
letterSpacing: '-0.025em',
},
h3: {
fontSize: { xs: '1.25rem', sm: '1.5rem', md: '1.875rem' },
fontWeight: 600,
color: colors.gray[900],
letterSpacing: '-0.025em',
},
h4: {
fontSize: { xs: '1.125rem', sm: '1.25rem', md: '1.5rem' },
fontWeight: 600,
color: colors.gray[800],
},
body1: {
fontSize: { xs: '0.875rem', sm: '1rem' },
color: colors.gray[700],
lineHeight: 1.6,
},
body2: {
fontSize: { xs: '0.8125rem', sm: '0.875rem' },
color: colors.gray[600],
lineHeight: 1.5,
},
};