diff --git a/src/app/(artist)/artist/home/page.tsx b/src/app/(artist)/artist/home/page.tsx index a4ba27d..d1ceebf 100644 --- a/src/app/(artist)/artist/home/page.tsx +++ b/src/app/(artist)/artist/home/page.tsx @@ -1,21 +1,115 @@ 'use client'; -import { logout } from '@/app/auth'; -import { Box, Button, Typography } from '@mui/material'; +// import { ReservationItem } from '@/app/(model)/model/reservation/components/ReservationItem'; +import { JButton } from '@/components/JButton'; +import { JIcon } from '@/components/JIcon'; +import { JImage } from '@/components/JImage'; +import { MotionWrapper } from '@/components/MotionWrapper'; +import { Row } from '@/components/Row'; +import { SquareImage } from '@/components/SquareImage'; +import { COLORS } from '@/styles/colors'; +import { Stack, Typography } from '@mui/material'; +// import Link from 'next/link'; +import { useRouter } from 'next/navigation'; const Page = () => { + const router = useRouter(); return ( - - ArtistHome - - + + + + + router.push('/notification')} + > + + + + + router.push('/artist/profile')} + > + + + + 안녕하세요, +
+ 치즈가 많이 좋아 님
+ {/* 오늘 예약 N건이 있어요. */} +
+
+ + + 아직 프로필이 완성되지 않았어요! + + + 프로필을 완성하고 모델과의 +
+ 예약을 잡아보세요! +
+ router.push('/artist/profile/setup')} + > + 프로필 완성하러 가기 + +
+ {/* + + + + 전체 예약 보기 + + + + + + + + router.push(`reservation/${0}`)} + type='today' + /> + + + + + 모델과의 예약을 확정해주세요! + + router.push(`/reservation/${0}`)} + type='wait' + /> + */} +
+
); }; export default Page; diff --git a/src/app/(artist)/artist/makeup/[id]/edit/page.tsx b/src/app/(artist)/artist/makeup/[id]/edit/page.tsx index c7dbc3d..668aea8 100644 --- a/src/app/(artist)/artist/makeup/[id]/edit/page.tsx +++ b/src/app/(artist)/artist/makeup/[id]/edit/page.tsx @@ -1,4 +1,186 @@ +'use client'; +import { AppBar } from '@/components/AppBar'; +import { MotionWrapper } from '@/components/MotionWrapper'; +import { Row } from '@/components/Row'; +import { + Button, + OutlinedInput, + Stack, + TextField, + Typography, +} from '@mui/material'; +import { useRef, useState } from 'react'; +import { SpecializationItem } from '../../../profile/setup/components/SpecializationItem'; +import { JButton } from '@/components/JButton'; +import { COLORS } from '@/styles/colors'; +import { JIcon } from '@/components/JIcon'; +import { ImageThumb } from '../../components/ImageThumb'; + +const category = { + daily: '데일리 메이크업', + actor: '배우 메이크업', + interview: '면접 메이크업', + party: '파티/이벤트 메이크업', + wedding: '웨딩 메이크업', + special: '특수 메이크업', + studio: '스튜디오 메이크업', + etc: '기타 (속눈썹, 퍼스널컬러)', +}; + const Page = () => { - return <>; + const fileInputRef = useRef(null); + const [formData, setFormData] = useState({ + category: [] as string[], + makeupName: '', + price: '', + information: '', + }); + const [images, setImages] = useState([]); + + const isButtonDisabled = !( + images.length > 0 && + formData.category.length > 0 && + formData.makeupName.trim() && + formData.price.trim() && + formData.information.trim() + ); + + const toggleCategory = (key: string) => { + setFormData((prev) => { + const isSelected = prev.category.includes(key); + return { + ...prev, + category: isSelected + ? prev.category.filter((item) => item !== key) + : [...prev.category, key], + }; + }); + }; + + const FileChange = (event: React.ChangeEvent) => { + if (event.target.files) { + const newFiles = Array.from(event.target.files); + setImages((prevImages) => [...prevImages, ...newFiles]); + } + }; + + const SelectImageDelete = (index: number) => { + setImages((prevImages) => prevImages.filter((_, i) => i !== index)); + }; + + const handleChange = (e: React.ChangeEvent) => { + const { id, value } = e.target; + setFormData((prev) => ({ ...prev, [id]: value })); + }; + + return ( + + + + + + + 사진 등록 (최대 3장) + + + {images.length !== 3 && ( + fileInputRef.current?.click()} + sx={{ + width: '80px', + height: '80px', + justifyContent: 'center', + alignItems: 'center', + border: `1px solid ${COLORS.gray300}`, + borderRadius: '5px', + }} + > + + + + )} + + + + + 카테고리 + + + {Object.entries(category).map(([key, value]) => ( + toggleCategory(key)} + isActive={formData.category.includes(key)} + /> + ))} + + + 메이크업명 + + + + 가격 + + + + 정보 + + + + + + + + + + ); }; export default Page; diff --git a/src/app/(artist)/artist/makeup/[id]/page.tsx b/src/app/(artist)/artist/makeup/[id]/page.tsx index c7dbc3d..b201e61 100644 --- a/src/app/(artist)/artist/makeup/[id]/page.tsx +++ b/src/app/(artist)/artist/makeup/[id]/page.tsx @@ -1,4 +1,157 @@ +'use client'; +import { LikeButton } from '@/app/(model)/makeup/[id]/components/LikeButton'; +import { ReservationViewInfo } from '@/app/(model)/makeup/[id]/components/ReservationViewInfo'; +import { ReservationViewReview } from '@/app/(model)/makeup/[id]/components/ReservationViewReview'; +import { TabItem, Tabs } from '@/app/(model)/makeup/[id]/components/Tabs'; +import { AppBar } from '@/components/AppBar'; +import Counter from '@/components/Counter'; +import { MotionWrapper } from '@/components/MotionWrapper'; +import { Row } from '@/components/Row'; +import { SquareImage } from '@/components/SquareImage'; +import { COLORS } from '@/styles/colors'; +import { Link, Stack, Typography } from '@mui/material'; +import { useState } from 'react'; + const Page = () => { - return <>; + const [activeTab, setActiveTab] = useState(0); + const [isScaled, setIsScaled] = useState(false); + + const tabs = [ + { + label: '정보', + content: ( + + ), + }, + { + label: ( + + + 리뷰 + + + + ), + content: , + }, + ]; + + return ( + + + + + + + + + + + + + + + + + 김차차 + + + setIsScaled((prev) => !prev)} + isScaled={isScaled} + /> + + + + + + 촬영 메이크업 + + + 프로필사진 촬영에 좋아요 + + + + + + + + + 샵 재직 여부 + + 🙅🏻프리랜서에요 + + + + 카테고리 + + 면접메이크업 + + + + + {tabs.map((tab, index) => ( + setActiveTab(index)}> + {tab.label} + + ))} + + {tabs[activeTab].content} + + + + + + + 수정하기 + + + + + + ); }; export default Page; diff --git a/src/app/(artist)/artist/makeup/components/ImageThumb.tsx b/src/app/(artist)/artist/makeup/components/ImageThumb.tsx new file mode 100644 index 0000000..47efc49 --- /dev/null +++ b/src/app/(artist)/artist/makeup/components/ImageThumb.tsx @@ -0,0 +1,41 @@ +import { JIcon } from '@/components/JIcon'; +import { Row } from '@/components/Row'; +import { SquareImage } from '@/components/SquareImage'; +import { COLORS } from '@/styles/colors'; +import { Stack } from '@mui/material'; + +type ImageThumbProps = { + images: File[]; + onDelete: (index: number) => void; +}; +export const ImageThumb = ({ images, onDelete }: ImageThumbProps) => { + return ( + + {images.map((item, index) => ( + onDelete(index)} + sx={{ cursor: 'pointer' }} + borderRadius={'5px'} + overflow={'hidden'} + > + + + + + + ))} + + ); +}; diff --git a/src/app/(artist)/artist/makeup/components/MakeupItem.tsx b/src/app/(artist)/artist/makeup/components/MakeupItem.tsx new file mode 100644 index 0000000..2d07868 --- /dev/null +++ b/src/app/(artist)/artist/makeup/components/MakeupItem.tsx @@ -0,0 +1,53 @@ +import { JButton } from '@/components/JButton'; +import { JIcon } from '@/components/JIcon'; +import { Row } from '@/components/Row'; +import { COLORS } from '@/styles/colors'; +import { Stack, Typography } from '@mui/material'; + +export const MakeupItem = () => { + return ( + + + + + + + + 웨딩 메이크업 + + 감성웨딩 메이크업 + + + + {4.8} + + + 아티스트 김제니 / 150,000 + + + + ); +}; diff --git a/src/app/(artist)/artist/makeup/page.tsx b/src/app/(artist)/artist/makeup/page.tsx index c7dbc3d..2e6ae57 100644 --- a/src/app/(artist)/artist/makeup/page.tsx +++ b/src/app/(artist)/artist/makeup/page.tsx @@ -1,4 +1,53 @@ +'use client'; +import { AppBar } from '@/components/AppBar'; +import { JButton } from '@/components/JButton'; +import { MotionWrapper } from '@/components/MotionWrapper'; +import { COLORS } from '@/styles/colors'; +import { Stack, Typography } from '@mui/material'; +import { MakeupItem } from './components/MakeupItem'; +import { useRouter } from 'next/navigation'; + const Page = () => { - return <>; + const router = useRouter(); + return ( + + + + {/* + + 등록된 포트폴리오가 없어요! + + + 포트폴리오를 등록하고 +
+ 모델과의 예약을 잡아보세요! +
+
*/} + + 총 4개 + + + router.push('makeup/write')} + sx={{ + position: 'fixed', + right: '23px', + bottom: '52px', + width: '75px', + height: '75px', + borderRadius: '50%', + bgcolor: `${COLORS.primary}`, + }} + > + a + +
+
+ ); }; export default Page; diff --git a/src/app/(artist)/artist/makeup/write/page.tsx b/src/app/(artist)/artist/makeup/write/page.tsx new file mode 100644 index 0000000..ee17b64 --- /dev/null +++ b/src/app/(artist)/artist/makeup/write/page.tsx @@ -0,0 +1,186 @@ +'use client'; +import { MotionWrapper } from '@/components/MotionWrapper'; +import { Row } from '@/components/Row'; +import { + Button, + OutlinedInput, + Stack, + TextField, + Typography, +} from '@mui/material'; +import { SpecializationItem } from '../../profile/setup/components/SpecializationItem'; +import { useRef, useState } from 'react'; +import { COLORS } from '@/styles/colors'; +import { AppBar } from '@/components/AppBar'; +import { JIcon } from '@/components/JIcon'; +import { JButton } from '@/components/JButton'; +import { ImageThumb } from '../components/ImageThumb'; + +const category = { + daily: '데일리 메이크업', + actor: '배우 메이크업', + interview: '면접 메이크업', + party: '파티/이벤트 메이크업', + wedding: '웨딩 메이크업', + special: '특수 메이크업', + studio: '스튜디오 메이크업', + etc: '기타 (속눈썹, 퍼스널컬러)', +}; + +const Page = () => { + const fileInputRef = useRef(null); + const [formData, setFormData] = useState({ + category: [] as string[], + makeupName: '', + price: '', + information: '', + }); + const [images, setImages] = useState([]); + + const isButtonDisabled = !( + images.length > 0 && + formData.category.length > 0 && + formData.makeupName.trim() && + formData.price.trim() && + formData.information.trim() + ); + + const toggleCategory = (key: string) => { + setFormData((prev) => { + const isSelected = prev.category.includes(key); + return { + ...prev, + category: isSelected + ? prev.category.filter((item) => item !== key) + : [...prev.category, key], + }; + }); + }; + + const FileChange = (event: React.ChangeEvent) => { + if (event.target.files) { + const newFiles = Array.from(event.target.files); + setImages((prevImages) => [...prevImages, ...newFiles]); + } + }; + + const SelectImageDelete = (index: number) => { + setImages((prevImages) => prevImages.filter((_, i) => i !== index)); + }; + + const handleChange = (e: React.ChangeEvent) => { + const { id, value } = e.target; + setFormData((prev) => ({ ...prev, [id]: value })); + }; + + return ( + + + + + + + 사진 등록 (최대 3장) + + + {images.length !== 3 && ( + fileInputRef.current?.click()} + sx={{ + width: '80px', + height: '80px', + justifyContent: 'center', + alignItems: 'center', + border: `1px solid ${COLORS.gray300}`, + borderRadius: '5px', + }} + > + + + + )} + + + + + 카테고리 + + + {Object.entries(category).map(([key, value]) => ( + toggleCategory(key)} + isActive={formData.category.includes(key)} + /> + ))} + + + 메이크업명 + + + + 가격 + + + + 정보 + + + + + + + + + + ); +}; +export default Page; diff --git a/src/app/(artist)/artist/profile/setup/components/ChocieSpecialization.tsx b/src/app/(artist)/artist/profile/setup/components/ChocieSpecialization.tsx new file mode 100644 index 0000000..1d8d3f4 --- /dev/null +++ b/src/app/(artist)/artist/profile/setup/components/ChocieSpecialization.tsx @@ -0,0 +1,140 @@ +import { Row } from '@/components/Row'; +import { + Button, + InputAdornment, + OutlinedInput, + Stack, + Typography, +} from '@mui/material'; +import { SpecializationItem } from './SpecializationItem'; +import { MakeupLocationItem } from './MakeupLocationItem'; +import { COLORS } from '@/styles/colors'; +import { useState } from 'react'; + +type Props = { + onNext: () => void; +}; + +const specialization = { + daily: '데일리 메이크업', + actor: '배우 메이크업', + interview: '면접 메이크업', + party: '파티/이벤트 메이크업', + wedding: '웨딩 메이크업', + special: '특수 메이크업', + studio: '스튜디오 메이크업', + etc: '기타 (속눈썹, 퍼스널컬러)', +}; + +const makeupLocation = { + shop: '제가 다니는 샵에서 진행해요', + visit: '직접 방문해서 진행해요', + etc: '둘 다 상관없어요', +}; + +const ChocieSpecialization = ({ onNext }: Props) => { + const [formData, setFormData] = useState({ + Specialization: [] as string[], + location: [] as string[], + address: '', + }); + + const toggleSpecialization = (key: string) => { + setFormData((prev) => { + const isSelected = prev.Specialization.includes(key); + return { + ...prev, + Specialization: isSelected + ? prev.Specialization.filter((item) => item !== key) + : [...prev.Specialization, key], + }; + }); + }; + + const toggleLocation = (key: string) => { + setFormData((prev) => { + const isSelected = prev.location.includes(key); + return { + ...prev, + location: isSelected + ? prev.location.filter((item) => item !== key) + : [...prev.location, key], + }; + }); + }; + const isButtonDisabled = !( + formData.Specialization && + formData.location && + formData.address + ); + + return ( + + + + 전문분야를 선택해주세요. (다중 선택 가능) + + + {Object.entries(specialization).map(([key, value]) => ( + toggleSpecialization(key)} + isActive={formData.Specialization.includes(key)} + /> + ))} + + + 메이크업장소 + + + {Object.entries(makeupLocation).map(([key, value]) => ( + toggleLocation(key)} + isActive={formData.location.includes(key)} + /> + ))} + + + 샵의 위치를 입력해주세요. + + ) => + setFormData((prev) => ({ + ...prev, + address: e.target.value, + })) + } + value={formData.address} + sx={{ + borderRadius: 2, + height: '41px', + fontSize: '14px', + }} + endAdornment={ + + } + aria-describedby='outlined-weight-helper-text' + inputProps={{ + 'aria-label': 'weight', + }} + /> + + + + ); +}; +export default ChocieSpecialization; diff --git a/src/app/(artist)/artist/profile/setup/components/ChoiceLocation.tsx b/src/app/(artist)/artist/profile/setup/components/ChoiceLocation.tsx new file mode 100644 index 0000000..5af56ab --- /dev/null +++ b/src/app/(artist)/artist/profile/setup/components/ChoiceLocation.tsx @@ -0,0 +1,56 @@ +import { Row } from '@/components/Row'; +import { Button, Stack, Typography } from '@mui/material'; +import { LocationButton } from './LocationButton'; +import { useState } from 'react'; + +type Props = { + onNext: () => void; +}; + +const location = { + all: '전체', + gangNam: '강남구', + gangDong: '강동구', + gangBuk: '강북구', + gangSeo: '강서구', + mapo: '마포구', + gwangJin: '광진구', + guRO: '구로구', + geumCheon: '금천구', + noWon: '노원구', + doBong: '도봉구', + dongDaeMoon: '동대문구', + seoDaeMoon: '서대문구', + seoCho: '서초구', + seongDong: '성동구', +}; + +const ChoiceLocation = ({ onNext }: Props) => { + const [selectLocation, setSelectLocation] = useState(null); + + const isButtonDisabled = !selectLocation?.trim(); + return ( + + + + 활동 가능 지역을 선택해주세요. (서울 지역만 선택가능) + + + {Object.entries(location).map(([key, value]) => ( + setSelectLocation(key)} + active={selectLocation === key} + /> + ))} + + + + + ); +}; + +export default ChoiceLocation; diff --git a/src/app/(artist)/artist/profile/setup/components/LocationButton.tsx b/src/app/(artist)/artist/profile/setup/components/LocationButton.tsx new file mode 100644 index 0000000..0babdf2 --- /dev/null +++ b/src/app/(artist)/artist/profile/setup/components/LocationButton.tsx @@ -0,0 +1,32 @@ +import { JButton } from '@/components/JButton'; +import { COLORS } from '@/styles/colors'; +import { Typography } from '@mui/material'; +type LocationButtonProps = { + text: string; + onClick?: () => void; + active: boolean; +}; +export const LocationButton = ({ + text, + onClick, + active, +}: LocationButtonProps) => { + return ( + + + {text} + + + ); +}; diff --git a/src/app/(artist)/artist/profile/setup/components/MakeupLocationItem.tsx b/src/app/(artist)/artist/profile/setup/components/MakeupLocationItem.tsx new file mode 100644 index 0000000..132ddde --- /dev/null +++ b/src/app/(artist)/artist/profile/setup/components/MakeupLocationItem.tsx @@ -0,0 +1,28 @@ +import { JButton } from '@/components/JButton'; +import { COLORS } from '@/styles/colors'; +import { Typography } from '@mui/material'; + +type MakeupLocationItemProps = { + text: string; + onClick: () => void; + isActive: boolean; +}; +export const MakeupLocationItem = ({ + text, + onClick, + isActive, +}: MakeupLocationItemProps) => { + return ( + + + {text} + + + ); +}; diff --git a/src/app/(artist)/artist/profile/setup/components/SelectBox.tsx b/src/app/(artist)/artist/profile/setup/components/SelectBox.tsx new file mode 100644 index 0000000..da4e206 --- /dev/null +++ b/src/app/(artist)/artist/profile/setup/components/SelectBox.tsx @@ -0,0 +1,34 @@ +import { COLORS } from '@/styles/colors'; +import { Stack, Typography } from '@mui/material'; + +type SelectBoxProps = { isOpen: boolean; onClick: () => void }; +export const SelectBox = ({ isOpen, onClick }: SelectBoxProps) => { + return ( + + + 선택해주세요. + + {isOpen === true && ( + + 1년 + + )} + + ); +}; diff --git a/src/app/(artist)/artist/profile/setup/components/SpecializationItem.tsx b/src/app/(artist)/artist/profile/setup/components/SpecializationItem.tsx new file mode 100644 index 0000000..97bd8bc --- /dev/null +++ b/src/app/(artist)/artist/profile/setup/components/SpecializationItem.tsx @@ -0,0 +1,35 @@ +import { JButton } from '@/components/JButton'; +import { COLORS } from '@/styles/colors'; +import { Stack, Typography } from '@mui/material'; + +type SpecializationItemProps = { + text: string; + onClick: () => void; + isActive: boolean; +}; +export const SpecializationItem = ({ + text, + onClick, + isActive, +}: SpecializationItemProps) => { + return ( + + + + {text} + + + + ); +}; diff --git a/src/app/(artist)/artist/profile/setup/components/WriteProfile.tsx b/src/app/(artist)/artist/profile/setup/components/WriteProfile.tsx new file mode 100644 index 0000000..fe99b2d --- /dev/null +++ b/src/app/(artist)/artist/profile/setup/components/WriteProfile.tsx @@ -0,0 +1,243 @@ +import { ShadowButton } from '@/app/(model)/profile/edit/components/ShadowButton'; +import { JIcon } from '@/components/JIcon'; +import { Row } from '@/components/Row'; +import { COLORS } from '@/styles/colors'; +import { + Button, + InputAdornment, + OutlinedInput, + Stack, + TextField, + Typography, +} from '@mui/material'; +import { useState } from 'react'; +import { SelectBox } from './SelectBox'; + +type Props = { + onNext: () => void; +}; + +const WriteProfile = ({ onNext }: Props) => { + const [formData, setFormData] = useState({ + nickName: '', + gender: '', + phone: '', + email: '', + instagram: '', + introduce: '', + }); + const [selectOpen, setSelectOpen] = useState(false); + + const isButtonDisabled = !( + formData.nickName.trim() && + formData.gender.trim() && + formData.phone.trim() && + formData.email.trim() && + formData.introduce.trim() + ); + + const handleChange = (e: React.ChangeEvent) => { + const { id, value } = e.target; + setFormData((prev) => ({ ...prev, [id]: value })); + }; + + const handleGenderSelect = (selectedGender: string) => { + setFormData((prev) => ({ ...prev, gender: selectedGender })); + }; + return ( + + + + + + + + + + + + 닉네임 + + + } + aria-describedby='outlined-weight-helper-text' + inputProps={{ + 'aria-label': 'weight', + }} + /> + + 닉네임은 최대 15자 작성 가능합니다. + + + + + 성별 + + + handleGenderSelect('여성')} + > + 여성 + + handleGenderSelect('남성')} + > + 남성 + + + + + + 전화번호 입력 + + + } + aria-describedby='outlined-weight-helper-text' + inputProps={{ + 'aria-label': 'weight', + }} + /> + + + + 이메일 입력 + + + } + aria-describedby='outlined-weight-helper-text' + inputProps={{ + 'aria-label': 'weight', + }} + /> + + + + 인스타그램 아이디 입력(선택) + + + } + aria-describedby='outlined-weight-helper-text' + inputProps={{ + 'aria-label': 'weight', + }} + /> + + + + 자기소개 (최대 250자) + + + + + + 총 경력 기간 + + setSelectOpen(!selectOpen)} + /> + + + + + ); +}; + +export default WriteProfile; diff --git a/src/app/(artist)/artist/profile/setup/page.tsx b/src/app/(artist)/artist/profile/setup/page.tsx new file mode 100644 index 0000000..f0dab5f --- /dev/null +++ b/src/app/(artist)/artist/profile/setup/page.tsx @@ -0,0 +1,58 @@ +'use client'; +import { AppBar } from '@/components/AppBar'; +import { useState } from 'react'; +import SwipeableViews from 'react-swipeable-views'; +import WriteProfile from './components/WriteProfile'; +import ChoiceLocation from './components/ChoiceLocation'; +import ChocieSpecialization from './components/ChocieSpecialization'; +import { Stack } from '@mui/material'; +import { TabIndicator } from '@/app/(guest)/join/components/TabIndicator'; +import { useRouter } from 'next/navigation'; + +const Page = () => { + const router = useRouter(); + const [step, setStep] = useState(1); + const onSubmit = () => {}; + const onNext = () => { + if (step !== 3) { + setStep(step + 1); + } else { + onSubmit(); + } + }; + const onPrev = () => { + if (step !== 1) { + setStep(step - 1); + } else { + router.replace('/artist/home'); + } + }; + return ( + + + + + + onNext()} /> + onNext()} /> + onNext()} /> + + + + ); +}; +export default Page; diff --git a/src/app/(artist)/artist/reservation/[id]/page.tsx b/src/app/(artist)/artist/reservation/[id]/page.tsx index c7dbc3d..3fce8a8 100644 --- a/src/app/(artist)/artist/reservation/[id]/page.tsx +++ b/src/app/(artist)/artist/reservation/[id]/page.tsx @@ -1,4 +1,208 @@ +'use client'; +import { AppBar } from '@/components/AppBar'; +import { JButton } from '@/components/JButton'; +import { Modal } from '@/components/Modal/Modal'; +import { ModalContent } from '@/components/Modal/ModalContent'; +import { MotionWrapper } from '@/components/MotionWrapper'; +import { Row } from '@/components/Row'; +import { SquareImage } from '@/components/SquareImage'; +import { COLORS } from '@/styles/colors'; +import { Box, Stack, Typography } from '@mui/material'; +import Link from 'next/link'; +import { useState } from 'react'; + const Page = () => { - return <>; + const [isOpen, setIsOpen] = useState(false); + return ( + + + + + + + + + + + 아티스트 차차 + + + + + + 전화번호 + + + 010-1234-5678 + + + + + 이메일 + + + meme@naver.com + + + + + 성별 + + + 여성 + + + + + 이메일 + + + meme@naver.com + + + + + 퍼스널 컬러 + + + 🍃 봄 웜톤 + + + + + + 메이크업 정보 + + + + + + 메이크업명 + + + 메이크업명 + + + + + + + 메이크업 분야 + + + 메이크업 분야 + + + + + + + 장소 + + + 강남 메이크업샵 + + + + + + + 날짜 + + + 4월 13일 (토) + + + + + + + 시간 + + + 오후 0시 0분 + + + + + + + 가격 + + + 100,000원 + + + + + + + + setIsOpen(!isOpen)} + sx={{ + background: '#000', + borderRadius: '10px', + lineHeight: '49px', + color: COLORS.white, + fontSize: '14px', + }} + > + 포트폴리오 보러가기 + + + 예약 취소하기 + + + + setIsOpen(false)}> + + 예약을 취소하시겠습니까? + + + 클릭시 예약이 취소되며, 모델에게 취소 알림이 전송됩니다. + + + + + ); }; export default Page; diff --git a/src/app/(artist)/artist/reservation/page.tsx b/src/app/(artist)/artist/reservation/page.tsx index c7dbc3d..a994d64 100644 --- a/src/app/(artist)/artist/reservation/page.tsx +++ b/src/app/(artist)/artist/reservation/page.tsx @@ -1,4 +1,129 @@ +'use client'; + +import { ReservationItem } from '@/app/(model)/model/reservation/components/ReservationItem'; +import { AppBar } from '@/components/AppBar'; +import { JIcon } from '@/components/JIcon'; +import { MotionWrapper } from '@/components/MotionWrapper'; +import { Row } from '@/components/Row'; +import { COLORS } from '@/styles/colors'; +import { Box, Stack, Typography } from '@mui/material'; +import { useRouter } from 'next/navigation'; + const Page = () => { - return <>; + const router = useRouter(); + return ( + + + + + + + + + + + 예정 + + + + + + + + 완료 + + + + + + + 확정된 예약 + + + 총 2건 + + + + router.push(`reservation/${0}`)} + /> + + + {/* + + + 예약 대기중 + + + 총 2건 + + + */} + + {/* + + 등록된 예약이 없어요! + + + 포트폴리오를 수정하고
모델과의 예약을 잡아보세요. +
+
*/} +
+
+ ); }; export default Page; diff --git a/src/app/(model)/model/reservation/components/ReservationItem.tsx b/src/app/(model)/model/reservation/components/ReservationItem.tsx index ad459cc..37e3852 100644 --- a/src/app/(model)/model/reservation/components/ReservationItem.tsx +++ b/src/app/(model)/model/reservation/components/ReservationItem.tsx @@ -13,7 +13,7 @@ type ReservationItemProps = { location: string; artistName: string; price: string; - type?: 'wait'; + type?: 'wait' | 'today' | 'confirm'; onClick: () => void; }; export const ReservationItem = ({ @@ -28,18 +28,27 @@ export const ReservationItem = ({ }: ReservationItemProps) => { return ( - - {date} - + {type !== 'today' && ( + + {date} + + )} {makeup} @@ -66,28 +75,35 @@ export const ReservationItem = ({ - {type ? '예약 대기' : '예약'} + {type === 'today' ? '예약' : '예약 대기 중'} - + {artistName} - + - + {location} - + diff --git a/src/app/(model)/review/components/ImageThumb.tsx b/src/app/(model)/review/components/ImageThumb.tsx index 8d9bf54..40a1da3 100644 --- a/src/app/(model)/review/components/ImageThumb.tsx +++ b/src/app/(model)/review/components/ImageThumb.tsx @@ -9,7 +9,6 @@ type ImageThumbProps = { onDelete: (index: number) => void; }; export const ImageThumb = ({ images, onDelete }: ImageThumbProps) => { - console.log(images); return ( {images.map((item, index) => ( @@ -31,7 +30,7 @@ export const ImageThumb = ({ images, onDelete }: ImageThumbProps) => { right={0} bgcolor={' #00000033'} > - + ))} diff --git a/src/app/(model)/review/write/page.tsx b/src/app/(model)/review/write/page.tsx index fc67a88..3233c6a 100644 --- a/src/app/(model)/review/write/page.tsx +++ b/src/app/(model)/review/write/page.tsx @@ -29,20 +29,20 @@ const Page = () => { return ( - + 아티스트명 @@ -51,14 +51,14 @@ const Page = () => { 메이크업명 @@ -90,19 +90,19 @@ const Page = () => { 메이크업 후기를 남겨주세요 - setIsOpen(false)}> + setIsOpen(false)}> 리뷰를 등록하시겠습니까? diff --git a/src/assets/calendar.svg b/src/assets/calendar.svg new file mode 100644 index 0000000..73122da --- /dev/null +++ b/src/assets/calendar.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/gallery.svg b/src/assets/gallery.svg new file mode 100644 index 0000000..a4aa3a7 --- /dev/null +++ b/src/assets/gallery.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/components/BottomNav.tsx b/src/components/BottomNav.tsx index 3bb71e5..f34ca3c 100644 --- a/src/components/BottomNav.tsx +++ b/src/components/BottomNav.tsx @@ -1,12 +1,27 @@ +'use client'; import { Row } from './Row'; import { JLink } from './JLink'; +import { usePathname } from 'next/navigation'; export const BottomNav = () => { + const pathname = usePathname(); + + if (pathname.startsWith('/artist')) { + return ( + + + + + + + ); + } + return ( - - - + + + ); }; diff --git a/src/components/JButton.tsx b/src/components/JButton.tsx index 7366136..7f18dad 100644 --- a/src/components/JButton.tsx +++ b/src/components/JButton.tsx @@ -10,7 +10,7 @@ type Props = { export const JButton = ({ children, rippleColor, sx, ...props }: Props) => { return ( { '&& .MuiTouchRipple-child': { backgroundColor: rippleColor ?? COLORS.primary, }, + fontFamily: 'pretendard', }, ...(Array.isArray(sx) ? sx : [sx]), ]} diff --git a/src/components/JIcon.tsx b/src/components/JIcon.tsx index ac85f8b..e7e52e9 100644 --- a/src/components/JIcon.tsx +++ b/src/components/JIcon.tsx @@ -43,6 +43,8 @@ import camera from '../assets/camera.svg'; import star2 from '../assets/star-primary2.svg'; import starGray2 from '../assets/star-gray2.svg'; import closeWhite from '../assets/close-white.svg'; +import calendar from '../assets/calendar.svg'; +import gallery from '../assets/gallery.svg'; const IconMap = { reservation: { @@ -266,6 +268,16 @@ const IconMap = { width: 12, height: 12, }, + calendar: { + src: calendar, + width: 24, + height: 24, + }, + gallery: { + src: gallery, + width: 27, + height: 20, + }, }; export type Icon = keyof typeof IconMap;