Skip to content

Commit b2c0bf5

Browse files
authored
Merge pull request #95 from SynclyProject/feat/94
Feat/94 랜딩 페이지 UI
2 parents 3962c7c + 4189c1c commit b2c0bf5

77 files changed

Lines changed: 7783 additions & 8 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Syncly/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
"dayjs": "^1.11.13",
3131
"js-cookie": "^3.0.5",
3232
"livekit-client": "^2.15.6",
33+
"lucide-react": "^0.546.0",
34+
"radix-ui": "^1.4.3",
3335
"react": "19.1.1",
3436
"react-dom": "19.1.1",
3537
"react-hook-form": "^7.56.3",

Syncly/public/landing-file.png

639 KB
Loading

Syncly/public/landing-screen.png

397 KB
Loading

Syncly/public/landing-url.png

92 KB
Loading

Syncly/src/App.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { WorkSpaceProvider } from "./context/workSpaceContext";
2323
import OAuthSuccessPage from "./shared/api/common/OAuthSuccessPage";
2424
import { LiveKitProvider } from "./context/LiveKitContext";
2525
import TeamNotePage from "./pages/Team/TeamNotePage";
26+
import PrivacyPolicyPage from "./pages/PrivacyPolicyPage";
2627

2728
const queryClient = new QueryClient();
2829

@@ -120,6 +121,10 @@ const router = createBrowserRouter([
120121
path: "/oauth2/success",
121122
element: <OAuthSuccessPage />,
122123
},
124+
{
125+
path: "privacy-policy",
126+
element: <PrivacyPolicyPage />,
127+
},
123128
],
124129
},
125130
]);

Syncly/src/Layout.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ const RootLayout = () => {
88
location.pathname === "/login" ||
99
location.pathname === "/signup" ||
1010
location.pathname === "/create-pw" ||
11-
location.pathname === "/";
11+
location.pathname === "/" ||
12+
location.pathname === "/privacy-policy";
1213

1314
return (
14-
<div className="flex flex-col h-full overflow-hidden">
15+
<div className="flex flex-col h-full overflow-y-auto">
1516
<TopBar />
16-
<div className="flex h-full overflow-hidden">
17+
<div className="flex h-full overflow-y-auto">
1718
{!hideSidebar && <SideBar />}
1819
<Outlet />
1920
</div>
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import { Check, Circle } from "lucide-react";
2+
import {
3+
Table,
4+
TableBody,
5+
TableCell,
6+
TableHead,
7+
TableHeader,
8+
TableRow,
9+
} from "../Landing/ui/table";
10+
11+
const comparisons = [
12+
{
13+
feature: "실시간 채팅",
14+
slack: true,
15+
around: true,
16+
syncly: true,
17+
},
18+
{
19+
feature: "화상회의",
20+
slack: true,
21+
around: true,
22+
syncly: true,
23+
},
24+
{
25+
feature: "URL 관리",
26+
slack: false,
27+
around: false,
28+
syncly: true,
29+
},
30+
{
31+
feature: "협업 중심",
32+
slack: "채팅 중심",
33+
around: "화면 공유 중심",
34+
syncly: "기록 + 정리 중심 협업",
35+
},
36+
];
37+
38+
function CellContent({ value }: { value: boolean | string }) {
39+
if (value === true) {
40+
return <Check className="h-5 w-5 text-accent mx-auto" />;
41+
}
42+
if (value === false) {
43+
return (
44+
<span className="text-muted-foreground mx-auto block text-center">-</span>
45+
);
46+
}
47+
if (value === "partial") {
48+
return <Circle className="h-5 w-5 text-muted-foreground mx-auto" />;
49+
}
50+
return <span className="text-sm text-muted-foreground">{value}</span>;
51+
}
52+
53+
export function ComparisonTable() {
54+
return (
55+
<section id="comparison" className="py-20 md:py-32 bg-muted/30">
56+
<div className="container">
57+
<div className="mx-auto max-w-4xl">
58+
<div className="text-center mb-12">
59+
<h2 className="text-3xl md:text-4xl font-bold mb-4">
60+
기존 협업툴과는 다릅니다.
61+
</h2>
62+
<p className="text-lg text-muted-foreground">
63+
Syncly만의 차별화된 강점을 확인하세요.
64+
</p>
65+
</div>
66+
67+
<div className="rounded-2xl border border-border bg-card overflow-hidden">
68+
<Table>
69+
<TableHeader>
70+
<TableRow className="hover:bg-transparent">
71+
<TableHead className="w-[200px] font-bold">항목</TableHead>
72+
<TableHead className="text-center font-bold">
73+
SLACK/TEAMS
74+
</TableHead>
75+
<TableHead className="text-center font-bold">
76+
AROUND
77+
</TableHead>
78+
<TableHead className="text-center font-bold bg-accent/5">
79+
SYNCLY
80+
</TableHead>
81+
</TableRow>
82+
</TableHeader>
83+
<TableBody>
84+
{comparisons.map((row, index) => (
85+
<TableRow key={index}>
86+
<TableCell className="font-medium">{row.feature}</TableCell>
87+
<TableCell className="text-center">
88+
<CellContent value={row.slack} />
89+
</TableCell>
90+
<TableCell className="text-center">
91+
<CellContent value={row.around} />
92+
</TableCell>
93+
<TableCell className="text-center bg-accent/5">
94+
<CellContent value={row.syncly} />
95+
</TableCell>
96+
</TableRow>
97+
))}
98+
</TableBody>
99+
</Table>
100+
</div>
101+
</div>
102+
</div>
103+
</section>
104+
);
105+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { Card, CardContent } from "../Landing/ui/card";
2+
import { Bookmark, Video, FolderOpen } from "lucide-react";
3+
4+
const features = [
5+
{
6+
icon: Bookmark,
7+
title: "URL : 원클릭 북마크",
8+
subtitle: "작업중인 링크를 모두 저장하고 한번에 열어보세요",
9+
description:
10+
"여러 개의 URL을 한번에 저장하고, 분류하여 체계적으로 관리합니다.",
11+
image: "/landing-url.png",
12+
},
13+
{
14+
icon: Video,
15+
title: "화면, 음성, 얼굴공유, 채팅, 회의록",
16+
subtitle: "작업중인 파일도 함께 저장하고 관리해보세요",
17+
description:
18+
"회의나 리뷰 중 바로 화면과 파일을 공유하여 즉각적인 협업이 가능합니다.",
19+
image: "/landing-screen.png",
20+
},
21+
{
22+
icon: FolderOpen,
23+
title: "파일 : 통합 파일 드라이브",
24+
subtitle: "한 공간에서 모든 파일을 관리하세요",
25+
description:
26+
"손쉽게 파일을 업로드하고, 폴더별로 깔끔하게 정리할 수 있습니다. ",
27+
image: "/landing-file.png",
28+
},
29+
];
30+
31+
export function FeaturesSection() {
32+
return (
33+
<section id="features" className="py-20 md:py-32 bg-muted/30">
34+
<div className="container">
35+
<div className="grid gap-8 md:gap-12 lg:grid-cols-3">
36+
{features.map((feature, index) => (
37+
<Card
38+
key={index}
39+
className="overflow-hidden border-border/50 hover:border-accent/50 transition-colors"
40+
>
41+
<div className="aspect-video bg-secondary relative overflow-hidden">
42+
<img
43+
src={feature.image || "/placeholder.svg"}
44+
alt={feature.title}
45+
className="object-cover w-full h-full"
46+
/>
47+
</div>
48+
<CardContent className="p-6">
49+
<div className="flex items-center gap-3 mb-3">
50+
<div className="p-2 rounded-lg bg-accent/10">
51+
<feature.icon className="h-5 w-5 text-accent" />
52+
</div>
53+
<h3 className="font-semibold text-lg">{feature.title}</h3>
54+
</div>
55+
{feature.subtitle && (
56+
<p className="text-sm font-medium text-foreground mb-2">
57+
{feature.subtitle}
58+
</p>
59+
)}
60+
<p className="text-sm text-muted-foreground leading-relaxed">
61+
{feature.description}
62+
</p>
63+
</CardContent>
64+
</Card>
65+
))}
66+
</div>
67+
</div>
68+
</section>
69+
);
70+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
export function Footer() {
2+
return (
3+
<footer className="border-t border-border py-12">
4+
<div className="container">
5+
<div className="flex flex-col md:flex-row items-center justify-between gap-4">
6+
<div className="flex items-center gap-2">
7+
<img src="/logo.png" className="h-10 w-10" />
8+
<span className="font-bold">Syncly</span>
9+
</div>
10+
<p className="text-sm text-muted-foreground">
11+
© 2025 Syncly. 모든 권리 보유
12+
</p>
13+
<a
14+
href="/privacy-policy"
15+
className="text-sm text-muted-foreground cursor-pointer"
16+
>
17+
개인정보처리방침
18+
</a>
19+
</div>
20+
</div>
21+
</footer>
22+
);
23+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { Button } from "../Landing/ui/button";
2+
import { Link2 } from "lucide-react";
3+
4+
export function Header() {
5+
return (
6+
<header className="sticky top-0 z-50 w-full border-b border-border/40 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
7+
<div className="container flex h-16 items-center justify-between">
8+
<div className="flex items-center gap-2">
9+
<Link2 className="h-6 w-6" />
10+
<span className="text-xl font-bold">Syncly</span>
11+
</div>
12+
<nav className="hidden md:flex items-center gap-6">
13+
<a
14+
href="#features"
15+
className="text-sm font-medium text-muted-foreground hover:text-foreground transition-colors"
16+
>
17+
기능
18+
</a>
19+
<a
20+
href="#solution"
21+
className="text-sm font-medium text-muted-foreground hover:text-foreground transition-colors"
22+
>
23+
솔루션
24+
</a>
25+
<a
26+
href="#comparison"
27+
className="text-sm font-medium text-muted-foreground hover:text-foreground transition-colors"
28+
>
29+
비교
30+
</a>
31+
</nav>
32+
<Button size="sm">무료로 시작하기</Button>
33+
</div>
34+
</header>
35+
);
36+
}

0 commit comments

Comments
 (0)