Skip to content

Commit 6da0d97

Browse files
committed
feat: 즉시구매, 가격 제안, 판매 취소, 받은 가격 제안 버튼 추가
1 parent 583b1e3 commit 6da0d97

File tree

2 files changed

+129
-42
lines changed

2 files changed

+129
-42
lines changed

src/pages/roomDetailPage/components/roomNavBar/RoomNavBar.style.ts

+56-13
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
1-
import styled from "styled-components";
1+
import IconHeart from "@assets/icons/ic_heart-fill.svg?react";
2+
import { hexToRgba } from "@utils/hexTorgba.ts";
3+
import styled, { css, DefaultTheme } from "styled-components";
24

35
export { Text } from "@pages/roomDetailPage/RoomDetail.style";
46

57
export const Wrapper = styled.section`
68
width: 100%;
79
max-width: 768px;
8-
height: 60px;
910
10-
padding: 1.2rem 1.25rem;
11+
padding: 1.25rem 1rem;
1112
position: fixed;
1213
bottom: 0;
1314
background-color: ${({ theme }) => theme.color.white};
1415
1516
display: flex;
1617
align-items: center;
18+
gap: 1rem;
1719
1820
box-shadow: 0 0 0.4rem rgba(5, 44, 82, 0.1);
1921
-webkit-clip-path: inset(-0.4rem 0 0 0);
@@ -36,17 +38,58 @@ export const Row2 = styled(Flex)`
3638
gap: 0.5rem;
3739
`;
3840

39-
export const Button = styled.button<{ $status: boolean }>`
40-
${({ theme }) => theme.typo.button2}
41-
padding: 0.7rem 3rem;
42-
color: ${({ theme }) => theme.color.white};
41+
export type TButtonVariant = keyof ReturnType<typeof variantStyles>;
42+
43+
const variantStyles = (theme: DefaultTheme) => ({
44+
fill: css`
45+
background-color: ${theme.color.percentOrange};
46+
color: ${theme.color.white};
47+
&:hover {background-color: ${({ theme }) => theme.color.darkOrange};
48+
`,
49+
outline: css`
50+
border: 1px solid ${theme.color.percentOrange};
51+
color: ${theme.color.percentOrange};
52+
&:hover {background-color: ${({ theme }) =>
53+
hexToRgba(theme.color.percentOrange, 0.1)};
54+
`,
55+
});
56+
57+
export const Button = styled.button.withConfig({
58+
shouldForwardProp: (prop) => prop !== "variant",
59+
})<{ variant?: TButtonVariant }>`
60+
${({ theme }) => theme.typo.button3}
61+
padding: 0.7rem 1rem;
4362
border-radius: 8px;
44-
background-color: ${({ $status, theme }) =>
45-
$status ? theme.color.percentOrange : theme.color.greyScale5};
46-
transition: background-color 0.2s ease-in;
4763
48-
&:hover {
49-
background-color: ${({ $status, theme }) =>
50-
$status ? theme.color.darkOrange : theme.color.greyScale4};
64+
display: flex;
65+
flex: 1;
66+
align-items: center;
67+
justify-content: center;
68+
69+
transition:
70+
background-color,
71+
border-color 0.2s ease-in;
72+
73+
${({ variant, theme }) =>
74+
variant ? variantStyles(theme)[variant] : variantStyles(theme)["fill"]}
75+
76+
&:disabled {
77+
background-color: ${({ theme }) => theme.color.greyScale5};
78+
color: ${({ theme }) => theme.color.white};
79+
80+
&:hover {
81+
background-color: ${({ theme }) => theme.color.greyScale4};
82+
}
5183
}
5284
`;
85+
86+
export const ButtonWrapper = styled.div`
87+
display: flex;
88+
gap: 8px;
89+
width: 100%;
90+
`;
91+
92+
export const Heart = styled(IconHeart)`
93+
display: flex;
94+
align-items: center;
95+
`;

src/pages/roomDetailPage/components/roomNavBar/RoomNavBar.tsx

+73-29
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,45 @@
1+
import IconInfoMark from "@assets/icons/ic_question-mark.svg?react";
2+
import { PATH } from "@constants/path";
3+
import useToastConfig from "@hooks/common/useToastConfig";
4+
import { ReactElement, useEffect, useState } from "react";
5+
import { useNavigate } from "react-router-dom";
6+
7+
import * as S from "./RoomNavBar.style";
8+
9+
import type { TButtonVariant } from "./RoomNavBar.style";
10+
import type { RoomNavBarData } from "@type/room";
11+
112
import { ResponseError } from "@/components/error/Error";
213
import { STATUS_CODE } from "@/constants/api";
314
import { useStockQuery } from "@/hooks/api/useStockQuery";
415
import useAuthStore from "@/store/authStore";
5-
import { PATH } from "@constants/path";
6-
import useToastConfig from "@hooks/common/useToastConfig";
716

8-
import type { RoomNavBarData } from "@type/room";
9-
import { useEffect, useState } from "react";
10-
import { useNavigate } from "react-router-dom";
17+
interface ButtonProps {
18+
text: ReactElement;
19+
action: () => void;
20+
status: boolean;
21+
variant?: TButtonVariant;
22+
}
1123

12-
import * as S from "./RoomNavBar.style";
24+
const Button = ({ text, action, status, variant }: ButtonProps) => {
25+
return (
26+
<S.Button
27+
type="button"
28+
variant={variant}
29+
disabled={!status}
30+
onClick={action}
31+
>
32+
{text}
33+
</S.Button>
34+
);
35+
};
1336

1437
interface RoomNavBarProps {
1538
room: RoomNavBarData;
1639
roomId: string;
17-
discount: string;
1840
}
1941

20-
const RoomNavBar = ({ room, roomId, discount }: RoomNavBarProps) => {
42+
const RoomNavBar = ({ room, roomId }: RoomNavBarProps) => {
2143
const navigate = useNavigate();
2244
const [error, setError] = useState<unknown>(null);
2345
const isLoggedIn = useAuthStore((state) => state.isLoggedIn);
@@ -61,6 +83,36 @@ const RoomNavBar = ({ room, roomId, discount }: RoomNavBarProps) => {
6183
}
6284
};
6385

86+
const buttonConfig = {
87+
propose: {
88+
buyer: {
89+
text: (
90+
<>
91+
가격 제안
92+
<IconInfoMark />
93+
</>
94+
),
95+
action: () => console.log("가격 제안 페이지로 이동"),
96+
},
97+
seller: {
98+
text: "받은 가격 제안",
99+
action: () => console.log("받은 가격 제안으로 이동"),
100+
},
101+
},
102+
purchase: {
103+
buyer: {
104+
text: "즉시 구매",
105+
action: handlePurchaseClick,
106+
},
107+
seller: {
108+
text: "판매 취소",
109+
action: () => console.log("판매 취소 로직"),
110+
},
111+
},
112+
};
113+
114+
const userType = room.isSeller ? "seller" : "buyer";
115+
64116
useEffect(() => {
65117
if (error) {
66118
throw error;
@@ -69,27 +121,19 @@ const RoomNavBar = ({ room, roomId, discount }: RoomNavBarProps) => {
69121

70122
return (
71123
<S.Wrapper>
72-
<S.ColWrapper>
73-
<S.Text variant="body3" color="greyScale3">
74-
<s>{room.originalPrice.toLocaleString()}</s>
75-
</S.Text>
76-
<S.Row2>
77-
<S.Text variant="title2" color="percentBlue">
78-
{discount}%
79-
</S.Text>
80-
<S.Text variant="title2">
81-
{room.sellingPrice.toLocaleString()}
82-
</S.Text>
83-
</S.Row2>
84-
</S.ColWrapper>
85-
<S.Button
86-
type="button"
87-
$status={room.saleStatus}
88-
aria-label="구매하기"
89-
onClick={handlePurchaseClick}
90-
>
91-
구매하기
92-
</S.Button>
124+
<S.Heart />
125+
<S.ButtonWrapper>
126+
<Button
127+
{...buttonConfig.propose[userType]}
128+
status={room.saleStatus}
129+
variant="outline"
130+
/>
131+
<Button
132+
{...buttonConfig.purchase[userType]}
133+
status={room.saleStatus}
134+
variant="fill"
135+
/>
136+
</S.ButtonWrapper>
93137
</S.Wrapper>
94138
);
95139
};

0 commit comments

Comments
 (0)