Skip to content

Commit d219aee

Browse files
authored
Merge pull request #53 from Duri-Salon/feat(duri)/q-post-ui(DURI-107)
2 parents 94b232c + 7a4b397 commit d219aee

File tree

24 files changed

+842
-236
lines changed

24 files changed

+842
-236
lines changed

.storybook/preview-head.html

+6
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,9 @@
44
crossorigin="anonymous"
55
href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.6/dist/web/static/pretendard-dynamic-subset.css"
66
/>
7+
<link
8+
rel="stylesheet"
9+
as="style"
10+
crossorigin="anonymous"
11+
href="https://ownglyph-ryryu.vercel.app/style.css"
12+
/>

apps/duri/src/App.tsx

+15-5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ import Shop from '@pages/Shop';
1919
import Portfolio from '@pages/Shop/Portfolio';
2020
import ShopDetail from '@pages/Shop/ShopDetail';
2121

22+
import 'react-spring-bottom-sheet/dist/style.css';
23+
24+
import PortfolioDetail from './pages/Shop/PortfolioDetail';
25+
2226
function App() {
2327
return (
2428
<BrowserRouter>
@@ -34,18 +38,24 @@ function App() {
3438
<Route path="/payment" element={<PaymentPage />} />
3539
<Route path="/payment/success" element={<SuccessPage />} />
3640
<Route path="/payment/fail" element={<FailPage />} />
37-
41+
3842
<Route path="/shop/request" element={<RequestPage />} />
3943
<Route path="/shop" element={<Shop />} />
4044
<Route path="/shop/:shopId" element={<ShopDetail />} />
41-
45+
4246
<Route path="/portfolio/:designerId" element={<Portfolio />} />
47+
<Route
48+
path="/portfolio/:designerId/:portfolioId"
49+
element={<PortfolioDetail />}
50+
/>
4351

4452
<Route path="/quotation" element={<QuotationPage />} />
45-
<Route path="/quotation/:quotationId" element={<QuotationDetailPage />} />
46-
47-
<Route path="/my" element={<MyPage />} />
53+
<Route
54+
path="/quotation/:quotationId"
55+
element={<QuotationDetailPage />}
56+
/>
4857

58+
<Route path="/my" element={<MyPage />} />
4959
</Routes>
5060
</BrowserRouter>
5161
);
+92-28
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,105 @@
11
import { useNavigate } from 'react-router-dom';
22

3-
import { Approve, Flex, Text } from '@duri-fe/ui';
3+
import { Approve, Flex, Text, theme } from '@duri-fe/ui';
44
import styled from '@emotion/styled';
55

6-
export const DesignerInfo = () => {
6+
interface DesignerInfoProps {
7+
version?: 'vertical' | 'horizontal';
8+
designerId: number | string;
9+
name: string;
10+
age: number;
11+
gender: string;
12+
experience: number;
13+
roles: string[];
14+
imageUrl: string;
15+
padding?: string;
16+
}
17+
18+
export const DesignerInfo = ({
19+
version = 'vertical',
20+
designerId,
21+
name,
22+
age,
23+
gender,
24+
experience,
25+
roles,
26+
imageUrl,
27+
padding,
28+
}: DesignerInfoProps) => {
729
const navigate = useNavigate();
8-
const moveToDetail = (designerId: number | string) => {
9-
navigate(`/portfolio/${designerId}`);
30+
31+
const moveToPortfolio = () => {
32+
if (version === 'vertical') {
33+
navigate(`/portfolio/${designerId}`);
34+
}
1035
};
36+
1137
return (
12-
<Flex direction="column" align="flex-start" onClick={() => moveToDetail(1)}>
13-
<DesignerImg
14-
src={
15-
'https://s3-alpha-sig.figma.com/img/06a3/855c/666ff7b8f7c18c7121369ac3b3132d84?Expires=1734307200&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4&Signature=kHnZaYFZ9lw11funsRnXLgiFg5Rwsg7mFn7dItWEmC-GWXDmtViBiw1KYXRDvjiutCH3s32c4r2kyPD10nx86gKJxZJWeJMVAfXaTRJVMlkBDHRajnbgbaQXd1s7JKwyNMZVxf64jzNBjyrhdCPZJk8npT8Ubb-OKkhsHGIq2zn9soSWjKqcmV9nsclfu6hFEnQlnUi77tBHKLROr8baKtikIlyYVqvOencSVUwSi~tU2Yq4DE3zhHyt9oVhIFwPcxAmS8M8d245IgP4Oehq2FUHEPyxExXdlVW6iZdRSas0SojaIv3ksehA3EH-8IMraM1RQGixX~iXhGZj6OPPtg__'
16-
}
17-
/>
18-
19-
<Text>김댕댕</Text>
20-
<Flex justify="flex-start">
21-
<Text>경력 5년</Text>,<Text>30세</Text>,<Text>남성</Text>
22-
</Flex>
23-
<Flex direction="column">
24-
{['반려견 스타일리스트', '펫테이너'].map((item, idx) => (
25-
<Flex key={idx} justify="flex-start">
26-
<Text>{item}</Text>
27-
<Approve width={11} height={10} />
28-
</Flex>
29-
))}
38+
<Container
39+
version={version}
40+
onClick={moveToPortfolio}
41+
clickable={version === 'vertical'}
42+
direction={version === 'horizontal' ? 'row' : 'column'}
43+
align={version === 'horizontal' ? 'center' : 'flex-start'}
44+
gap={version === 'horizontal' ? 16 : 8}
45+
padding={padding}
46+
>
47+
<ImageWrapper version={version}>
48+
<DesignerImg
49+
version={version}
50+
src={imageUrl}
51+
alt={`${name}'s profile`}
52+
/>
53+
</ImageWrapper>
54+
55+
<Flex direction="column" align="flex-start" justify="flex-start" gap={8}>
56+
<Text typo="Title3">{name}</Text>
57+
58+
<Text
59+
typo="Caption4"
60+
colorCode={theme.palette.Gray400}
61+
>{`경력 ${experience}년, ${age}세, ${gender}`}</Text>
62+
63+
<Flex direction="column" gap={8}>
64+
{roles.map((item, idx) => (
65+
<Role key={idx}>
66+
<Text typo="Caption3" colorCode={theme.palette.Link}>
67+
{item}
68+
</Text>
69+
<Approve width={11} height={10} />
70+
</Role>
71+
))}
72+
</Flex>
3073
</Flex>
31-
</Flex>
74+
</Container>
3275
);
3376
};
3477

35-
const DesignerImg = styled.img`
36-
display: flex;
37-
width: 160px;
38-
height: 160px;
39-
border-radius: 8px;
78+
const Container = styled(Flex)<{
79+
version: 'vertical' | 'horizontal';
80+
clickable: boolean;
81+
}>`
82+
cursor: ${({ clickable }) => (clickable ? 'pointer' : 'default')};
83+
`;
84+
85+
const DesignerImg = styled.img<{ version: 'vertical' | 'horizontal' }>`
86+
width: ${({ version }) => (version === 'horizontal' ? '124px' : '160px')};
87+
height: ${({ version }) => (version === 'horizontal' ? '124px' : '160px')};
88+
border-radius: ${({ version }) =>
89+
version === 'horizontal' ? '99px' : '8px'};
4090
object-fit: cover;
4191
`;
92+
93+
const ImageWrapper = styled.div<{ version: 'vertical' | 'horizontal' }>`
94+
display: flex;
95+
align-items: center;
96+
justify-content: center;
97+
flex-shrink: 0;
98+
`;
99+
100+
// 역할 태그 스타일
101+
const Role = styled(Flex)`
102+
justify-content: flex-start;
103+
align-items: center;
104+
gap: 8px;
105+
`;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { useNavigate } from 'react-router-dom';
2+
3+
import { Flex } from '@duri-fe/ui';
4+
import styled from '@emotion/styled';
5+
6+
interface PortfolioPhotosProps {
7+
portfolios: { id: number; src: string }[];
8+
designerId: string | number;
9+
}
10+
11+
export const PortfolioPhotos = ({
12+
portfolios,
13+
designerId,
14+
}: PortfolioPhotosProps) => {
15+
const navigate = useNavigate();
16+
17+
const moveToProfolioDetail = (id: number) => {
18+
navigate(`/portfolio/${designerId}/${id}`);
19+
};
20+
return (
21+
<Flex>
22+
<PhotoGrid>
23+
{portfolios.map((item, index) => (
24+
<PortfolioInsideImg
25+
key={item.id}
26+
src={item.src}
27+
alt={`Porfolio ${index + 1}`}
28+
onClick={() => moveToProfolioDetail(item.id)}
29+
/>
30+
))}
31+
</PhotoGrid>
32+
</Flex>
33+
);
34+
};
35+
36+
const PhotoGrid = styled.div`
37+
display: grid;
38+
grid-template-columns: repeat(3, 1fr);
39+
gap: 3px;
40+
`;
41+
42+
const PortfolioInsideImg = styled.img`
43+
width: 120px;
44+
height: 120px;
45+
object-fit: cover;
46+
`;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { useNavigate } from 'react-router-dom';
2+
3+
import {
4+
Button,
5+
HeightFitFlex,
6+
NextArrow,
7+
RelativeFlex,
8+
SendColor,
9+
Text,
10+
theme,
11+
WidthFitFlex,
12+
} from '@duri-fe/ui';
13+
import styled from '@emotion/styled';
14+
15+
export const SendRequestQBox = () => {
16+
const navigate = useNavigate();
17+
const moveToShopRequest = () => {
18+
navigate('/shop/request');
19+
};
20+
return (
21+
<RelativeFlex
22+
height={500}
23+
direction="column"
24+
justify="flex-start"
25+
padding="54px 0 56px 0"
26+
>
27+
<SendColor width={55} />
28+
<Text
29+
typo="Title1"
30+
margin="55px 0 0 0"
31+
colorCode={theme.palette.Normal700}
32+
>
33+
견적 요청서를 전송하시겠습니까?
34+
</Text>
35+
<Text typo="Body3" colorCode={theme.palette.Gray300} margin="14px 0 0 0">
36+
선택한 샵에 요청서를 전송합니다.
37+
</Text>
38+
39+
<HeightFitFlex
40+
direction="column"
41+
align="flex-start"
42+
padding="58px 24px 0 28px"
43+
gap={24}
44+
>
45+
<Text typo="Title3">요청서 선택</Text>
46+
<HeightFitFlex justify="space-between">
47+
<Text typo="Title3">작성한 요청서가 없습니다.</Text>
48+
<WidthFitFlex onClick={moveToShopRequest}>
49+
<Text typo="Label3" colorCode={theme.palette.Gray300}>
50+
작성하러가기
51+
</Text>
52+
<NextArrow width={23} color={theme.palette.Gray300} />
53+
</WidthFitFlex>
54+
</HeightFitFlex>
55+
</HeightFitFlex>
56+
<AbsoluteBtnWrapper gap={8} padding="0 20px">
57+
<FlexBtn flex="136" bg={theme.palette.Gray20}>
58+
<Text typo="Body3">취소</Text>
59+
</FlexBtn>
60+
<FlexBtn flex="191" bg={theme.palette.Gray200}>
61+
<Text typo="Body3" colorCode={theme.palette.White}>
62+
확인
63+
</Text>
64+
</FlexBtn>
65+
</AbsoluteBtnWrapper>
66+
</RelativeFlex>
67+
);
68+
};
69+
const AbsoluteBtnWrapper = styled(HeightFitFlex)`
70+
position: absolute;
71+
bottom: 0;
72+
`;
73+
74+
const FlexBtn = styled(Button)<{ flex: string }>`
75+
border-radius: 8px;
76+
flex: ${({ flex }) => flex};
77+
`;

0 commit comments

Comments
 (0)