diff --git a/.storybook/preview-head.html b/.storybook/preview-head.html
index f7e86e8f..1dd32072 100644
--- a/.storybook/preview-head.html
+++ b/.storybook/preview-head.html
@@ -4,3 +4,9 @@
crossorigin="anonymous"
href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.6/dist/web/static/pretendard-dynamic-subset.css"
/>
+
diff --git a/apps/duri/src/App.tsx b/apps/duri/src/App.tsx
index 3e8c4753..90ca87f8 100644
--- a/apps/duri/src/App.tsx
+++ b/apps/duri/src/App.tsx
@@ -19,6 +19,10 @@ import Shop from '@pages/Shop';
import Portfolio from '@pages/Shop/Portfolio';
import ShopDetail from '@pages/Shop/ShopDetail';
+import 'react-spring-bottom-sheet/dist/style.css';
+
+import PortfolioDetail from './pages/Shop/PortfolioDetail';
+
function App() {
return (
@@ -34,18 +38,24 @@ function App() {
} />
} />
} />
-
+
} />
} />
} />
-
+
} />
+ }
+ />
} />
- } />
-
- } />
+ }
+ />
+ } />
);
diff --git a/apps/duri/src/components/shop/DesignerInfo.tsx b/apps/duri/src/components/shop/DesignerInfo.tsx
index cb574226..6ee0b971 100644
--- a/apps/duri/src/components/shop/DesignerInfo.tsx
+++ b/apps/duri/src/components/shop/DesignerInfo.tsx
@@ -1,41 +1,105 @@
import { useNavigate } from 'react-router-dom';
-import { Approve, Flex, Text } from '@duri-fe/ui';
+import { Approve, Flex, Text, theme } from '@duri-fe/ui';
import styled from '@emotion/styled';
-export const DesignerInfo = () => {
+interface DesignerInfoProps {
+ version?: 'vertical' | 'horizontal';
+ designerId: number | string;
+ name: string;
+ age: number;
+ gender: string;
+ experience: number;
+ roles: string[];
+ imageUrl: string;
+ padding?: string;
+}
+
+export const DesignerInfo = ({
+ version = 'vertical',
+ designerId,
+ name,
+ age,
+ gender,
+ experience,
+ roles,
+ imageUrl,
+ padding,
+}: DesignerInfoProps) => {
const navigate = useNavigate();
- const moveToDetail = (designerId: number | string) => {
- navigate(`/portfolio/${designerId}`);
+
+ const moveToPortfolio = () => {
+ if (version === 'vertical') {
+ navigate(`/portfolio/${designerId}`);
+ }
};
+
return (
- moveToDetail(1)}>
-
-
- 김댕댕
-
- 경력 5년,30세,남성
-
-
- {['반려견 스타일리스트', '펫테이너'].map((item, idx) => (
-
- {item}
-
-
- ))}
+
+
+
+
+
+
+ {name}
+
+ {`경력 ${experience}년, ${age}세, ${gender}`}
+
+
+ {roles.map((item, idx) => (
+
+
+ {item}
+
+
+
+ ))}
+
-
+
);
};
-const DesignerImg = styled.img`
- display: flex;
- width: 160px;
- height: 160px;
- border-radius: 8px;
+const Container = styled(Flex)<{
+ version: 'vertical' | 'horizontal';
+ clickable: boolean;
+}>`
+ cursor: ${({ clickable }) => (clickable ? 'pointer' : 'default')};
+`;
+
+const DesignerImg = styled.img<{ version: 'vertical' | 'horizontal' }>`
+ width: ${({ version }) => (version === 'horizontal' ? '124px' : '160px')};
+ height: ${({ version }) => (version === 'horizontal' ? '124px' : '160px')};
+ border-radius: ${({ version }) =>
+ version === 'horizontal' ? '99px' : '8px'};
object-fit: cover;
`;
+
+const ImageWrapper = styled.div<{ version: 'vertical' | 'horizontal' }>`
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-shrink: 0;
+`;
+
+// 역할 태그 스타일
+const Role = styled(Flex)`
+ justify-content: flex-start;
+ align-items: center;
+ gap: 8px;
+`;
diff --git a/apps/duri/src/components/shop/PortfolioPhotos.tsx b/apps/duri/src/components/shop/PortfolioPhotos.tsx
new file mode 100644
index 00000000..f96dcc23
--- /dev/null
+++ b/apps/duri/src/components/shop/PortfolioPhotos.tsx
@@ -0,0 +1,46 @@
+import { useNavigate } from 'react-router-dom';
+
+import { Flex } from '@duri-fe/ui';
+import styled from '@emotion/styled';
+
+interface PortfolioPhotosProps {
+ portfolios: { id: number; src: string }[];
+ designerId: string | number;
+}
+
+export const PortfolioPhotos = ({
+ portfolios,
+ designerId,
+}: PortfolioPhotosProps) => {
+ const navigate = useNavigate();
+
+ const moveToProfolioDetail = (id: number) => {
+ navigate(`/portfolio/${designerId}/${id}`);
+ };
+ return (
+
+
+ {portfolios.map((item, index) => (
+ moveToProfolioDetail(item.id)}
+ />
+ ))}
+
+
+ );
+};
+
+const PhotoGrid = styled.div`
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 3px;
+`;
+
+const PortfolioInsideImg = styled.img`
+ width: 120px;
+ height: 120px;
+ object-fit: cover;
+`;
diff --git a/apps/duri/src/components/shop/SendRequesQBox.tsx b/apps/duri/src/components/shop/SendRequesQBox.tsx
new file mode 100644
index 00000000..2ef77ff6
--- /dev/null
+++ b/apps/duri/src/components/shop/SendRequesQBox.tsx
@@ -0,0 +1,77 @@
+import { useNavigate } from 'react-router-dom';
+
+import {
+ Button,
+ HeightFitFlex,
+ NextArrow,
+ RelativeFlex,
+ SendColor,
+ Text,
+ theme,
+ WidthFitFlex,
+} from '@duri-fe/ui';
+import styled from '@emotion/styled';
+
+export const SendRequestQBox = () => {
+ const navigate = useNavigate();
+ const moveToShopRequest = () => {
+ navigate('/shop/request');
+ };
+ return (
+
+
+
+ 견적 요청서를 전송하시겠습니까?
+
+
+ 선택한 샵에 요청서를 전송합니다.
+
+
+
+ 요청서 선택
+
+ 작성한 요청서가 없습니다.
+
+
+ 작성하러가기
+
+
+
+
+
+
+
+ 취소
+
+
+
+ 확인
+
+
+
+
+ );
+};
+const AbsoluteBtnWrapper = styled(HeightFitFlex)`
+ position: absolute;
+ bottom: 0;
+`;
+
+const FlexBtn = styled(Button)<{ flex: string }>`
+ border-radius: 8px;
+ flex: ${({ flex }) => flex};
+`;
diff --git a/apps/duri/src/components/shop/ShopInfo.tsx b/apps/duri/src/components/shop/ShopInfo.tsx
index c176c66e..1a292aa5 100644
--- a/apps/duri/src/components/shop/ShopInfo.tsx
+++ b/apps/duri/src/components/shop/ShopInfo.tsx
@@ -1,128 +1,209 @@
-import salonDefault from '@assets/images/pngs/salonDefault.png';
+import { BottomSheet } from 'react-spring-bottom-sheet';
+import { useNavigate } from 'react-router-dom';
+
import {
Call,
+ DownArrow,
FilledLocation,
Flex,
+ FrontBtn,
+ HardText,
HeightFitFlex,
+ Image,
+ RatingStars,
+ Send,
Star,
Text,
theme,
Time,
WidthFitFlex,
} from '@duri-fe/ui';
+import { PetInfo } from '@duri-fe/ui';
+import { useBottomSheet } from '@duri-fe/utils';
import styled from '@emotion/styled';
import { DesignerInfo } from './DesignerInfo';
+import { SendRequestQBox } from './SendRequesQBox';
import { ShopPhotos } from './ShopPhotos';
export const ShopInfo = () => {
+ const navigate = useNavigate();
+ const { openSheet, bottomSheetProps } = useBottomSheet({
+ maxHeight: 556,
+ });
+
return (
-
-
- {/**헤더 */}
-
-
- 댕댕샵
-
-
- 4.9 (120)
-
-
-
-
-
-
- {`354m | `}
- 주소
-
-
-
-
-
-
- 02-111-1111
-
-
-
-
-
- 9:00 ~ 1800
-
-
-
-
-
- 안녕하세요!
- 꼼꼼하고 소중히 미용하는 댕댕샵입니다.
-
-
-
- {/**디자이너 */}
- 디자이너 소개
-
-
- {/**샵 내부 */}
- 샵 내부
-
-
- {/**리뷰 */}
-
- 리뷰
-
- 4.9 (120)
-
-
+
-
-
-
-
-
- 사용자 이름
-
-
+ navigate(-1)}>
+
+
+
+
+ {/**헤더 */}
+
+
+ 댕댕샵
+
+
+ 4.9 (120)
-
-
- 2024-12-26
-
-
- 후기를 작성하는 곳 ~~ 아주 좋았습니다
+
+
+
+
+
+ {`354m | `}
+ 서울특별시 강남구 188-16 101호
+
+
+
+
+
+
+ 02-111-1111
+
+
+
+
+
+ 9:00 ~ 18:00
+
+
+
-
-
- 신참이
+
+ 안녕하세요!
+ 꼼꼼하고 소중히 미용하는 댕댕샵입니다.
+
+
+
+ {/**디자이너 */}
+
+ 디자이너 소개
+
+
+
+ {/**샵 내부 */}
+
+ 샵 내부
+
+
+
+ {/**리뷰 */}
+
+
+ 리뷰
+
+ 4.2
+
+ (120)
+
+
+
- 시츄, 암컷, 7세,
- 7.3kg
+
+
+
+
+ 사용자 이름
+
+
+
+
+
+ 2024-12-26
+
-
+
+ 후기를 작성하는 곳 ~~ 아주 좋았습니다. 후기를작성하는
+ 칸입니다.후기를작성하는 칸입니다.후기를작성하는 칸입니다.
+
+
+
+
+
-
-
+
+
+
+
+ 요청서 보내기
+
+
+
+
+
+ >
);
};
const ShopInfoContainer = styled(Flex)`
@@ -148,20 +229,6 @@ const MainImg = styled.img`
object-fit: cover;
`;
-const ReviewerImg = styled.img`
- display: flex;
- width: 34px;
- height: 34px;
- border-radius: 99px;
-`;
-
-const PetImg = styled.img`
- display: flex;
- width: 77px;
- height: 77px;
- border-radius: 99px;
-`;
-
const ShadowFlex = styled(HeightFitFlex)`
box-shadow: 0px 0px 4px 0px rgba(0, 0, 0, 0.1);
`;
diff --git a/apps/duri/src/components/shop/ShopList.tsx b/apps/duri/src/components/shop/ShopList.tsx
index 96bd09ba..d0162309 100644
--- a/apps/duri/src/components/shop/ShopList.tsx
+++ b/apps/duri/src/components/shop/ShopList.tsx
@@ -17,8 +17,7 @@ import {
import { ShopInfoType, useBottomSheet } from '@duri-fe/utils';
import styled from '@emotion/styled';
-import 'react-spring-bottom-sheet/dist/style.css';
-
+import { SendRequestQBox } from './SendRequesQBox';
import { ShopLine } from './ShopLine';
interface ShopListProps {
@@ -32,9 +31,17 @@ export const ShopList = ({
filter,
onFilterChange,
}: ShopListProps) => {
- const { openSheet, bottomSheetProps } = useBottomSheet({
- maxHeight: 260,
- });
+ // 필터용
+ const { openSheet: openFilterSheet, bottomSheetProps: filterSheetProps } =
+ useBottomSheet({
+ maxHeight: 260,
+ });
+
+ // 요청서 전송용
+ const { openSheet: openRequestSheet, bottomSheetProps: requestSheetProps } =
+ useBottomSheet({
+ maxHeight: 552,
+ });
// 선택된 가게 취합용
const [selectedShops, setSelectedShops] = useState([]);
@@ -61,7 +68,7 @@ export const ShopList = ({
borderRadius="99px"
padding="10px"
shadow={'0px 0px 4px 0px rgba(0, 0, 0, 0.25)'}
- onClick={openSheet}
+ onClick={openFilterSheet}
>
@@ -145,7 +153,7 @@ export const ShopList = ({
) : null}
-
+
+
+
+
>
);
diff --git a/apps/duri/src/components/shop/index.tsx b/apps/duri/src/components/shop/index.tsx
index e4431002..e57cc694 100644
--- a/apps/duri/src/components/shop/index.tsx
+++ b/apps/duri/src/components/shop/index.tsx
@@ -3,3 +3,5 @@ export { ShopList } from './ShopList';
export { ShopLine } from './ShopLine';
export { ShopInfo } from './ShopInfo';
export { DesignerInfo } from './DesignerInfo';
+export { ShopPhotos } from './ShopPhotos';
+export { PortfolioPhotos } from './PortfolioPhotos';
diff --git a/apps/duri/src/pages/Shop/Portfolio.tsx b/apps/duri/src/pages/Shop/Portfolio.tsx
index e6ea87d2..6d13dadb 100644
--- a/apps/duri/src/pages/Shop/Portfolio.tsx
+++ b/apps/duri/src/pages/Shop/Portfolio.tsx
@@ -1,12 +1,14 @@
import { useState } from 'react';
+import { useParams } from 'react-router-dom';
+import { DesignerInfo, PortfolioPhotos } from '@duri/components/shop';
import {
- AbsoluteFlex,
+ DuriNavbar,
FilledHeart,
+ Flex,
Heart,
HeightFitFlex,
MobileLayout,
- RelativeFlex,
Text,
theme,
WidthFitFlex,
@@ -16,17 +18,54 @@ import styled from '@emotion/styled';
const Portfolio = () => {
const [isMarked, setIsMarked] = useState(false);
+ // image dummy
+ const { designerId } = useParams<{ designerId: string }>();
+
+ const images = [
+ {
+ id: 1,
+ src: 'https://s3-alpha-sig.figma.com/img/7a9d/1693/e6a098242d4a2c8446d1acc0d8bf51ab?Expires=1734912000&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4&Signature=oWIr3Sr2va~UzNKEF4BG2jr3NWDieuXmdrJOaLxpHdcMJKypZi9sN3TyZQCj60ZIlgmzE8Ntj-6~sQBDL1N719Z5AI7J6~WtCi9mWR6jRRNoIxUALcUvZ1lmTuHeywMpKYDzPRbebB~KbJSCv3JphfMpuGEUeS~E3MuLPwsaexSdVtpfcUQg3uYmS3-qPMxnwym0oUbYBPK0xJD28yK3ZjfiMm~FtHSnXUmXegJ4Bp74sYndmHEF1MQKtVfy7h5N-ugtkTT9LuuLerthz26tNe8h4kYfEE9edM7puOyXCIH5Xgh4lNzt4WGD0ObsbUS8XkYpXrTiobSniqq~vnYUHg__',
+ },
+ {
+ id: 2,
+ src: 'https://s3-alpha-sig.figma.com/img/7a9d/1693/e6a098242d4a2c8446d1acc0d8bf51ab?Expires=1734912000&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4&Signature=oWIr3Sr2va~UzNKEF4BG2jr3NWDieuXmdrJOaLxpHdcMJKypZi9sN3TyZQCj60ZIlgmzE8Ntj-6~sQBDL1N719Z5AI7J6~WtCi9mWR6jRRNoIxUALcUvZ1lmTuHeywMpKYDzPRbebB~KbJSCv3JphfMpuGEUeS~E3MuLPwsaexSdVtpfcUQg3uYmS3-qPMxnwym0oUbYBPK0xJD28yK3ZjfiMm~FtHSnXUmXegJ4Bp74sYndmHEF1MQKtVfy7h5N-ugtkTT9LuuLerthz26tNe8h4kYfEE9edM7puOyXCIH5Xgh4lNzt4WGD0ObsbUS8XkYpXrTiobSniqq~vnYUHg__',
+ },
+ {
+ id: 3,
+ src: 'https://s3-alpha-sig.figma.com/img/7a9d/1693/e6a098242d4a2c8446d1acc0d8bf51ab?Expires=1734912000&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4&Signature=oWIr3Sr2va~UzNKEF4BG2jr3NWDieuXmdrJOaLxpHdcMJKypZi9sN3TyZQCj60ZIlgmzE8Ntj-6~sQBDL1N719Z5AI7J6~WtCi9mWR6jRRNoIxUALcUvZ1lmTuHeywMpKYDzPRbebB~KbJSCv3JphfMpuGEUeS~E3MuLPwsaexSdVtpfcUQg3uYmS3-qPMxnwym0oUbYBPK0xJD28yK3ZjfiMm~FtHSnXUmXegJ4Bp74sYndmHEF1MQKtVfy7h5N-ugtkTT9LuuLerthz26tNe8h4kYfEE9edM7puOyXCIH5Xgh4lNzt4WGD0ObsbUS8XkYpXrTiobSniqq~vnYUHg__',
+ },
+ {
+ id: 4,
+ src: 'https://s3-alpha-sig.figma.com/img/7a9d/1693/e6a098242d4a2c8446d1acc0d8bf51ab?Expires=1734912000&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4&Signature=oWIr3Sr2va~UzNKEF4BG2jr3NWDieuXmdrJOaLxpHdcMJKypZi9sN3TyZQCj60ZIlgmzE8Ntj-6~sQBDL1N719Z5AI7J6~WtCi9mWR6jRRNoIxUALcUvZ1lmTuHeywMpKYDzPRbebB~KbJSCv3JphfMpuGEUeS~E3MuLPwsaexSdVtpfcUQg3uYmS3-qPMxnwym0oUbYBPK0xJD28yK3ZjfiMm~FtHSnXUmXegJ4Bp74sYndmHEF1MQKtVfy7h5N-ugtkTT9LuuLerthz26tNe8h4kYfEE9edM7puOyXCIH5Xgh4lNzt4WGD0ObsbUS8XkYpXrTiobSniqq~vnYUHg__',
+ },
+ {
+ id: 6,
+ src: 'https://s3-alpha-sig.figma.com/img/7a9d/1693/e6a098242d4a2c8446d1acc0d8bf51ab?Expires=1734912000&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4&Signature=oWIr3Sr2va~UzNKEF4BG2jr3NWDieuXmdrJOaLxpHdcMJKypZi9sN3TyZQCj60ZIlgmzE8Ntj-6~sQBDL1N719Z5AI7J6~WtCi9mWR6jRRNoIxUALcUvZ1lmTuHeywMpKYDzPRbebB~KbJSCv3JphfMpuGEUeS~E3MuLPwsaexSdVtpfcUQg3uYmS3-qPMxnwym0oUbYBPK0xJD28yK3ZjfiMm~FtHSnXUmXegJ4Bp74sYndmHEF1MQKtVfy7h5N-ugtkTT9LuuLerthz26tNe8h4kYfEE9edM7puOyXCIH5Xgh4lNzt4WGD0ObsbUS8XkYpXrTiobSniqq~vnYUHg__',
+ },
+ {
+ id: 7,
+ src: 'https://s3-alpha-sig.figma.com/img/7a9d/1693/e6a098242d4a2c8446d1acc0d8bf51ab?Expires=1734912000&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4&Signature=oWIr3Sr2va~UzNKEF4BG2jr3NWDieuXmdrJOaLxpHdcMJKypZi9sN3TyZQCj60ZIlgmzE8Ntj-6~sQBDL1N719Z5AI7J6~WtCi9mWR6jRRNoIxUALcUvZ1lmTuHeywMpKYDzPRbebB~KbJSCv3JphfMpuGEUeS~E3MuLPwsaexSdVtpfcUQg3uYmS3-qPMxnwym0oUbYBPK0xJD28yK3ZjfiMm~FtHSnXUmXegJ4Bp74sYndmHEF1MQKtVfy7h5N-ugtkTT9LuuLerthz26tNe8h4kYfEE9edM7puOyXCIH5Xgh4lNzt4WGD0ObsbUS8XkYpXrTiobSniqq~vnYUHg__',
+ },
+ {
+ id: 8,
+ src: 'https://s3-alpha-sig.figma.com/img/7a9d/1693/e6a098242d4a2c8446d1acc0d8bf51ab?Expires=1734912000&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4&Signature=oWIr3Sr2va~UzNKEF4BG2jr3NWDieuXmdrJOaLxpHdcMJKypZi9sN3TyZQCj60ZIlgmzE8Ntj-6~sQBDL1N719Z5AI7J6~WtCi9mWR6jRRNoIxUALcUvZ1lmTuHeywMpKYDzPRbebB~KbJSCv3JphfMpuGEUeS~E3MuLPwsaexSdVtpfcUQg3uYmS3-qPMxnwym0oUbYBPK0xJD28yK3ZjfiMm~FtHSnXUmXegJ4Bp74sYndmHEF1MQKtVfy7h5N-ugtkTT9LuuLerthz26tNe8h4kYfEE9edM7puOyXCIH5Xgh4lNzt4WGD0ObsbUS8XkYpXrTiobSniqq~vnYUHg__',
+ },
+ ];
+
return (
-
+
-
+
- 댕댕샵
+
+ 댕댕샵
+
setIsMarked(!isMarked)}
@@ -37,11 +76,30 @@ const Portfolio = () => {
)}
-
- 경기도 성남시 불정로 119
-
-
+
+ 경기도 성남시 불정로 119
+
+
+
+
+
+
+ {designerId && (
+
+ )}
+
+
);
};
@@ -49,12 +107,38 @@ const Portfolio = () => {
export default Portfolio;
const MainImg = styled.img`
+ position: absolute;
width: 100%;
- position: relative;
aspect-ratio: 375 / 310;
object-fit: cover;
+ z-index: -1;
+`;
+
+const HeaderBox = styled(Flex)`
+ position: relative;
+ z-index: 1;
+ aspect-ratio: 375 / 310;
+ height: auto;
+
+ &::before {
+ content: '';
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ height: 70%;
+ background: linear-gradient(
+ 180deg,
+ rgba(217, 217, 217, 0) 0%,
+ ${theme.palette.Black} 100%
+ );
+ }
`;
-const Gradation = styled.div`
- background: linear-gradient(180deg, rgba(217, 217, 217, 0) 0%, #111 100%);
+const TextBox = styled(Flex)`
+ position: absolute;
+ width: fit-content;
+ height: fit-content;
+ left: 20px;
+ bottom: 36px;
`;
diff --git a/apps/duri/src/pages/Shop/PortfolioDetail.tsx b/apps/duri/src/pages/Shop/PortfolioDetail.tsx
new file mode 100644
index 00000000..69f2decb
--- /dev/null
+++ b/apps/duri/src/pages/Shop/PortfolioDetail.tsx
@@ -0,0 +1,97 @@
+// import { useParams } from 'react-router-dom';
+
+import { useNavigate } from 'react-router-dom';
+
+import {
+ DuriNavbar,
+ Flex,
+ HardText,
+ Header,
+ HeightFitFlex,
+ Image,
+ MobileLayout,
+ RelativeFlex,
+ Text,
+ theme,
+ WidthFitFlex,
+} from '@duri-fe/ui';
+import styled from '@emotion/styled';
+
+const PortfolioDetail = () => {
+ const navigate = useNavigate();
+
+ return (
+
+
+ navigate(-1)}
+ />
+
+
+
+
+
+ {/** 피드백 및 후기 */}
+
+
+
+
+
+ 김댕댕
+
+
+ 2024-12-25
+
+
+
+
+
+
+ 너무 행복했던 뽀삐와의 미용이 있었어요 :D 너무 얌전하게 미용
+ 잘받고간 우리 뽀삐에게 박수^~^ 뽀삐 너무 귀여워요 우리 뽀삐 최고~
+
+
+
+
+
+
+
+ );
+};
+
+export default PortfolioDetail;
+
+const AbsoluteHeader = styled(Header)`
+ position: absolute;
+ z-index: 2;
+`;
+
+const AbsoluteWrapper = styled(HeightFitFlex)`
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 0;
+`;
+
+const LetterBox = styled(Flex)`
+ border-radius: 0px 16px 16px 16px;
+`;
diff --git a/apps/salon/src/pages/Quotation/index.tsx b/apps/salon/src/pages/Quotation/index.tsx
index 18013f5d..8f9fc1c1 100644
--- a/apps/salon/src/pages/Quotation/index.tsx
+++ b/apps/salon/src/pages/Quotation/index.tsx
@@ -1,28 +1,49 @@
-import { Card, Flex, MobileLayout, PetInfo, SalonNavbar, theme } from "@duri-fe/ui"
-import { TabBarItem } from "@salon/components/quotation/TabBarItem"
+import {
+ Card,
+ Flex,
+ MobileLayout,
+ PetInfo,
+ SalonNavbar,
+ theme,
+} from '@duri-fe/ui';
+import { TabBarItem } from '@salon/components/quotation/TabBarItem';
export const QuotationPage = () => {
return (
-
-
-
+
+
+
-
-
-
+
+
+
-
@@ -30,5 +51,5 @@ export const QuotationPage = () => {
- )
-}
\ No newline at end of file
+ );
+};
diff --git a/packages/ui/src/assets/BeforeArrow.tsx b/packages/ui/src/assets/BeforeArrow.tsx
index c25bd643..04a6c09f 100644
--- a/packages/ui/src/assets/BeforeArrow.tsx
+++ b/packages/ui/src/assets/BeforeArrow.tsx
@@ -7,8 +7,8 @@ const SvgBeforeArrow = (props: React.SVGProps) => (
{...props}
>
diff --git a/packages/ui/src/assets/SendColor.tsx b/packages/ui/src/assets/SendColor.tsx
new file mode 100644
index 00000000..00e3c42a
--- /dev/null
+++ b/packages/ui/src/assets/SendColor.tsx
@@ -0,0 +1,17 @@
+import * as React from 'react';
+const SvgSendColor = (props: React.SVGProps) => (
+
+);
+export default SvgSendColor;
diff --git a/packages/ui/src/assets/index.tsx b/packages/ui/src/assets/index.tsx
index f75e657b..ffae693d 100644
--- a/packages/ui/src/assets/index.tsx
+++ b/packages/ui/src/assets/index.tsx
@@ -1,3 +1,4 @@
+export { default as SendColor } from './SendColor';
export { default as Add } from './Add';
export { default as AddNew } from './AddNew';
export { default as Approve } from './Approve';
@@ -111,6 +112,7 @@ import SecurityWarning from './SecurityWarning';
import SelectBox from './SelectBox';
import SelectBoxUn from './SelectBoxUn';
import Send from './Send';
+import SendColor from './SendColor';
import Shield from './Shield';
import Shopping from './Shopping';
import Star from './Star';
@@ -160,6 +162,7 @@ export const icons = {
CurLocation,
Notification,
FilledNotification,
+ SendColor,
Report,
FilledReport,
Menu,
diff --git a/packages/ui/src/assets/svgs/Time.svg b/packages/ui/src/assets/svgs/Time.svg
deleted file mode 100644
index 4abc17d7..00000000
--- a/packages/ui/src/assets/svgs/Time.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
diff --git a/packages/ui/src/components/MobileLayout/MobileLayout.tsx b/packages/ui/src/components/MobileLayout/MobileLayout.tsx
index 9710415a..12fe32d7 100644
--- a/packages/ui/src/components/MobileLayout/MobileLayout.tsx
+++ b/packages/ui/src/components/MobileLayout/MobileLayout.tsx
@@ -26,7 +26,10 @@ export const MobileLayout = ({
};
const Container = styled(Flex)`
- max-width: 375px;
min-height: 100vh;
box-sizing: border-box;
+
+ @media (min-width: 420px) {
+ max-width: 375px;
+ }
`;
diff --git a/packages/ui/src/components/ProfileImage/ProfileImage.tsx b/packages/ui/src/components/ProfileImage/ProfileImage.tsx
index 9d2f5fc7..da8bcc61 100644
--- a/packages/ui/src/components/ProfileImage/ProfileImage.tsx
+++ b/packages/ui/src/components/ProfileImage/ProfileImage.tsx
@@ -1,5 +1,5 @@
-import { Flex, Profile, theme } from "@duri-fe/ui";
-import styled from "@emotion/styled";
+import { Flex, Image, Profile, theme } from '@duri-fe/ui';
+import styled from '@emotion/styled';
interface ProfileImageProps {
width: number;
@@ -14,22 +14,34 @@ export const ProfileImage = ({
height,
borderRadius,
src,
- iconSize = 52
+ iconSize = 52,
}: ProfileImageProps) => {
- return (
- src ? (
-
-
-
- ) : (
-
-
-
- )
- )
-}
+ return src ? (
+
+
+
+ ) : (
+
+
+
+ );
+};
const ProfileContainer = styled(Flex)`
flex-shrink: 0;
overflow: hidden;
-`
\ No newline at end of file
+`;
diff --git a/packages/ui/src/components/Quotation/PetInfo.tsx b/packages/ui/src/components/Quotation/PetInfo.tsx
index 84dbe046..31eb9a74 100644
--- a/packages/ui/src/components/Quotation/PetInfo.tsx
+++ b/packages/ui/src/components/Quotation/PetInfo.tsx
@@ -2,6 +2,7 @@ import {
diseaseMapping,
Flex,
HeightFitFlex,
+ KeyOfTypo,
personalityMapping,
ProfileImage,
SalonTag,
@@ -16,11 +17,10 @@ interface PetInfoType {
breed: string;
weight: number;
gender: string;
+ themeVariant?: 'compact' | 'spacious' | 'medium';
neutering?: boolean;
character?: string[];
diseases?: string[];
- imageSize?: number;
- imageBorderRadius?: number;
}
export const PetInfo = ({
@@ -33,47 +33,95 @@ export const PetInfo = ({
neutering,
character,
diseases,
- imageSize = 133,
- imageBorderRadius = 40,
+ themeVariant = 'spacious',
}: PetInfoType) => {
+ const { imageSize, gap, typo } = PetInfoTheme[themeVariant];
+
return (
-
-
- {name}
-
+
+
+ {name}
+
{breed}, {gender === 'F' ? '암컷' : '수컷'}, {age}세, {weight}kg
{neutering && }
- {character &&
- {character.map((key, index) => {
- const label = personalityMapping[key]
- return
- })}
- }
- {diseases &&
- {diseases.map((key, index) => {
- const label = diseaseMapping[key]
- return
- })}
- }
+ {character && (
+
+ {character.map((key, index) => {
+ const label = personalityMapping[key];
+ return (
+
+ );
+ })}
+
+ )}
+ {diseases && (
+
+ {diseases.map((key, index) => {
+ const label = diseaseMapping[key];
+ return (
+
+ );
+ })}
+
+ )}
);
};
+
+interface ThemeVariant {
+ imageSize: {
+ width: number;
+ height: number;
+ borderRadius: number;
+ };
+ gap: {
+ vertical: number;
+ horizontal: number;
+ };
+ typo: {
+ name: KeyOfTypo;
+ description: KeyOfTypo;
+ };
+}
+
+const PetInfoTheme: Record<'compact' | 'spacious' | 'medium', ThemeVariant> = {
+ compact: {
+ imageSize: { width: 77, height: 77, borderRadius: 99 },
+ gap: { vertical: 20, horizontal: 6 },
+ typo: { name: 'Label1', description: 'Label3' },
+ },
+ medium: {
+ imageSize: { width: 100, height: 100, borderRadius: 8 },
+ gap: { vertical: 18, horizontal: 6 },
+ typo: { name: 'Body2', description: 'Caption2' },
+ },
+ spacious: {
+ imageSize: { width: 133, height: 133, borderRadius: 40 },
+ gap: { vertical: 18, horizontal: 8 },
+ typo: { name: 'Title3', description: 'Body3' },
+ },
+};
diff --git a/packages/ui/src/components/RatingStars/RatingStars.tsx b/packages/ui/src/components/RatingStars/RatingStars.tsx
new file mode 100644
index 00000000..097d08d6
--- /dev/null
+++ b/packages/ui/src/components/RatingStars/RatingStars.tsx
@@ -0,0 +1,18 @@
+import { Star, WidthFitFlex } from '@duri-fe/ui';
+
+interface RatingStarsProps {
+ score: number;
+ size: number;
+}
+
+export const RatingStars = ({ score, size }: RatingStarsProps) => {
+ const fullStars = Math.round(score);
+
+ return (
+
+ {Array.from({ length: fullStars }).map((_, idx) => (
+
+ ))}
+
+ );
+};
diff --git a/packages/ui/src/components/RatingStars/index.tsx b/packages/ui/src/components/RatingStars/index.tsx
new file mode 100644
index 00000000..d2bbd2f9
--- /dev/null
+++ b/packages/ui/src/components/RatingStars/index.tsx
@@ -0,0 +1 @@
+export { RatingStars } from './RatingStars';
diff --git a/packages/ui/src/components/index.tsx b/packages/ui/src/components/index.tsx
index c0f0c863..bc70f808 100644
--- a/packages/ui/src/components/index.tsx
+++ b/packages/ui/src/components/index.tsx
@@ -17,3 +17,4 @@ export * from './Toast';
export * from './Modal';
export * from './ProfileImage';
export * from './Quotation';
+export * from './RatingStars';
diff --git a/packages/ui/src/stories/styles/Typo.mdx b/packages/ui/src/stories/styles/Typo.mdx
index d504b4ce..126daf3d 100644
--- a/packages/ui/src/stories/styles/Typo.mdx
+++ b/packages/ui/src/stories/styles/Typo.mdx
@@ -132,3 +132,14 @@ import { theme } from '../../styles';
sampleText={'Body4: This is a sample text.'}
fontFamily={'Pretendard'}
/>
+
+
+
+## Letter
+
+
diff --git a/packages/ui/src/styles/typo.tsx b/packages/ui/src/styles/typo.tsx
index f3fead77..db60ae50 100644
--- a/packages/ui/src/styles/typo.tsx
+++ b/packages/ui/src/styles/typo.tsx
@@ -5,6 +5,7 @@ export const calcRem = (px: number) => `${px / 16}rem`;
* @param Title1: 페이지 제목 타이틀
* @param Title2: 본문 타이틀
* @param Title3: 박스 안에 들어가는 타이틀
+ * @param Title4: 가게 상세 페이지 타이틀
*
* @param Caption1: 타이틀 위/아래 부가설명 텍스트
* @param Caption2: 거리표시 텍스트
@@ -75,6 +76,13 @@ export const typo = {
font-weight: 600;
line-height: normal;
`,
+ Title4: css`
+ /* 가게 상세 타이틀 */
+ font-family: 'Pretendard';
+ font-size: ${calcRem(22)};
+ font-weight: 600;
+ line-height: normal;
+ `,
Caption1: css`
/* 타이틀 위/아래 부가설명 텍스트 */
font-family: 'Pretendard';
@@ -84,7 +92,6 @@ export const typo = {
`,
Caption2: css`
/* 거리표시 텍스트 */
-
font-family: 'Pretendard';
font-size: ${calcRem(13)};
font-weight: 500;
diff --git a/packages/utils/src/hooks/useBottomSheet.ts b/packages/utils/src/hooks/useBottomSheet.ts
index 7504c432..a75297a1 100644
--- a/packages/utils/src/hooks/useBottomSheet.ts
+++ b/packages/utils/src/hooks/useBottomSheet.ts
@@ -42,11 +42,14 @@ const StyledBottomCss = css`
[data-rsbs-root]::after {
border-radius: 16px 16px 0px 0px;
z-index: 20;
- max-width: 375px;
+ --max-width: 375px;
- @media (min-width: 480px) {
- left: calc(50% - 187.5px);
+ @media (max-width: 420px) {
+ --max-width: 100%;
}
+
+ max-width: var(--max-width);
+ left: calc(50% - (var(--max-width) / 2));
}
[data-rsbs-backdrop] {