diff --git a/apps/duri/src/App.tsx b/apps/duri/src/App.tsx index a63060c5..05cf56e8 100644 --- a/apps/duri/src/App.tsx +++ b/apps/duri/src/App.tsx @@ -1,6 +1,7 @@ import { BrowserRouter, Route, Routes } from 'react-router-dom'; import AuthPage from '@duri/pages/Auth'; +import Home from '@duri/pages/Home'; import MyPetPage from '@duri/pages/My/MyPet'; import Onboarding from '@duri/pages/Onboarding'; import { globalStyle } from '@duri-fe/ui'; @@ -11,7 +12,6 @@ import PetDiaryDetail from '@pages/Diary/DiaryDetail'; import DooriAI from '@pages/DooriAI'; import DooriAIResult from '@pages/DooriAI/AIResult'; import AIStyling from '@pages/DooriAI/AIStyling'; -import Home from '@pages/Home'; import LoginPage from '@pages/Login'; import MyPage from '@pages/My'; import MyHistoryPage from '@pages/My/MyHistory'; diff --git a/apps/duri/src/components/my/review/ReviewUserInfo.tsx b/apps/duri/src/components/my/review/ReviewUserInfo.tsx index 7e8a19c3..839fc3a5 100644 --- a/apps/duri/src/components/my/review/ReviewUserInfo.tsx +++ b/apps/duri/src/components/my/review/ReviewUserInfo.tsx @@ -80,18 +80,12 @@ export const ReviewUserInfo = ({ {createdAt} - + - + {isOpen && ( - + 수정하기 @@ -101,14 +95,10 @@ export const ReviewUserInfo = ({ )} {isOpenModal && ( - + - + 후기를 삭제하시겠습니까? + 후기 삭제 후 @@ -116,12 +106,13 @@ export const ReviewUserInfo = ({ 복구할 수 없습니다. - + + 내 포트폴리오 보기 - + ); }; + +const MoveToPortfolio = styled.a` + background-color: ${theme.palette.White}; + ${theme.typo.Caption3} + color: ${theme.palette.Gray300}; + padding: 10px; + text-align: center; + border-radius: 99px; + cursor: pointer; + text-decoration: none; +`; diff --git a/apps/salon/src/components/onboarding/InputSalon.tsx b/apps/salon/src/components/onboarding/InputSalon.tsx index 24434be9..dad2b4d8 100644 --- a/apps/salon/src/components/onboarding/InputSalon.tsx +++ b/apps/salon/src/components/onboarding/InputSalon.tsx @@ -225,6 +225,7 @@ const InputSalon = ({ placeholder="미용사 면허번호 입력" isEssential width={175} + maxLength={10} isNoBorder shadow="0px 0px 4px 0px rgba(0, 0, 0, 0.10)" helperText={ @@ -260,7 +261,7 @@ const InputSalon = ({ diff --git a/apps/salon/src/components/onboarding/InputSalonOwner.tsx b/apps/salon/src/components/onboarding/InputSalonOwner.tsx index 132fad8a..7258c9db 100644 --- a/apps/salon/src/components/onboarding/InputSalonOwner.tsx +++ b/apps/salon/src/components/onboarding/InputSalonOwner.tsx @@ -362,8 +362,8 @@ const InputSalonOwner = ({ diff --git a/apps/salon/src/pages/Home/index.tsx b/apps/salon/src/pages/Home/index.tsx index 0bb26200..7ebb4e40 100644 --- a/apps/salon/src/pages/Home/index.tsx +++ b/apps/salon/src/pages/Home/index.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { BottomSheet } from 'react-spring-bottom-sheet'; import { useNavigate } from 'react-router-dom'; @@ -22,6 +22,7 @@ import { useBottomSheet, useGetClosetGrooming, useGetDailySchedule, + useGetGroomersList, useGetHomeQuotationRequest, useGetHomeShopInfo, usePutGroomingComplete, @@ -29,6 +30,7 @@ import { } from '@duri-fe/utils'; import styled from '@emotion/styled'; import { RadioButton } from '@salon/components/home/RadioButton'; +import useGroomerStore from '@salon/stores/groomerStore'; import ClosetGrooming from '@components/home/ClosetGrooming'; import DailyScheduleItem from '@components/home/DailyScheduleItem'; @@ -49,6 +51,10 @@ const Home = () => { const [completeToggle, setCompleteToggle] = useState(null); + //홈 진입 시 groomerId 전역변수로 저장 + const { data: groomersListInfo } = useGetGroomersList({}); + const { setGroomerId } = useGroomerStore(); + const { data: shopInfoData } = useGetHomeShopInfo({}); const { data: closetGroomingData, isPending: closetGroomingPending } = useGetClosetGrooming(); @@ -72,6 +78,11 @@ const Home = () => { } }; + //로그인 후 미용사 id를 전역변수로 저장 for 포트폴리오 + useEffect(() => { + if (groomersListInfo) setGroomerId(groomersListInfo[0].id); + }, [groomersListInfo]); + return ( { - // const { data: petData, isError: getPetInfoError } = useGetPetInfo(); - const navigate = useNavigate(); const handleNavigate = (path: string) => navigate(path); + + const groomerId = useGroomerStore((state) => state.groomerId); + + const [shopProfile, setShopProfile] = useState(); + const [groomerProfile, setGroomerProfile] = useState(); + + const { data } = UseGetGroomerInfo({ + groomerId: groomerId, + }); + + useEffect(() => { + if (data) { + setGroomerProfile(data.groomerProfileDetail); + setShopProfile(data.shopProfileDetail); + } + }, [data]); + const logout = () => { - localStorage.removeItem('authorization_user'); + localStorage.removeItem('authorization_shop'); navigate('/login'); }; + useEffect(() => { window.scrollTo(0, 0); }, []); @@ -38,54 +60,60 @@ const MyPage = () => { margin="0 0 100px 0" justify="flex-start" > - - - - - + - - handleNavigate('/my/income')} - > - - 매출관리 - - handleNavigate('/my/review')} - > - - 후기관리 - + + + + + + handleNavigate('/my/income')} + > + + 매출관리 + + handleNavigate('/my/review')} + > + + 후기관리 + + + - - + + ) : ( + 등록된 정보가 없습니다. + )} 로그아웃 - + ); }; diff --git a/apps/salon/src/pages/Onboarding/index.tsx b/apps/salon/src/pages/Onboarding/index.tsx index 416328e6..079c9940 100644 --- a/apps/salon/src/pages/Onboarding/index.tsx +++ b/apps/salon/src/pages/Onboarding/index.tsx @@ -58,7 +58,7 @@ const OnboardingPage = () => { }; formData.append( - 'data', + 'shopOnboardingRequest', new Blob([JSON.stringify(onboardingFormData)], { type: 'application/json', }), diff --git a/apps/salon/src/pages/Portfolio/PortfolioDetail.tsx b/apps/salon/src/pages/Portfolio/PortfolioDetail.tsx new file mode 100644 index 00000000..bb92399f --- /dev/null +++ b/apps/salon/src/pages/Portfolio/PortfolioDetail.tsx @@ -0,0 +1,17 @@ +import { useParams } from 'react-router-dom'; + +import { GroomerPortfolioDetail, MobileLayout, SalonNavbar } from '@duri-fe/ui'; + +const PortfolioDetailPage = () => { + const { portfolioId } = useParams<{ portfolioId: string }>(); + const feedbackId = portfolioId ? Number(portfolioId) : 0; + + return ( + + + + + ); +}; + +export default PortfolioDetailPage; diff --git a/apps/salon/src/pages/Portfolio/index.tsx b/apps/salon/src/pages/Portfolio/index.tsx new file mode 100644 index 00000000..8e59264c --- /dev/null +++ b/apps/salon/src/pages/Portfolio/index.tsx @@ -0,0 +1,14 @@ +import { GroomerPortfolio, MobileLayout, SalonNavbar } from "@duri-fe/ui" +import useGroomerStore from "@salon/stores/groomerStore"; + +const PortfolioPage = () => { + const groomerId = useGroomerStore((state)=>state.groomerId); + + return( + + + + + ) +} +export default PortfolioPage; \ No newline at end of file diff --git a/apps/salon/src/stores/groomerStore.ts b/apps/salon/src/stores/groomerStore.ts new file mode 100644 index 00000000..4aa26b87 --- /dev/null +++ b/apps/salon/src/stores/groomerStore.ts @@ -0,0 +1,23 @@ +import { create } from 'zustand'; +import { createJSONStorage, persist } from 'zustand/middleware'; + +interface GroomerStoreType { + groomerId: number; + setGroomerId: (id: number) => void; +} + +// Zustand 상태 생성 +const useGroomerStore = create( + persist( + (set) => ({ + groomerId: 0, + setGroomerId: (groomerId: number) => set({ groomerId }), + }), + { + name: 'groomer-id', + storage: createJSONStorage(() => sessionStorage), // sessionStorage 사용 + }, + ), +); + +export default useGroomerStore; diff --git a/apps/salon/src/stores/index.ts b/apps/salon/src/stores/index.ts new file mode 100644 index 00000000..4c491a60 --- /dev/null +++ b/apps/salon/src/stores/index.ts @@ -0,0 +1 @@ +export * from './groomerStore' \ No newline at end of file diff --git a/apps/salon/vite.config.ts b/apps/salon/vite.config.ts index e62fce30..fda672ba 100644 --- a/apps/salon/vite.config.ts +++ b/apps/salon/vite.config.ts @@ -14,6 +14,7 @@ export default defineConfig({ { find: '@utils', replacement: '/src/utils' }, { find: '@types', replacement: '/src/types' }, { find: '@hooks', replacement: '/src/hooks' }, + { find: '@stores', replacement: '/src/stores' }, ], }, server: { diff --git a/packages/ui/src/components/Portfolio/DesignerInfo.tsx b/packages/ui/src/components/Portfolio/DesignerInfo.tsx index 0ca6807e..973ac92c 100644 --- a/packages/ui/src/components/Portfolio/DesignerInfo.tsx +++ b/packages/ui/src/components/Portfolio/DesignerInfo.tsx @@ -1,6 +1,7 @@ +import React, { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; -import { Approve, Flex, Text, theme } from '@duri-fe/ui'; +import { Approve, Flex, ProfileImage, Text, theme } from '@duri-fe/ui'; import styled from '@emotion/styled'; interface DesignerInfoProps { @@ -28,12 +29,22 @@ export const DesignerInfo = ({ }: DesignerInfoProps) => { const navigate = useNavigate(); + const [careerYear, setCareerYear] = useState(0); + const [careerMonth, setCareerMonth] = useState(0); + const moveToPortfolio = () => { if (version === 'vertical') { navigate(`/portfolio/${designerId}`); } }; + useEffect(() => { + if (experience !== 0) { + setCareerYear(Math.floor(experience / 12)); + setCareerMonth(experience % 12); + } + }, [experience]); + return ( - + {imageUrl === undefined ? ( + + ) : ( + + )} - {name} + {name ?? '정보없음'} {`경력 ${experience}년, ${age}세, ${gender}`} + >{`경력 ${careerYear ?? '-'}년 ${careerMonth ?? '-'}개월, ${age ?? '-'}세, ${gender}`} - - {roles.map((item, idx) => ( - - - {item} - - - - ))} - + {roles?.length > 0 && ( + + {roles.map((item, idx) => ( + + + {item} + + + + ))} + + )} ); diff --git a/packages/ui/src/components/Portfolio/GroomerPortfolio.tsx b/packages/ui/src/components/Portfolio/GroomerPortfolio.tsx index 136e41ad..2c88f4fd 100644 --- a/packages/ui/src/components/Portfolio/GroomerPortfolio.tsx +++ b/packages/ui/src/components/Portfolio/GroomerPortfolio.tsx @@ -1,8 +1,13 @@ -import { useState } from 'react'; +import { useEffect, useState } from 'react'; +import React from 'react'; -import { FilledHeart, Heart } from '@duri-fe/ui'; +import { FilledHeart, Heart, SalonTag } from '@duri-fe/ui'; import { theme } from '@duri-fe/ui'; import { UseGetGroomerInfo } from '@duri-fe/utils'; +import { + GroomerInfoType, + ShopInfoType, +} from '@duri-fe/utils/src/apis/types/my'; import styled from '@emotion/styled'; import { Flex, HeightFitFlex, WidthFitFlex } from '../FlexBox'; @@ -13,24 +18,28 @@ import { PortfolioPhotos } from './PortfolioPhotos'; export const GroomerPortfolio = ({ groomerId }: { groomerId: number }) => { const [isMarked, setIsMarked] = useState(false); + const [shopProfile, setShopProfile] = useState(); + const [groomerProfile, setGroomerProfile] = useState(); const { data } = UseGetGroomerInfo({ groomerId: groomerId, }); + useEffect(() => { + if (data) { + setGroomerProfile(data.groomerProfileDetail); + setShopProfile(data.shopProfileDetail); + } + }, [data]); + return ( <> - + - 댕댕샵 + {shopProfile?.name ?? '정보 없음'} { - 경기도 성남시 불정로 119 + {shopProfile?.address ?? '정보 없음'} + {shopProfile?.tags && ( + + {shopProfile.tags[0] && ( + + )} + {shopProfile.tags[1] && ( + + )} + {shopProfile.tags[2] && ( + + )} + + )} - {data && ( + {groomerProfile && ( )} diff --git a/packages/ui/src/components/Portfolio/GroomerPortfolioDetail.tsx b/packages/ui/src/components/Portfolio/GroomerPortfolioDetail.tsx index 7920e8c1..8cc594b3 100644 --- a/packages/ui/src/components/Portfolio/GroomerPortfolioDetail.tsx +++ b/packages/ui/src/components/Portfolio/GroomerPortfolioDetail.tsx @@ -1,32 +1,62 @@ +import { useRef, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { + Button, Card, Flex, + HardText, Header, HeightFitFlex, Image, + Menu, + Modal, PetInfo, + ProfileImage, RelativeFlex, SalonTag, Text, theme, WidthFitFlex, } from '@duri-fe/ui'; -import { UseGetPorfolioDetail } from '@duri-fe/utils'; +import { + useDeletePortfolio, + UseGetPorfolioDetail, + useModal, +} from '@duri-fe/utils'; import styled from '@emotion/styled'; export const GroomerPortfolioDetail = ({ feedbackId, + groomer = false, }: { feedbackId: number; + groomer?: boolean; }) => { const navigate = useNavigate(); + const { isOpenModal, toggleModal } = useModal(); const { data } = UseGetPorfolioDetail({ feedbackId: feedbackId, }); + const { mutateAsync: deletePortfolio } = useDeletePortfolio(); + + const [menuOpen, setMenuOpen] = useState(false); // MenuWrapper 상태 + const menuRef = useRef(null); // MenuWrapper의 ref + + const handleClickMenu = () => { + setMenuOpen(!menuOpen); + }; + + const handleClickModifyButton = () => { + // navigate('/portfolio/modify', { state: feedbackId }); + }; + + const handleClickDeleteConfirmButton = () => { + deletePortfolio(feedbackId); + }; + return ( data && ( <> @@ -39,10 +69,10 @@ export const GroomerPortfolioDetail = ({ {/** 피드백 및 후기 */} - - + + - {data.groomerInfo.name} - {/* - 2024-12-25 - */} + {/* 미용사 포폴용 - 수정삭제를 선택 할 수 있는 메뉴 노출 */} + {groomer ? ( + <> + + + {data.feedbackDate} + + + + + + {menuOpen && ( + + + 수정하기 + + + 삭제하기 + + + )} + + ) : ( + + {data.feedbackDate} + + )} @@ -115,7 +175,47 @@ export const GroomerPortfolioDetail = ({ padding="12px" /> - + + + + + 포트폴리오 본문을 + 삭제하시겠습니까? + + + + 삭제 후엔 복구할 수 없습니다. + + + 신중히 선택해주세요! + + + + + + + ) ); @@ -162,3 +262,30 @@ const PetInfoCard = styled(Card)` box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); background-color: ${theme.palette.Gray_White}; `; + +const MenuWrapper = styled(WidthFitFlex)` + cursor: pointer; +`; + +const MenuCard = styled(Flex)` + position: absolute; + top: 37.4px; + right: 9px; + background-color: ${theme.palette.White}; + box-shadow: 0px 0px 4px 0px rgba(0, 0, 0, 0.1); + z-index: 10; +`; + +const MenuItem = styled.div` + width: 100%; + height: 100%; + display: flex; + justify-content: center; + cursor: pointer; + /* padding: 0 10px; // 좌우 여백을 추가하여 텍스트가 너무 붙지 않도록 조정 */ + &:hover { + background-color: ${theme.palette.Gray_White}; + border-radius: 8px; + } + z-index: 10; +`; diff --git a/packages/ui/src/components/Portfolio/PortfolioPhotos.tsx b/packages/ui/src/components/Portfolio/PortfolioPhotos.tsx index a8d986e8..59e00361 100644 --- a/packages/ui/src/components/Portfolio/PortfolioPhotos.tsx +++ b/packages/ui/src/components/Portfolio/PortfolioPhotos.tsx @@ -1,6 +1,6 @@ import { useNavigate } from 'react-router-dom'; -import { Flex, Text } from '@duri-fe/ui'; +import { Flex, Text, theme } from '@duri-fe/ui'; import { UseGetGroomerPorfolio } from '@duri-fe/utils'; import styled from '@emotion/styled'; @@ -33,8 +33,8 @@ export const PortfolioPhotos = ({ groomerId }: PortfolioPhotosProps) => { ))} ) : ( - - 아직 등록된 포트폴리오가 없어요. + + 아직 등록된 포트폴리오가 없어요. )} diff --git a/packages/ui/src/components/ShopInfo/ShopInfo.tsx b/packages/ui/src/components/ShopInfo/ShopInfo.tsx index e42ac674..2fda931a 100644 --- a/packages/ui/src/components/ShopInfo/ShopInfo.tsx +++ b/packages/ui/src/components/ShopInfo/ShopInfo.tsx @@ -46,7 +46,8 @@ export const ShopInfo = ({ onClick, themeVariant, }: ShopInfoProps) => { - const { imageSize, typo, gap, padding, backgroundColor } = ShopInfoTheme[themeVariant]; + const { imageSize, typo, gap, padding, backgroundColor } = + ShopInfoTheme[themeVariant]; return ( {title && {title}} - + {address} - - - - - + {(shopTag1 || shopTag2 || shopTag3) && ( + + {shopTag1 && } + {shopTag2 && } + {shopTag3 && } + + )} @@ -112,5 +115,5 @@ const FlexButton = styled(Flex)` `; const ShadowImage = styled(Image)` - box-shadow: 0px 0px 4px 0px rgba(0, 0, 0, 0.10); -` \ No newline at end of file + box-shadow: 0px 0px 4px 0px rgba(0, 0, 0, 0.1); +`; diff --git a/packages/ui/vite.config.ts b/packages/ui/vite.config.ts index fabde1a8..d348c4c3 100644 --- a/packages/ui/vite.config.ts +++ b/packages/ui/vite.config.ts @@ -3,4 +3,7 @@ import { defineConfig } from 'vite'; export default defineConfig({ plugins: [react()], + resolve: { + alias: [{ find: '@assets', replacement: '/src/assets' }], + }, }); diff --git a/packages/utils/src/apis/duri/hooks/quotation.ts b/packages/utils/src/apis/duri/hooks/quotation.ts index 2a9e7411..e529cea0 100644 --- a/packages/utils/src/apis/duri/hooks/quotation.ts +++ b/packages/utils/src/apis/duri/hooks/quotation.ts @@ -1,5 +1,7 @@ import { useQuery } from '@tanstack/react-query'; +import { BaseError, RequestDetailResponse } from '../../types'; +import { UseQueryProps } from '../../types/tanstack'; import { getDetailRequestQuotaion, getQuotationList } from '../quotation'; import { getRequestItems } from './../quotation'; @@ -13,11 +15,24 @@ export const useGetRequestItems = () => { return data; }; -export const useGetDetailRequestQuotation = (requestId: number) => { +type UseGetDetailRequestQuotation = UseQueryProps< + RequestDetailResponse['response'], + BaseError +> & { + requestId: number; +}; + +// 견적서 매장 순위 조회용 +export const useGetDetailRequestQuotation = ({ + queryKey, + requestId, + options, +}: UseGetDetailRequestQuotation) => { return useQuery({ - queryKey: ['getRequestDetailInfo'], + queryKey: ['getRequestDetailInfo', requestId, ...(queryKey || [])], queryFn: () => getDetailRequestQuotaion(requestId), - staleTime: 1000 * 60 * 10, + staleTime: 1000 * 60 * 0, //항상 최신상태!! + ...options, }); }; diff --git a/packages/utils/src/apis/duri/portfolio.ts b/packages/utils/src/apis/duri/portfolio.ts index b2bd3436..397955eb 100644 --- a/packages/utils/src/apis/duri/portfolio.ts +++ b/packages/utils/src/apis/duri/portfolio.ts @@ -21,5 +21,6 @@ export const getPortfolioDetail = async ({ const { data } = await publicInstance.get(`/feedback/detail/${feedbackId}`, { params: { feedbackId }, }); + console.log(data); return data.response; }; diff --git a/packages/utils/src/apis/salon/home.ts b/packages/utils/src/apis/salon/home.ts index 11825348..e53eb4b6 100644 --- a/packages/utils/src/apis/salon/home.ts +++ b/packages/utils/src/apis/salon/home.ts @@ -1,6 +1,7 @@ import { ClosetGroomingResponse, DailyScheduleResponse, + GroomersListProfileResponse, HomeQuotationRequestResponse, HomeShopInfoResponse, salonInstance, @@ -59,3 +60,11 @@ export const putGroomingNoshow = async (quotationId: number) => { ); return response.data.response; }; + +//미용사 id 조회 +export const getGroomersProfileList = async (): Promise< +GroomersListProfileResponse['response'] +> => { + const { data } = await salonInstance.get('/shop/groomers'); + return data.response; +}; diff --git a/packages/utils/src/apis/salon/hooks/home.ts b/packages/utils/src/apis/salon/hooks/home.ts index 4a5462ed..b137e42c 100644 --- a/packages/utils/src/apis/salon/hooks/home.ts +++ b/packages/utils/src/apis/salon/hooks/home.ts @@ -2,8 +2,10 @@ import { BaseError, getClosetGrooming, getDailySchedule, + getGroomersProfileList, getHomeQuotationRequest, getHomeShopInfo, + GroomersListProfileResponse, HomeShopInfoResponse, putGroomingComplete, PutGroomingCompleteResponse, @@ -83,3 +85,20 @@ export const usePutGroomingNoshow = (): UseMutationResult< mutationFn: (quotationId: number) => putGroomingNoshow(quotationId), }); }; + +type UseGetGroomerProfile = UseQueryProps< + GroomersListProfileResponse['response'], + BaseError +>; + +export const useGetGroomersList = ({ + queryKey, + options, +}: UseGetGroomerProfile) => { + return useQuery({ + queryKey: ['getPortfolioDetail', ...(queryKey || [])], + queryFn: () => getGroomersProfileList(), + staleTime: 1000 * 60 * 5, + ...options, + }); +}; diff --git a/packages/utils/src/apis/salon/hooks/index.ts b/packages/utils/src/apis/salon/hooks/index.ts index 46bd6c78..5cc3de67 100644 --- a/packages/utils/src/apis/salon/hooks/index.ts +++ b/packages/utils/src/apis/salon/hooks/index.ts @@ -4,3 +4,4 @@ export * from './request'; export * from './quotation'; export * from './onboarding'; export * from './my'; +export * from './portfolio'; \ No newline at end of file diff --git a/packages/utils/src/apis/salon/hooks/my.ts b/packages/utils/src/apis/salon/hooks/my.ts index 209cd08e..129eb5bc 100644 --- a/packages/utils/src/apis/salon/hooks/my.ts +++ b/packages/utils/src/apis/salon/hooks/my.ts @@ -1,12 +1,12 @@ import { useQuery } from '@tanstack/react-query'; import { BaseError } from '../../types'; -import { GroomerInfoResponse } from '../../types/my'; +import { GroomerAndShopProfileResponse } from '../../types/my'; import { UseQueryProps } from '../../types/tanstack'; import { getGroomerInfo } from '../my'; type UseGetGroomerInfo = UseQueryProps< - GroomerInfoResponse['response'], +GroomerAndShopProfileResponse['response'], BaseError > & { groomerId: number; diff --git a/packages/utils/src/apis/salon/hooks/portfolio.ts b/packages/utils/src/apis/salon/hooks/portfolio.ts new file mode 100644 index 00000000..bf27b6e0 --- /dev/null +++ b/packages/utils/src/apis/salon/hooks/portfolio.ts @@ -0,0 +1,16 @@ +import { useMutation } from '@tanstack/react-query'; + +import { deletePortfolio } from '../portfolio'; + +export const useDeletePortfolio = () => { + return useMutation({ + mutationKey: ['deletePortfolio'], + mutationFn: (feedbackId: number) => deletePortfolio(feedbackId), + onSuccess: () => { + window.location.href = '/portfolio'; + }, + onError: (error) => { + console.error(error); + }, + }); +}; diff --git a/packages/utils/src/apis/salon/index.ts b/packages/utils/src/apis/salon/index.ts index 12579d72..040a68d8 100644 --- a/packages/utils/src/apis/salon/index.ts +++ b/packages/utils/src/apis/salon/index.ts @@ -5,3 +5,4 @@ export * from './request'; export * from './quotation'; export * from './onboarding'; export * from './my'; +export * from './portfolio'; \ No newline at end of file diff --git a/packages/utils/src/apis/salon/my.ts b/packages/utils/src/apis/salon/my.ts index 582d782f..104dfd7f 100644 --- a/packages/utils/src/apis/salon/my.ts +++ b/packages/utils/src/apis/salon/my.ts @@ -1,12 +1,12 @@ import { publicInstance } from '@duri-fe/utils'; -import { GroomerInfoResponse } from '../types/my'; +import { GroomerAndShopProfileResponse } from '../types/my'; export const getGroomerInfo = async ({ groomerId, }: { groomerId: number; -}): Promise => { +}): Promise => { const { data } = await publicInstance.get(`/groomer/profile/${groomerId}`, { params: { groomerId }, }); diff --git a/packages/utils/src/apis/salon/portfolio.ts b/packages/utils/src/apis/salon/portfolio.ts new file mode 100644 index 00000000..3fd58ca0 --- /dev/null +++ b/packages/utils/src/apis/salon/portfolio.ts @@ -0,0 +1,9 @@ +import { salonInstance } from '../config'; +import { PutDeletePortfolioResponse } from '../types/portfolio'; + +export const deletePortfolio = async ( + feedbackId: number, +): Promise => { + const { data } = await salonInstance.put(`/feedback/remove/${feedbackId}`); + return data; +}; diff --git a/packages/utils/src/apis/types/home.ts b/packages/utils/src/apis/types/home.ts index 8e583661..4366b0fa 100644 --- a/packages/utils/src/apis/types/home.ts +++ b/packages/utils/src/apis/types/home.ts @@ -1,4 +1,5 @@ import { BaseResponse } from './base'; +import { GroomerInfoType } from './my'; export interface ClosetGroomingResponse extends BaseResponse { response: { @@ -116,3 +117,8 @@ export interface HomeShopInfoResponse extends BaseResponse { phone: string; }; } + +//미용사 GroomersList 프로필 조회 응답 +export interface GroomersListProfileResponse extends BaseResponse { + response: GroomerInfoType[]; +} \ No newline at end of file diff --git a/packages/utils/src/apis/types/my.ts b/packages/utils/src/apis/types/my.ts index 76a02117..d71fa591 100644 --- a/packages/utils/src/apis/types/my.ts +++ b/packages/utils/src/apis/types/my.ts @@ -114,7 +114,7 @@ export interface VisitHistoryResponse { }[]; } -/** 그루머 아이디로 그루머 인포 조회 시 사용 */ +/** 그루머 아이디로 그루머 인포 조회 시 사용 & 포트폴리오 조회를 위해 id 얻으려고 사용 */ export interface GroomerInfoType { id: number; email: string; @@ -128,6 +128,22 @@ export interface GroomerInfoType { license: string[]; } -export interface GroomerInfoResponse extends BaseResponse { - response: GroomerInfoType; +export interface ShopInfoType { + id: 0; + name: string; + address: string; + imageURL: string; + phone: string; + openTime: string; + closeTime: string; + info: string; + kakaoTalk: string; + tags: string[]; +} + +export interface GroomerAndShopProfileResponse extends BaseResponse { + response: { + groomerProfileDetail: GroomerInfoType; + shopProfileDetail: ShopInfoType; + }; } diff --git a/packages/utils/src/apis/types/portfolio.ts b/packages/utils/src/apis/types/portfolio.ts index 4058ca33..939ebe93 100644 --- a/packages/utils/src/apis/types/portfolio.ts +++ b/packages/utils/src/apis/types/portfolio.ts @@ -1,5 +1,20 @@ import { BaseResponse } from './base'; +export interface GroomerProfileInfo extends BaseResponse { + response: { + id: number; + email: string; + phone: string; + name: string; + gender: string; + age: number; + history: number; + image: string; + info: string; + license: string[]; + }[]; +} + export interface PortfolioType { feedbackId: number; imageUrl: string; @@ -34,8 +49,14 @@ export interface PortfolioDetailType { feedbackImages: string[]; petInfo: PortfolioPetInfo; groomerInfo: PortfolioGroomerInfo; + feedbackDate: string; } export interface PorfolioDetailResponse extends BaseResponse { response: PortfolioDetailType; } + +//삭제 수정용 response +export interface PutDeletePortfolioResponse extends BaseResponse { + response: string; +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index d58f43f2..7af7f25e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -561,6 +561,7 @@ __metadata: react-toastify: "npm:^10.0.6" typescript: "npm:5.5.4" vite: "npm:^5.1.4" + zustand: "npm:^5.0.2" languageName: unknown linkType: soft