mirror of
https://github.com/ktds-dg0501/kt-event-marketing-fe.git
synced 2025-12-06 11:36:24 +00:00
그래디언트 배경 카드 텍스트 가독성 개선 및 입체감 추가
- 배경색이 있는 모든 카드의 흰색 글자를 검은색으로 변경하여 가독성 향상 - 아이콘과 텍스트에 그림자 효과를 추가하여 입체감 부여 - Profile 페이지 디자인 통일성 완료 변경 파일: - src/app/(main)/page.tsx: 대시보드 KPI 카드 (3개) - src/app/(main)/events/page.tsx: 이벤트 통계 카드 (4개) - src/app/(main)/events/create/steps/ApprovalStep.tsx: 승인 단계 요약 카드 (4개) - src/app/(main)/profile/page.tsx: 프로필 페이지 전체 리디자인 적용된 효과: - 아이콘: drop-shadow(0px 2px 4px rgba(0,0,0,0.2)) - 큰 텍스트: text-shadow 0px 2px 4px rgba(0,0,0,0.15) - 작은 텍스트: text-shadow 0px 1px 2px rgba(0,0,0,0.1) - 아이콘 배경: rgba(0,0,0,0.05) (대시보드) - 글자 색상: colors.gray[900] (제목), colors.gray[700] (라벨)
This commit is contained in:
parent
56d3071b19
commit
47ed0b5a7c
@ -97,13 +97,28 @@ export default function ApprovalStep({ eventData, onApprove, onBack }: ApprovalS
|
||||
}}
|
||||
>
|
||||
<CardContent sx={{ textAlign: 'center', py: 4, px: 3 }}>
|
||||
<CheckCircle sx={{ fontSize: 32, color: 'white', mb: 1 }} />
|
||||
<Typography variant="body2" sx={{ color: 'rgba(255,255,255,0.9)', fontSize: '0.875rem', mb: 1 }}>
|
||||
<CheckCircle sx={{
|
||||
fontSize: 32,
|
||||
color: colors.gray[900],
|
||||
mb: 1,
|
||||
filter: 'drop-shadow(0px 2px 4px rgba(0,0,0,0.2))',
|
||||
}} />
|
||||
<Typography variant="body2" sx={{
|
||||
color: colors.gray[700],
|
||||
fontSize: '0.875rem',
|
||||
mb: 1,
|
||||
textShadow: '0px 1px 2px rgba(0,0,0,0.1)',
|
||||
}}>
|
||||
이벤트 제목
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="h6"
|
||||
sx={{ fontWeight: 700, color: 'white', fontSize: '1rem' }}
|
||||
sx={{
|
||||
fontWeight: 700,
|
||||
color: colors.gray[900],
|
||||
fontSize: '1rem',
|
||||
textShadow: '0px 2px 4px rgba(0,0,0,0.15)',
|
||||
}}
|
||||
>
|
||||
{eventData.recommendation?.title || '이벤트 제목'}
|
||||
</Typography>
|
||||
@ -120,16 +135,36 @@ export default function ApprovalStep({ eventData, onApprove, onBack }: ApprovalS
|
||||
}}
|
||||
>
|
||||
<CardContent sx={{ textAlign: 'center', py: 4, px: 3 }}>
|
||||
<People sx={{ fontSize: 32, color: 'white', mb: 1 }} />
|
||||
<Typography variant="body2" sx={{ color: 'rgba(255,255,255,0.9)', fontSize: '0.875rem', mb: 1 }}>
|
||||
<People sx={{
|
||||
fontSize: 32,
|
||||
color: colors.gray[900],
|
||||
mb: 1,
|
||||
filter: 'drop-shadow(0px 2px 4px rgba(0,0,0,0.2))',
|
||||
}} />
|
||||
<Typography variant="body2" sx={{
|
||||
color: colors.gray[700],
|
||||
fontSize: '0.875rem',
|
||||
mb: 1,
|
||||
textShadow: '0px 1px 2px rgba(0,0,0,0.1)',
|
||||
}}>
|
||||
목표 참여자
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="h4"
|
||||
sx={{ fontWeight: 700, color: 'white', fontSize: '1.75rem' }}
|
||||
sx={{
|
||||
fontWeight: 700,
|
||||
color: colors.gray[900],
|
||||
fontSize: '1.75rem',
|
||||
textShadow: '0px 2px 4px rgba(0,0,0,0.15)',
|
||||
}}
|
||||
>
|
||||
{eventData.recommendation?.expectedParticipants || 0}
|
||||
<Typography component="span" sx={{ fontSize: '1rem', ml: 0.5 }}>
|
||||
<Typography component="span" sx={{
|
||||
fontSize: '1rem',
|
||||
ml: 0.5,
|
||||
color: colors.gray[900],
|
||||
textShadow: '0px 2px 4px rgba(0,0,0,0.15)',
|
||||
}}>
|
||||
명
|
||||
</Typography>
|
||||
</Typography>
|
||||
@ -146,16 +181,36 @@ export default function ApprovalStep({ eventData, onApprove, onBack }: ApprovalS
|
||||
}}
|
||||
>
|
||||
<CardContent sx={{ textAlign: 'center', py: 4, px: 3 }}>
|
||||
<AttachMoney sx={{ fontSize: 32, color: 'white', mb: 1 }} />
|
||||
<Typography variant="body2" sx={{ color: 'rgba(255,255,255,0.9)', fontSize: '0.875rem', mb: 1 }}>
|
||||
<AttachMoney sx={{
|
||||
fontSize: 32,
|
||||
color: colors.gray[900],
|
||||
mb: 1,
|
||||
filter: 'drop-shadow(0px 2px 4px rgba(0,0,0,0.2))',
|
||||
}} />
|
||||
<Typography variant="body2" sx={{
|
||||
color: colors.gray[700],
|
||||
fontSize: '0.875rem',
|
||||
mb: 1,
|
||||
textShadow: '0px 1px 2px rgba(0,0,0,0.1)',
|
||||
}}>
|
||||
예상 비용
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="h4"
|
||||
sx={{ fontWeight: 700, color: 'white', fontSize: '1.75rem' }}
|
||||
sx={{
|
||||
fontWeight: 700,
|
||||
color: colors.gray[900],
|
||||
fontSize: '1.75rem',
|
||||
textShadow: '0px 2px 4px rgba(0,0,0,0.15)',
|
||||
}}
|
||||
>
|
||||
{((eventData.recommendation?.estimatedCost || 0) / 10000).toFixed(0)}
|
||||
<Typography component="span" sx={{ fontSize: '1rem', ml: 0.5 }}>
|
||||
<Typography component="span" sx={{
|
||||
fontSize: '1rem',
|
||||
ml: 0.5,
|
||||
color: colors.gray[900],
|
||||
textShadow: '0px 2px 4px rgba(0,0,0,0.15)',
|
||||
}}>
|
||||
만원
|
||||
</Typography>
|
||||
</Typography>
|
||||
@ -172,13 +227,28 @@ export default function ApprovalStep({ eventData, onApprove, onBack }: ApprovalS
|
||||
}}
|
||||
>
|
||||
<CardContent sx={{ textAlign: 'center', py: 4, px: 3 }}>
|
||||
<TrendingUp sx={{ fontSize: 32, color: 'white', mb: 1 }} />
|
||||
<Typography variant="body2" sx={{ color: 'rgba(255,255,255,0.9)', fontSize: '0.875rem', mb: 1 }}>
|
||||
<TrendingUp sx={{
|
||||
fontSize: 32,
|
||||
color: colors.gray[900],
|
||||
mb: 1,
|
||||
filter: 'drop-shadow(0px 2px 4px rgba(0,0,0,0.2))',
|
||||
}} />
|
||||
<Typography variant="body2" sx={{
|
||||
color: colors.gray[700],
|
||||
fontSize: '0.875rem',
|
||||
mb: 1,
|
||||
textShadow: '0px 1px 2px rgba(0,0,0,0.1)',
|
||||
}}>
|
||||
예상 ROI
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="h4"
|
||||
sx={{ fontWeight: 700, color: 'white', fontSize: '1.75rem' }}
|
||||
sx={{
|
||||
fontWeight: 700,
|
||||
color: colors.gray[900],
|
||||
fontSize: '1.75rem',
|
||||
textShadow: '0px 2px 4px rgba(0,0,0,0.15)',
|
||||
}}
|
||||
>
|
||||
{eventData.recommendation?.roi || 0}%
|
||||
</Typography>
|
||||
|
||||
@ -250,14 +250,29 @@ export default function EventsPage() {
|
||||
}}
|
||||
>
|
||||
<CardContent sx={{ textAlign: 'center', py: 4, px: 3 }}>
|
||||
<Event sx={{ fontSize: 32, color: 'white', mb: 1 }} />
|
||||
<Event sx={{
|
||||
fontSize: 32,
|
||||
color: colors.gray[900],
|
||||
mb: 1,
|
||||
filter: 'drop-shadow(0px 2px 4px rgba(0,0,0,0.2))',
|
||||
}} />
|
||||
<Typography
|
||||
variant="h4"
|
||||
sx={{ fontWeight: 700, color: 'white', fontSize: '1.75rem', mb: 0.5 }}
|
||||
sx={{
|
||||
fontWeight: 700,
|
||||
color: colors.gray[900],
|
||||
fontSize: '1.75rem',
|
||||
mb: 0.5,
|
||||
textShadow: '0px 2px 4px rgba(0,0,0,0.15)',
|
||||
}}
|
||||
>
|
||||
{stats.total}
|
||||
</Typography>
|
||||
<Typography variant="body2" sx={{ color: 'rgba(255,255,255,0.9)', fontSize: '0.875rem' }}>
|
||||
<Typography variant="body2" sx={{
|
||||
color: colors.gray[700],
|
||||
fontSize: '0.875rem',
|
||||
textShadow: '0px 1px 2px rgba(0,0,0,0.1)',
|
||||
}}>
|
||||
전체 이벤트
|
||||
</Typography>
|
||||
</CardContent>
|
||||
@ -273,14 +288,29 @@ export default function EventsPage() {
|
||||
}}
|
||||
>
|
||||
<CardContent sx={{ textAlign: 'center', py: 4, px: 3 }}>
|
||||
<LocalFireDepartment sx={{ fontSize: 32, color: 'white', mb: 1 }} />
|
||||
<LocalFireDepartment sx={{
|
||||
fontSize: 32,
|
||||
color: colors.gray[900],
|
||||
mb: 1,
|
||||
filter: 'drop-shadow(0px 2px 4px rgba(0,0,0,0.2))',
|
||||
}} />
|
||||
<Typography
|
||||
variant="h4"
|
||||
sx={{ fontWeight: 700, color: 'white', fontSize: '1.75rem', mb: 0.5 }}
|
||||
sx={{
|
||||
fontWeight: 700,
|
||||
color: colors.gray[900],
|
||||
fontSize: '1.75rem',
|
||||
mb: 0.5,
|
||||
textShadow: '0px 2px 4px rgba(0,0,0,0.15)',
|
||||
}}
|
||||
>
|
||||
{stats.active}
|
||||
</Typography>
|
||||
<Typography variant="body2" sx={{ color: 'rgba(255,255,255,0.9)', fontSize: '0.875rem' }}>
|
||||
<Typography variant="body2" sx={{
|
||||
color: colors.gray[700],
|
||||
fontSize: '0.875rem',
|
||||
textShadow: '0px 1px 2px rgba(0,0,0,0.1)',
|
||||
}}>
|
||||
진행중
|
||||
</Typography>
|
||||
</CardContent>
|
||||
@ -296,14 +326,29 @@ export default function EventsPage() {
|
||||
}}
|
||||
>
|
||||
<CardContent sx={{ textAlign: 'center', py: 4, px: 3 }}>
|
||||
<People sx={{ fontSize: 32, color: 'white', mb: 1 }} />
|
||||
<People sx={{
|
||||
fontSize: 32,
|
||||
color: colors.gray[900],
|
||||
mb: 1,
|
||||
filter: 'drop-shadow(0px 2px 4px rgba(0,0,0,0.2))',
|
||||
}} />
|
||||
<Typography
|
||||
variant="h4"
|
||||
sx={{ fontWeight: 700, color: 'white', fontSize: '1.75rem', mb: 0.5 }}
|
||||
sx={{
|
||||
fontWeight: 700,
|
||||
color: colors.gray[900],
|
||||
fontSize: '1.75rem',
|
||||
mb: 0.5,
|
||||
textShadow: '0px 2px 4px rgba(0,0,0,0.15)',
|
||||
}}
|
||||
>
|
||||
{stats.totalParticipants}
|
||||
</Typography>
|
||||
<Typography variant="body2" sx={{ color: 'rgba(255,255,255,0.9)', fontSize: '0.875rem' }}>
|
||||
<Typography variant="body2" sx={{
|
||||
color: colors.gray[700],
|
||||
fontSize: '0.875rem',
|
||||
textShadow: '0px 1px 2px rgba(0,0,0,0.1)',
|
||||
}}>
|
||||
총 참여자
|
||||
</Typography>
|
||||
</CardContent>
|
||||
@ -319,14 +364,29 @@ export default function EventsPage() {
|
||||
}}
|
||||
>
|
||||
<CardContent sx={{ textAlign: 'center', py: 4, px: 3 }}>
|
||||
<TrendingUp sx={{ fontSize: 32, color: 'white', mb: 1 }} />
|
||||
<TrendingUp sx={{
|
||||
fontSize: 32,
|
||||
color: colors.gray[900],
|
||||
mb: 1,
|
||||
filter: 'drop-shadow(0px 2px 4px rgba(0,0,0,0.2))',
|
||||
}} />
|
||||
<Typography
|
||||
variant="h4"
|
||||
sx={{ fontWeight: 700, color: 'white', fontSize: '1.75rem', mb: 0.5 }}
|
||||
sx={{
|
||||
fontWeight: 700,
|
||||
color: colors.gray[900],
|
||||
fontSize: '1.75rem',
|
||||
mb: 0.5,
|
||||
textShadow: '0px 2px 4px rgba(0,0,0,0.15)',
|
||||
}}
|
||||
>
|
||||
{stats.avgROI}%
|
||||
</Typography>
|
||||
<Typography variant="body2" sx={{ color: 'rgba(255,255,255,0.9)', fontSize: '0.875rem' }}>
|
||||
<Typography variant="body2" sx={{
|
||||
color: colors.gray[700],
|
||||
fontSize: '0.875rem',
|
||||
textShadow: '0px 1px 2px rgba(0,0,0,0.1)',
|
||||
}}>
|
||||
평균 ROI
|
||||
</Typography>
|
||||
</CardContent>
|
||||
|
||||
@ -122,7 +122,7 @@ export default function HomePage() {
|
||||
width: 64,
|
||||
height: 64,
|
||||
borderRadius: '50%',
|
||||
bgcolor: 'rgba(255, 255, 255, 0.2)',
|
||||
bgcolor: 'rgba(0, 0, 0, 0.05)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
@ -130,22 +130,32 @@ export default function HomePage() {
|
||||
mb: 3,
|
||||
}}
|
||||
>
|
||||
<Celebration sx={{ fontSize: 32, color: 'white' }} />
|
||||
<Celebration sx={{
|
||||
fontSize: 32,
|
||||
color: colors.gray[900],
|
||||
filter: 'drop-shadow(0px 2px 4px rgba(0,0,0,0.2))',
|
||||
}} />
|
||||
</Box>
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{
|
||||
mb: 1,
|
||||
color: 'rgba(255, 255, 255, 0.9)',
|
||||
color: colors.gray[700],
|
||||
fontWeight: 500,
|
||||
fontSize: '0.875rem',
|
||||
textShadow: '0px 1px 2px rgba(0,0,0,0.1)',
|
||||
}}
|
||||
>
|
||||
진행 중인 이벤트
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="h3"
|
||||
sx={{ fontWeight: 700, color: 'white', fontSize: '2.25rem' }}
|
||||
sx={{
|
||||
fontWeight: 700,
|
||||
color: colors.gray[900],
|
||||
fontSize: '2.25rem',
|
||||
textShadow: '0px 2px 4px rgba(0,0,0,0.15)',
|
||||
}}
|
||||
>
|
||||
{activeEvents.length}
|
||||
</Typography>
|
||||
@ -167,7 +177,7 @@ export default function HomePage() {
|
||||
width: 64,
|
||||
height: 64,
|
||||
borderRadius: '50%',
|
||||
bgcolor: 'rgba(255, 255, 255, 0.2)',
|
||||
bgcolor: 'rgba(0, 0, 0, 0.05)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
@ -175,22 +185,32 @@ export default function HomePage() {
|
||||
mb: 3,
|
||||
}}
|
||||
>
|
||||
<Group sx={{ fontSize: 32, color: 'white' }} />
|
||||
<Group sx={{
|
||||
fontSize: 32,
|
||||
color: colors.gray[900],
|
||||
filter: 'drop-shadow(0px 2px 4px rgba(0,0,0,0.2))',
|
||||
}} />
|
||||
</Box>
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{
|
||||
mb: 1,
|
||||
color: 'rgba(255, 255, 255, 0.9)',
|
||||
color: colors.gray[700],
|
||||
fontWeight: 500,
|
||||
fontSize: '0.875rem',
|
||||
textShadow: '0px 1px 2px rgba(0,0,0,0.1)',
|
||||
}}
|
||||
>
|
||||
총 참여자
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="h3"
|
||||
sx={{ fontWeight: 700, color: 'white', fontSize: '2.25rem' }}
|
||||
sx={{
|
||||
fontWeight: 700,
|
||||
color: colors.gray[900],
|
||||
fontSize: '2.25rem',
|
||||
textShadow: '0px 2px 4px rgba(0,0,0,0.15)',
|
||||
}}
|
||||
>
|
||||
{totalParticipants.toLocaleString()}
|
||||
</Typography>
|
||||
@ -212,7 +232,7 @@ export default function HomePage() {
|
||||
width: 64,
|
||||
height: 64,
|
||||
borderRadius: '50%',
|
||||
bgcolor: 'rgba(255, 255, 255, 0.2)',
|
||||
bgcolor: 'rgba(0, 0, 0, 0.05)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
@ -220,22 +240,32 @@ export default function HomePage() {
|
||||
mb: 3,
|
||||
}}
|
||||
>
|
||||
<TrendingUp sx={{ fontSize: 32, color: 'white' }} />
|
||||
<TrendingUp sx={{
|
||||
fontSize: 32,
|
||||
color: colors.gray[900],
|
||||
filter: 'drop-shadow(0px 2px 4px rgba(0,0,0,0.2))',
|
||||
}} />
|
||||
</Box>
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{
|
||||
mb: 1,
|
||||
color: 'rgba(255, 255, 255, 0.9)',
|
||||
color: colors.gray[700],
|
||||
fontWeight: 500,
|
||||
fontSize: '0.875rem',
|
||||
textShadow: '0px 1px 2px rgba(0,0,0,0.1)',
|
||||
}}
|
||||
>
|
||||
평균 ROI
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="h3"
|
||||
sx={{ fontWeight: 700, color: 'white', fontSize: '2.25rem' }}
|
||||
sx={{
|
||||
fontWeight: 700,
|
||||
color: colors.gray[900],
|
||||
fontSize: '2.25rem',
|
||||
textShadow: '0px 2px 4px rgba(0,0,0,0.15)',
|
||||
}}
|
||||
>
|
||||
{avgROI}%
|
||||
</Typography>
|
||||
|
||||
@ -7,10 +7,12 @@ import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { z } from 'zod';
|
||||
import {
|
||||
Box,
|
||||
Container,
|
||||
TextField,
|
||||
Button,
|
||||
Typography,
|
||||
Paper,
|
||||
Card,
|
||||
CardContent,
|
||||
Avatar,
|
||||
Select,
|
||||
MenuItem,
|
||||
@ -26,7 +28,8 @@ import {
|
||||
import { Person, Visibility, VisibilityOff, CheckCircle } from '@mui/icons-material';
|
||||
import { useAuthStore } from '@/stores/authStore';
|
||||
import { useUIStore } from '@/stores/uiStore';
|
||||
import { getGradientButtonStyle, responsiveText, containerStyles } from '@/shared/lib/button-styles';
|
||||
import Header from '@/shared/ui/Header';
|
||||
import { cardStyles, colors, responsiveText } from '@/shared/lib/button-styles';
|
||||
|
||||
// 기본 정보 스키마
|
||||
const basicInfoSchema = z.object({
|
||||
@ -186,304 +189,341 @@ export default function ProfilePage() {
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ ...containerStyles.page }}>
|
||||
<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' }}>
|
||||
<Avatar
|
||||
sx={{
|
||||
width: 80,
|
||||
height: 80,
|
||||
mx: 'auto',
|
||||
mb: 2,
|
||||
bgcolor: 'grey.100',
|
||||
color: 'grey.400',
|
||||
}}
|
||||
>
|
||||
<Person sx={{ fontSize: 48 }} />
|
||||
</Avatar>
|
||||
<Typography variant="h5" sx={{ ...responsiveText.h3, mb: 0.5 }}>
|
||||
{user?.name}
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
{user?.email}
|
||||
</Typography>
|
||||
</Paper>
|
||||
<>
|
||||
<Header title="프로필" showBack={true} showMenu={false} showProfile={false} />
|
||||
<Box
|
||||
sx={{
|
||||
pt: { xs: 7, sm: 8 },
|
||||
pb: 10,
|
||||
bgcolor: colors.gray[50],
|
||||
minHeight: '100vh',
|
||||
}}
|
||||
>
|
||||
<Container maxWidth="lg" sx={{ pt: 8, pb: 6, px: { xs: 6, sm: 8, md: 10 } }}>
|
||||
{/* 사용자 정보 섹션 */}
|
||||
<Card elevation={0} sx={{ ...cardStyles.default, mb: 10, textAlign: 'center' }}>
|
||||
<CardContent sx={{ p: { xs: 6, sm: 8 } }}>
|
||||
<Avatar
|
||||
sx={{
|
||||
width: 100,
|
||||
height: 100,
|
||||
mx: 'auto',
|
||||
mb: 3,
|
||||
bgcolor: colors.purple,
|
||||
color: 'white',
|
||||
}}
|
||||
>
|
||||
<Person sx={{ fontSize: 56 }} />
|
||||
</Avatar>
|
||||
<Typography variant="h5" sx={{ ...responsiveText.h3, mb: 1 }}>
|
||||
{user?.name}
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary" sx={{ ...responsiveText.body1 }}>
|
||||
{user?.email}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* 기본 정보 */}
|
||||
<Paper elevation={0} sx={{ p: 4, mb: 3 }}>
|
||||
<Typography variant="h6" sx={{ ...responsiveText.h4, mb: 3 }}>
|
||||
기본 정보
|
||||
</Typography>
|
||||
{/* 기본 정보 */}
|
||||
<Card elevation={0} sx={{ ...cardStyles.default, mb: 10 }}>
|
||||
<CardContent sx={{ p: { xs: 6, sm: 8 } }}>
|
||||
<Typography variant="h6" sx={{ ...responsiveText.h4, fontWeight: 700, mb: 6 }}>
|
||||
기본 정보
|
||||
</Typography>
|
||||
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
|
||||
<Controller
|
||||
name="name"
|
||||
control={basicControl}
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fullWidth
|
||||
label="이름"
|
||||
error={!!basicErrors.name}
|
||||
helperText={basicErrors.name?.message}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
name="phone"
|
||||
control={basicControl}
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fullWidth
|
||||
label="전화번호"
|
||||
onChange={(e) => {
|
||||
const formatted = formatPhoneNumber(e.target.value);
|
||||
field.onChange(formatted);
|
||||
}}
|
||||
error={!!basicErrors.phone}
|
||||
helperText={basicErrors.phone?.message}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
name="email"
|
||||
control={basicControl}
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fullWidth
|
||||
label="이메일"
|
||||
type="email"
|
||||
error={!!basicErrors.email}
|
||||
helperText={basicErrors.email?.message}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Box>
|
||||
</Paper>
|
||||
|
||||
{/* 매장 정보 */}
|
||||
<Paper elevation={0} sx={{ p: 4, mb: 3 }}>
|
||||
<Typography variant="h6" sx={{ ...responsiveText.h4, mb: 3 }}>
|
||||
매장 정보
|
||||
</Typography>
|
||||
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
|
||||
<Controller
|
||||
name="businessName"
|
||||
control={businessControl}
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fullWidth
|
||||
label="매장명"
|
||||
error={!!businessErrors.businessName}
|
||||
helperText={businessErrors.businessName?.message}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
name="businessType"
|
||||
control={businessControl}
|
||||
render={({ field }) => (
|
||||
<FormControl fullWidth error={!!businessErrors.businessType}>
|
||||
<InputLabel>업종</InputLabel>
|
||||
<Select {...field} label="업종">
|
||||
<MenuItem value="restaurant">음식점</MenuItem>
|
||||
<MenuItem value="cafe">카페/베이커리</MenuItem>
|
||||
<MenuItem value="retail">소매/편의점</MenuItem>
|
||||
<MenuItem value="beauty">미용/뷰티</MenuItem>
|
||||
<MenuItem value="fitness">헬스/피트니스</MenuItem>
|
||||
<MenuItem value="education">학원/교육</MenuItem>
|
||||
<MenuItem value="service">서비스업</MenuItem>
|
||||
<MenuItem value="other">기타</MenuItem>
|
||||
</Select>
|
||||
{businessErrors.businessType && (
|
||||
<Typography variant="caption" color="error" sx={{ mt: 0.5, ml: 2 }}>
|
||||
{businessErrors.businessType.message}
|
||||
</Typography>
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
|
||||
<Controller
|
||||
name="name"
|
||||
control={basicControl}
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fullWidth
|
||||
label="이름"
|
||||
error={!!basicErrors.name}
|
||||
helperText={basicErrors.name?.message}
|
||||
/>
|
||||
)}
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
name="businessLocation"
|
||||
control={businessControl}
|
||||
render={({ field }) => (
|
||||
<TextField {...field} fullWidth label="주소" />
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
name="businessHours"
|
||||
control={businessControl}
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fullWidth
|
||||
label="영업시간"
|
||||
placeholder="예: 10:00 ~ 22:00"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Box>
|
||||
</Paper>
|
||||
|
||||
{/* 비밀번호 변경 */}
|
||||
<Paper elevation={0} sx={{ p: 4, mb: 3 }}>
|
||||
<Typography variant="h6" sx={{ ...responsiveText.h4, mb: 3 }}>
|
||||
비밀번호 변경
|
||||
</Typography>
|
||||
<Controller
|
||||
name="phone"
|
||||
control={basicControl}
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fullWidth
|
||||
label="전화번호"
|
||||
onChange={(e) => {
|
||||
const formatted = formatPhoneNumber(e.target.value);
|
||||
field.onChange(formatted);
|
||||
}}
|
||||
error={!!basicErrors.phone}
|
||||
helperText={basicErrors.phone?.message}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
|
||||
<Controller
|
||||
name="currentPassword"
|
||||
control={passwordControl}
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
<Controller
|
||||
name="email"
|
||||
control={basicControl}
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fullWidth
|
||||
label="이메일"
|
||||
type="email"
|
||||
error={!!basicErrors.email}
|
||||
helperText={basicErrors.email?.message}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Box>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* 매장 정보 */}
|
||||
<Card elevation={0} sx={{ ...cardStyles.default, mb: 10 }}>
|
||||
<CardContent sx={{ p: { xs: 6, sm: 8 } }}>
|
||||
<Typography variant="h6" sx={{ ...responsiveText.h4, fontWeight: 700, mb: 6 }}>
|
||||
매장 정보
|
||||
</Typography>
|
||||
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
|
||||
<Controller
|
||||
name="businessName"
|
||||
control={businessControl}
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fullWidth
|
||||
label="매장명"
|
||||
error={!!businessErrors.businessName}
|
||||
helperText={businessErrors.businessName?.message}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
name="businessType"
|
||||
control={businessControl}
|
||||
render={({ field }) => (
|
||||
<FormControl fullWidth error={!!businessErrors.businessType}>
|
||||
<InputLabel>업종</InputLabel>
|
||||
<Select {...field} label="업종">
|
||||
<MenuItem value="restaurant">음식점</MenuItem>
|
||||
<MenuItem value="cafe">카페/베이커리</MenuItem>
|
||||
<MenuItem value="retail">소매/편의점</MenuItem>
|
||||
<MenuItem value="beauty">미용/뷰티</MenuItem>
|
||||
<MenuItem value="fitness">헬스/피트니스</MenuItem>
|
||||
<MenuItem value="education">학원/교육</MenuItem>
|
||||
<MenuItem value="service">서비스업</MenuItem>
|
||||
<MenuItem value="other">기타</MenuItem>
|
||||
</Select>
|
||||
{businessErrors.businessType && (
|
||||
<Typography variant="caption" color="error" sx={{ mt: 0.5, ml: 2 }}>
|
||||
{businessErrors.businessType.message}
|
||||
</Typography>
|
||||
)}
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
name="businessLocation"
|
||||
control={businessControl}
|
||||
render={({ field }) => (
|
||||
<TextField {...field} fullWidth label="주소" />
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
name="businessHours"
|
||||
control={businessControl}
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fullWidth
|
||||
label="영업시간"
|
||||
placeholder="예: 10:00 ~ 22:00"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Box>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* 비밀번호 변경 */}
|
||||
<Card elevation={0} sx={{ ...cardStyles.default, mb: 10 }}>
|
||||
<CardContent sx={{ p: { xs: 6, sm: 8 } }}>
|
||||
<Typography variant="h6" sx={{ ...responsiveText.h4, fontWeight: 700, mb: 6 }}>
|
||||
비밀번호 변경
|
||||
</Typography>
|
||||
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
|
||||
<Controller
|
||||
name="currentPassword"
|
||||
control={passwordControl}
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fullWidth
|
||||
type={showCurrentPassword ? 'text' : 'password'}
|
||||
label="현재 비밀번호"
|
||||
placeholder="현재 비밀번호를 입력하세요"
|
||||
error={!!passwordErrors.currentPassword}
|
||||
helperText={passwordErrors.currentPassword?.message}
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
onClick={() => setShowCurrentPassword(!showCurrentPassword)}
|
||||
edge="end"
|
||||
>
|
||||
{showCurrentPassword ? <VisibilityOff /> : <Visibility />}
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
name="newPassword"
|
||||
control={passwordControl}
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fullWidth
|
||||
type={showNewPassword ? 'text' : 'password'}
|
||||
label="새 비밀번호"
|
||||
placeholder="새 비밀번호를 입력하세요"
|
||||
error={!!passwordErrors.newPassword}
|
||||
helperText={passwordErrors.newPassword?.message || '8자 이상, 영문과 숫자를 포함해주세요'}
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
onClick={() => setShowNewPassword(!showNewPassword)}
|
||||
edge="end"
|
||||
>
|
||||
{showNewPassword ? <VisibilityOff /> : <Visibility />}
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
name="confirmPassword"
|
||||
control={passwordControl}
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fullWidth
|
||||
type={showConfirmPassword ? 'text' : 'password'}
|
||||
label="비밀번호 확인"
|
||||
placeholder="비밀번호를 다시 입력하세요"
|
||||
error={!!passwordErrors.confirmPassword}
|
||||
helperText={passwordErrors.confirmPassword?.message}
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
onClick={() => setShowConfirmPassword(!showConfirmPassword)}
|
||||
edge="end"
|
||||
>
|
||||
{showConfirmPassword ? <VisibilityOff /> : <Visibility />}
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Button
|
||||
fullWidth
|
||||
type={showCurrentPassword ? 'text' : 'password'}
|
||||
label="현재 비밀번호"
|
||||
placeholder="현재 비밀번호를 입력하세요"
|
||||
error={!!passwordErrors.currentPassword}
|
||||
helperText={passwordErrors.currentPassword?.message}
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
onClick={() => setShowCurrentPassword(!showCurrentPassword)}
|
||||
edge="end"
|
||||
>
|
||||
{showCurrentPassword ? <VisibilityOff /> : <Visibility />}
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
variant="outlined"
|
||||
size="large"
|
||||
onClick={handlePasswordSubmit(onChangePassword)}
|
||||
sx={{
|
||||
mt: 1,
|
||||
py: 3,
|
||||
borderRadius: 3,
|
||||
fontSize: '1rem',
|
||||
fontWeight: 600,
|
||||
borderWidth: 2,
|
||||
'&:hover': {
|
||||
borderWidth: 2,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
name="newPassword"
|
||||
control={passwordControl}
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fullWidth
|
||||
type={showNewPassword ? 'text' : 'password'}
|
||||
label="새 비밀번호"
|
||||
placeholder="새 비밀번호를 입력하세요"
|
||||
error={!!passwordErrors.newPassword}
|
||||
helperText={passwordErrors.newPassword?.message || '8자 이상, 영문과 숫자를 포함해주세요'}
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
onClick={() => setShowNewPassword(!showNewPassword)}
|
||||
edge="end"
|
||||
>
|
||||
{showNewPassword ? <VisibilityOff /> : <Visibility />}
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
name="confirmPassword"
|
||||
control={passwordControl}
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fullWidth
|
||||
type={showConfirmPassword ? 'text' : 'password'}
|
||||
label="비밀번호 확인"
|
||||
placeholder="비밀번호를 다시 입력하세요"
|
||||
error={!!passwordErrors.confirmPassword}
|
||||
helperText={passwordErrors.confirmPassword?.message}
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
onClick={() => setShowConfirmPassword(!showConfirmPassword)}
|
||||
edge="end"
|
||||
>
|
||||
{showConfirmPassword ? <VisibilityOff /> : <Visibility />}
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
>
|
||||
비밀번호 변경
|
||||
</Button>
|
||||
</Box>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* 액션 버튼 */}
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
|
||||
<Button
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
variant="contained"
|
||||
size="large"
|
||||
onClick={handlePasswordSubmit(onChangePassword)}
|
||||
onClick={handleSave}
|
||||
sx={{
|
||||
mt: 1,
|
||||
py: { xs: 1.5, sm: 1.75 },
|
||||
fontSize: { xs: 15, sm: 16 },
|
||||
fontWeight: 600,
|
||||
borderWidth: 2,
|
||||
py: 3,
|
||||
borderRadius: 3,
|
||||
fontSize: '1rem',
|
||||
fontWeight: 700,
|
||||
background: `linear-gradient(135deg, ${colors.purple} 0%, ${colors.pink} 100%)`,
|
||||
'&:hover': {
|
||||
background: `linear-gradient(135deg, ${colors.purple} 0%, ${colors.pink} 100%)`,
|
||||
opacity: 0.9,
|
||||
},
|
||||
}}
|
||||
>
|
||||
비밀번호 변경
|
||||
저장하기
|
||||
</Button>
|
||||
<Button
|
||||
fullWidth
|
||||
variant="text"
|
||||
size="large"
|
||||
color="error"
|
||||
onClick={() => setLogoutDialogOpen(true)}
|
||||
sx={{
|
||||
py: 3,
|
||||
fontSize: '1rem',
|
||||
fontWeight: 600,
|
||||
}}
|
||||
>
|
||||
로그아웃
|
||||
</Button>
|
||||
</Box>
|
||||
</Paper>
|
||||
|
||||
{/* 액션 버튼 */}
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
|
||||
<Button
|
||||
fullWidth
|
||||
variant="contained"
|
||||
size="large"
|
||||
onClick={handleSave}
|
||||
sx={{
|
||||
py: { xs: 1.5, sm: 1.75 },
|
||||
fontSize: { xs: 15, sm: 16 },
|
||||
...getGradientButtonStyle('primary'),
|
||||
}}
|
||||
>
|
||||
저장하기
|
||||
</Button>
|
||||
<Button
|
||||
fullWidth
|
||||
variant="text"
|
||||
size="large"
|
||||
color="error"
|
||||
onClick={() => setLogoutDialogOpen(true)}
|
||||
sx={{
|
||||
py: { xs: 1.5, sm: 1.75 },
|
||||
fontSize: { xs: 15, sm: 16 },
|
||||
fontWeight: 600,
|
||||
}}
|
||||
>
|
||||
로그아웃
|
||||
</Button>
|
||||
</Box>
|
||||
</Container>
|
||||
</Box>
|
||||
|
||||
{/* 저장 완료 다이얼로그 */}
|
||||
<Dialog open={successDialogOpen} onClose={() => setSuccessDialogOpen(false)}>
|
||||
<Dialog
|
||||
open={successDialogOpen}
|
||||
onClose={() => setSuccessDialogOpen(false)}
|
||||
PaperProps={{
|
||||
sx: {
|
||||
borderRadius: 4,
|
||||
minWidth: 300,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<DialogContent sx={{ textAlign: 'center', py: 6, px: 4 }}>
|
||||
<CheckCircle sx={{ fontSize: 64, color: 'success.main', mb: 2 }} />
|
||||
<Typography variant="h6" sx={{ fontWeight: 700, mb: 1 }}>
|
||||
<Typography variant="h6" sx={{ fontWeight: 700, mb: 1, fontSize: '1.25rem' }}>
|
||||
저장 완료
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
<Typography variant="body2" color="text.secondary" sx={{ fontSize: '1rem' }}>
|
||||
프로필 정보가 업데이트되었습니다.
|
||||
</Typography>
|
||||
</DialogContent>
|
||||
@ -496,8 +536,15 @@ export default function ProfilePage() {
|
||||
}}
|
||||
sx={{
|
||||
minWidth: 120,
|
||||
py: { xs: 1.25, sm: 1.5 },
|
||||
...getGradientButtonStyle('success'),
|
||||
py: 2,
|
||||
borderRadius: 2,
|
||||
fontSize: '1rem',
|
||||
fontWeight: 700,
|
||||
background: `linear-gradient(135deg, ${colors.purple} 0%, ${colors.pink} 100%)`,
|
||||
'&:hover': {
|
||||
background: `linear-gradient(135deg, ${colors.purple} 0%, ${colors.pink} 100%)`,
|
||||
opacity: 0.9,
|
||||
},
|
||||
}}
|
||||
>
|
||||
확인
|
||||
@ -506,29 +553,51 @@ export default function ProfilePage() {
|
||||
</Dialog>
|
||||
|
||||
{/* 로그아웃 확인 다이얼로그 */}
|
||||
<Dialog open={logoutDialogOpen} onClose={() => setLogoutDialogOpen(false)}>
|
||||
<DialogTitle>로그아웃</DialogTitle>
|
||||
<Dialog
|
||||
open={logoutDialogOpen}
|
||||
onClose={() => setLogoutDialogOpen(false)}
|
||||
PaperProps={{
|
||||
sx: {
|
||||
borderRadius: 4,
|
||||
minWidth: 300,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<DialogTitle sx={{ fontSize: '1.25rem', fontWeight: 700 }}>로그아웃</DialogTitle>
|
||||
<DialogContent>
|
||||
<Typography variant="body1" sx={{ textAlign: 'center', py: 2 }}>
|
||||
<Typography variant="body1" sx={{ textAlign: 'center', py: 2, fontSize: '1rem' }}>
|
||||
로그아웃 하시겠습니까?
|
||||
</Typography>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<DialogActions sx={{ justifyContent: 'center', gap: 2, pb: 3 }}>
|
||||
<Button
|
||||
onClick={() => setLogoutDialogOpen(false)}
|
||||
sx={{ fontWeight: 600 }}
|
||||
sx={{
|
||||
fontWeight: 600,
|
||||
fontSize: '1rem',
|
||||
py: 2,
|
||||
px: 4,
|
||||
borderRadius: 2,
|
||||
}}
|
||||
>
|
||||
취소
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={handleLogout}
|
||||
sx={{ ...getGradientButtonStyle('error') }}
|
||||
color="error"
|
||||
sx={{
|
||||
fontWeight: 700,
|
||||
fontSize: '1rem',
|
||||
py: 2,
|
||||
px: 4,
|
||||
borderRadius: 2,
|
||||
}}
|
||||
>
|
||||
확인
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user