mirror of
https://github.com/ktds-dg0501/kt-event-marketing-fe.git
synced 2025-12-06 10:16:25 +00:00
참고 디자인을 기반으로 전면 리디자인 완료
## 주요 변경사항
### 디자인 시스템 개선
- 새로운 색상 팔레트 적용 (민트, 보라, 파랑 기반)
- 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:
parent
edcd0cd559
commit
01a77fe7a8
@ -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'),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
로그인
|
로그인
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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 }}>
|
||||||
|
|||||||
@ -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>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
156
src/shared/lib/button-styles.ts
Normal file
156
src/shared/lib/button-styles.ts
Normal 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,
|
||||||
|
},
|
||||||
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user