Skip to content

Commit eebf537

Browse files
committed
[ChoosePage] feat: 마크업
1 parent 64a4bac commit eebf537

File tree

11 files changed

+245
-29
lines changed

11 files changed

+245
-29
lines changed

src/App.tsx

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,7 @@
1-
import { Outlet, RouterProvider, createBrowserRouter } from "react-router-dom";
2-
import LandingPage from "@Pages/landing/Landing.page";
1+
import Router from "./Router";
32

43
function App() {
5-
const router = createBrowserRouter([
6-
{
7-
path: "/",
8-
element: <MobileLayout />,
9-
children: [{ path: "/", element: <LandingPage /> }],
10-
},
11-
]);
12-
13-
return <RouterProvider router={router} />;
14-
}
15-
16-
function MobileLayout() {
17-
return (
18-
<div className="w-screen bg-white h-screen flex justify-center">
19-
<section className="w-[500px] h-full bg-[#1A1A1A] overflow-auto">
20-
<Outlet />
21-
</section>
22-
</div>
23-
);
4+
return <Router />;
245
}
256

267
export default App;

src/Router.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import ChoosePage from "@Pages/choose/Choose.page";
2+
import LandingPage from "@Pages/landing/Landing.page";
3+
import { Outlet, RouterProvider, createBrowserRouter } from "react-router-dom";
4+
5+
export default function Router() {
6+
const router = createBrowserRouter([
7+
{
8+
path: "/",
9+
element: <MobileLayout />,
10+
children: [
11+
{ path: "/", element: <LandingPage /> },
12+
{ path: "/choose", element: <ChoosePage /> },
13+
],
14+
},
15+
]);
16+
17+
return <RouterProvider router={router} />;
18+
}
19+
20+
function MobileLayout() {
21+
return (
22+
<div className="w-screen bg-white h-screen flex justify-center">
23+
<section className="w-[500px] h-full bg-[#1A1A1A] overflow-auto">
24+
<Outlet />
25+
</section>
26+
</div>
27+
);
28+
}

src/assets/images/sample-image1.png

69.5 KB
Loading

src/assets/images/sample-image2.png

56.5 KB
Loading

src/assets/images/sample-image3.png

60.3 KB
Loading

src/assets/images/sample-image4.png

60.3 KB
Loading

src/components/Card/Card.tsx

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { mergeClassName } from "@Utils/styleExtension";
2+
import { ComponentProps } from "react";
3+
4+
export interface CardProps extends ComponentProps<"button"> {
5+
label: string;
6+
description: string;
7+
src: string;
8+
}
9+
10+
export default function Card({
11+
label,
12+
description,
13+
className,
14+
src,
15+
...restProps
16+
}: CardProps) {
17+
const { disabled } = restProps;
18+
19+
return (
20+
<button
21+
className={mergeClassName(
22+
"flex rounded-[14px] overflow-hidden relative aspect-[160/240]",
23+
className
24+
)}
25+
{...restProps}
26+
>
27+
<img className="w-full" src={src} />
28+
<div className="absolute bottom-[12px] left-[12px] right-[19px] flex flex-col gap-[8px] items-start text-left">
29+
<div className="py-[4px] px-[8px] rounded-full bg-[#FCD55F] font-yClover font-bold text-[#191919]">
30+
{label}
31+
</div>
32+
<div className="font-yClover font-bold text-white leading-5">
33+
{description}
34+
</div>
35+
</div>
36+
{disabled && (
37+
<div className="absolute w-full h-full bg-[rgba(0,0,0,0.7)] flex items-center justify-center">
38+
<span className="font-yClover text-[#DCDCDC] font-bold">
39+
준비 중이다냥
40+
</span>
41+
</div>
42+
)}
43+
</button>
44+
);
45+
}

src/pages/choose/Choose.page.tsx

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import Card, { CardProps } from "@Components/Card/Card";
2+
import Base64 from "@Constant/base64";
3+
import { createRepeatBackground, mergeClassName } from "@Utils/styleExtension";
4+
import SampleImage1 from "@Assets/images/sample-image1.png";
5+
import SampleImage2 from "@Assets/images/sample-image2.png";
6+
import SampleImage3 from "@Assets/images/sample-image3.png";
7+
import SampleImage4 from "@Assets/images/sample-image4.png";
8+
9+
export default function ChoosePage() {
10+
return (
11+
<div className="flex flex-col h-full">
12+
<Top />
13+
<div className="flex flex-col px-[24px] overflow-y-auto gap-[32px]">
14+
<Middle />
15+
<Content />
16+
</div>
17+
</div>
18+
);
19+
}
20+
21+
function Top() {
22+
return (
23+
<div className=" pt-[24px] pb-[8px] pr-[16px] flex gap-[26px]">
24+
<div
25+
className="w-full"
26+
style={{
27+
backgroundImage: createRepeatBackground(
28+
Base64.rectange,
29+
17,
30+
20,
31+
24,
32+
"row"
33+
),
34+
backgroundPositionX: "left",
35+
backgroundRepeat: "repeat-x",
36+
backgroundPositionY: "center",
37+
transform: "scale(-1,-1)",
38+
}}
39+
/>
40+
<button className="min-w-[16px]">
41+
<IconMenu />
42+
</button>
43+
</div>
44+
);
45+
}
46+
47+
function IconMenu() {
48+
return (
49+
<svg
50+
xmlns="http://www.w3.org/2000/svg"
51+
width="32"
52+
height="32"
53+
viewBox="0 0 32 32"
54+
fill="none"
55+
>
56+
<path
57+
fillRule="evenodd"
58+
clipRule="evenodd"
59+
d="M4.80005 8.00002C4.80005 7.57568 4.96862 7.16871 5.26868 6.86865C5.56874 6.5686 5.9757 6.40002 6.40005 6.40002H25.6C26.0244 6.40002 26.4314 6.5686 26.7314 6.86865C27.0315 7.16871 27.2001 7.57568 27.2001 8.00002C27.2001 8.42437 27.0315 8.83134 26.7314 9.1314C26.4314 9.43145 26.0244 9.60002 25.6 9.60002H6.40005C5.9757 9.60002 5.56874 9.43145 5.26868 9.1314C4.96862 8.83134 4.80005 8.42437 4.80005 8.00002ZM4.80005 16C4.80005 15.5757 4.96862 15.1687 5.26868 14.8687C5.56874 14.5686 5.9757 14.4 6.40005 14.4H25.6C26.0244 14.4 26.4314 14.5686 26.7314 14.8687C27.0315 15.1687 27.2001 15.5757 27.2001 16C27.2001 16.4244 27.0315 16.8313 26.7314 17.1314C26.4314 17.4315 26.0244 17.6 25.6 17.6H6.40005C5.9757 17.6 5.56874 17.4315 5.26868 17.1314C4.96862 16.8313 4.80005 16.4244 4.80005 16ZM4.80005 24C4.80005 23.5757 4.96862 23.1687 5.26868 22.8687C5.56874 22.5686 5.9757 22.4 6.40005 22.4H25.6C26.0244 22.4 26.4314 22.5686 26.7314 22.8687C27.0315 23.1687 27.2001 23.5757 27.2001 24C27.2001 24.4244 27.0315 24.8313 26.7314 25.1314C26.4314 25.4315 26.0244 25.6 25.6 25.6H6.40005C5.9757 25.6 5.56874 25.4315 5.26868 25.1314C4.96862 24.8313 4.80005 24.4244 4.80005 24Z"
60+
fill="white"
61+
/>
62+
</svg>
63+
);
64+
}
65+
66+
function Middle() {
67+
return (
68+
<div className="mt-[16px] flex flex-row gap-[24px]">
69+
<div className="w-[80px] h-[80px] rounded-full bg-[#DAD9D9]">
70+
<img />
71+
</div>
72+
<div className="flex flex-col justify-center gap-[8px] font-yClover font-bold text-[#FCD55F]">
73+
<span className="text-[24px]">@ catsch</span>
74+
<span className="text-[16px]">너도 찍어볼래냥?</span>
75+
</div>
76+
</div>
77+
);
78+
}
79+
80+
function Content() {
81+
const items: [CardProps[], CardProps[]] = [
82+
[
83+
{
84+
label: "생일 축하",
85+
description: "템플릿이름 길이가 길어질 경우 2줄",
86+
src: SampleImage1,
87+
},
88+
{
89+
label: "생일 축하",
90+
description: "템플릿 이름",
91+
src: SampleImage3,
92+
disabled: true,
93+
},
94+
{
95+
label: "생일 축하",
96+
description: "템플릿이름 길이가 길어질 경우 2줄",
97+
src: SampleImage4,
98+
disabled: true,
99+
},
100+
],
101+
[
102+
{
103+
label: "인절미",
104+
description: "템플릿 이름",
105+
src: SampleImage2,
106+
},
107+
{
108+
label: "키치",
109+
description: "템플릿 이름",
110+
src: SampleImage4,
111+
disabled: true,
112+
},
113+
{
114+
label: "인절미",
115+
description: "템플릿 이름",
116+
src: SampleImage2,
117+
disabled: true,
118+
},
119+
],
120+
];
121+
122+
return (
123+
<div className="flex flex-row gap-[8px]">
124+
{items.map((item, idx) => {
125+
const margin = idx === 1 ? "mt-[88px]" : "";
126+
return (
127+
<div
128+
key={idx}
129+
className={mergeClassName("flex flex-col gap-[8px] w-full", margin)}
130+
>
131+
{item.map((props, idx2) => {
132+
return <Card key={idx2} {...props} />;
133+
})}
134+
</div>
135+
);
136+
})}
137+
</div>
138+
);
139+
}

src/pages/landing/Landing.page.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ import { createRepeatBackground } from "@Utils/styleExtension";
44
import { useNavigate } from "react-router-dom";
55

66
export default function LandingPage() {
7+
const navigate = useNavigate();
8+
9+
const goNext = () => {
10+
navigate("choose");
11+
};
12+
713
return (
814
<div className="flex flex-col h-full">
915
<div className="h-full px-[16px] flex w-full justify-between gap-[9px]">
@@ -12,7 +18,11 @@ export default function LandingPage() {
1218
<MovieSide />
1319
</div>
1420
<div className="pt-[28px] pb-[32px] flex items-center justify-center">
15-
<Button variant="primary" className="w-[324px] h-[56px]">
21+
<Button
22+
variant="primary"
23+
className="w-[324px] h-[56px]"
24+
onClick={goNext}
25+
>
1626
시작해보자냥
1727
</Button>
1828
</div>
@@ -25,7 +35,13 @@ function MovieSide() {
2535
<div
2636
className="min-w-[32px] h-full"
2737
style={{
28-
backgroundImage: createRepeatBackground(Base64.rectange, 32, 24, 28),
38+
backgroundImage: createRepeatBackground(
39+
Base64.rectange,
40+
32,
41+
24,
42+
28,
43+
"col"
44+
),
2945
backgroundRepeat: "repeat-y",
3046
backgroundPositionY: "-15px",
3147
}}

src/utils/styleExtension.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ export function createRepeatBackground(
66
base64: string,
77
width: number,
88
height: number,
9-
gap: number
9+
gap: number,
10+
direction: "col" | "row"
1011
) {
11-
const innerText = `data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${width}" height="${
12-
height + gap
13-
}"><image width="${
14-
width - 1
15-
}" height="${gap}" xlink:href="${base64}" /></svg>`;
12+
const outWidth = direction === "col" ? width : width + gap;
13+
const outHeight = direction === "col" ? height + gap : height;
14+
15+
const innerWidth = direction === "col" ? width - 1 : gap;
16+
const innerHeight = direction === "col" ? gap : height - 1;
17+
const innerText = `data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${outWidth}" height="${outHeight}"><image width="${innerWidth}" height="${innerHeight}" xlink:href="${base64}" /></svg>`;
1618

1719
return `url('${innerText}')`;
1820
}

tailwind.config.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ export default {
88
fontFamily: {
99
yClover: ['"Y Clover"'],
1010
},
11+
backgroundColor: {
12+
test: "white",
13+
test2: "blue",
14+
test3: "green",
15+
},
1116
backgroundImage: {
1217
"movie-side": "url('@Assets/images/movie-side.png')",
1318
},

0 commit comments

Comments
 (0)