Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 5 additions & 136 deletions src/app/(marketing)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,142 +1,11 @@
"use client";
import { LandingHeroSection } from "@/components/landing/LandingHeroSection";

import { SignupGroupButton } from "@/components/SiginupGroupButton";
import { BackButton } from "@/shared/BackButton";
import { Button } from "@/shared/button";
import { FeatureButton } from "@/shared/FeatureButton";
import { Icon } from "@/shared/Icon";
import { Input } from "@/shared/input";
import { SelectModuleCard } from "@/shared/SelectModuleCard";
import { SpecialFeatureCard } from "@/shared/SpecialFeatureCard";
import { InputStatus } from "@/types/input";
import { useState } from "react";
export const revalidate = 21600;

export default function Home() {
const [email, setEmail] = useState("");
const [status, setStatus] = useState<InputStatus>("default");
const [isReady, setIsReady] = useState(false);

return (
<div className="flex flex-col justify-center items-center gap-8">
{/* Hero CTA */}
<div className="flex gap-3">
<Button preset="hero" pill>
<span className="inline-flex items-center gap-4">
<Icon name="monitor" />
<span>Desktop</span>
</span>
</Button>
<Button preset="hero" pill>
<span className="inline-flex items-center gap-4">
<Icon name="laptop" />
<span>Mac</span>
</span>
</Button>
<Button preset="hero" pill>
<span className="inline-flex items-center gap-4">
<Icon name="smartphone" />
<span>iOS</span>
</span>
</Button>
</div>

<FeatureButton
icon={<Icon name="calendar" size={19} />}
title="일간"
description="였늘의 일정과 ν•  일을 ν•œλˆˆμ—"
/>

<SpecialFeatureCard
icon={<Icon name="calendar" size={23} />}
title="슀마트 μŠ€μΌ€μ€„λ§"
description="AIκ°€ μΆ”μ²œν•˜λŠ” 졜적의 일정 배치둜 νš¨μœ¨μ„±μ„ κ·ΉλŒ€ν™”ν•˜μ„Έμš”."
/>

<Button preset="auth" color="black">
둜그인 ν•˜κΈ°
</Button>

<section className="space-y-2">
<h2 className="t-18-b">μ—λŸ¬ μƒνƒœ</h2>
<div className="space-y-1">
<label htmlFor="email" className="t-14-m text-muted-foreground">
이메일
</label>

{/** status: "default" | "error" */}
<Input
id="email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
status={status} // βœ… cva와 1:1
placeholder="이메일을 μž…λ ₯ν•˜μ„Έμš”"
aria-describedby={status === "error" ? "email-error" : undefined}
onFocus={() => setStatus("default")}
/>

{status === "error" && (
<p id="email-error" className="t-12-m text-destructive">
이메일 ν˜•μ‹μ„ ν™•μΈν•˜μ„Έμš”.
</p>
)}

<div className="flex gap-2 pt-2">
<button
type="button"
onClick={() => setStatus((v: InputStatus) => (v === "error" ? "default" : "error"))}
className="rounded-md border px-3 py-1 text-sm"
>
μ—λŸ¬ ν† κΈ€
</button>
<button
type="button"
onClick={() => {
setEmail("");
setStatus("default");
}}
className="rounded-md border px-3 py-1 text-sm"
>
κ°’ μ΄ˆκΈ°ν™”
</button>
</div>
</div>
</section>

<SignupGroupButton />

<BackButton>이전</BackButton>

<Button
preset="cta"
disabled={!isReady} // falseλ©΄ ν™œμ„±, trueλ©΄ λΉ„ν™œμ„±
onClick={() => alert("λ‹€μŒ λ‹¨κ³„λ‘œ 이동")}
>
선택 μ™„λ£Œ
</Button>

<Button preset="cta" disabled={false} onClick={() => setIsReady((prev) => !prev)}>
{isReady ? "선택 ν•΄μ œ" : "ν™œμ„±ν™” ν† κΈ€"}
</Button>

<SelectModuleCard
kind="module" // "module" | "design"
title="일간 ν”Œλž˜λ„ˆ"
subtitle="Daily Intelligence"
description="ν•˜λ£¨λ₯Ό μ²΄κ³„μ μœΌλ‘œ κ΄€λ¦¬ν•˜μ„Έμš”"
imageSrc="/images/daily-planner.png"
onClick={() => console.log("일간 ν”Œλž˜λ„ˆ 클릭")}
/>

<SelectModuleCard
kind="design" // "module" | "design"
title="일간 ν”Œλž˜λ„ˆ"
subtitle="Daily Intelligence"
subtitleState="noSelect"
description="ν•˜λ£¨λ₯Ό μ²΄κ³„μ μœΌλ‘œ κ΄€λ¦¬ν•˜μ„Έμš”"
imageSrc="/images/daily-planner.png"
onClick={() => console.log("일간 ν”Œλž˜λ„ˆ 클릭")}
/>
</div>
<>
<LandingHeroSection />
</>
);
}
23 changes: 19 additions & 4 deletions src/components/landing/LandingFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,26 @@ export function LandingFooter() {
<div
className={cn(
"grid grid-cols-[14rem_14rem] grid-rows-[auto_auto] justify-center items-start gap-10 text-center",
"md:grid-cols-3 md:grid-rows-1 md:justify-between md:text-left",
"md:grid-cols-3 md:grid-rows-1 md:justify-between",
)}
>
{/* μ œν’ˆ 컬럼 */}
<div className="col-span-1 row-start-2 justify-self-center md:row-auto md:justify-self-start">
<div
className={cn(
"col-span-1 row-start-2 justify-self-center",
"md:row-auto md:justify-self-start",
)}
>
<LandingFooterColumn title="μ œν’ˆ" links={productLinks} />
</div>

{/* 둜고 블둝*/}
<div className="col-span-2 row-start-1 flex flex-col items-center gap-4 justify-self-center md:col-span-1 md:row-auto">
<div
className={cn(
"col-span-2 row-start-1 flex flex-col items-center gap-4 justify-self-center",
"md:col-span-1 md:row-auto",
)}
>
<Link
href="/"
aria-label="MyPlanMate ν™ˆμœΌλ‘œ 이동"
Expand All @@ -62,7 +72,12 @@ export function LandingFooter() {
</div>

{/* 지원 컬럼 */}
<div className="col-span-1 row-start-2 justify-self-center md:row-auto md:justify-self-end">
<div
className={cn(
"col-span-1 row-start-2 justify-self-center",
"md:row-auto md:justify-self-end",
)}
>
<LandingFooterColumn title="지원" links={supportLinks} />
</div>
</div>
Expand Down
27 changes: 27 additions & 0 deletions src/components/landing/LandingHeroAnimation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"use client";

import { cn } from "@/lib/utils";

export function LandingHeroAnimation() {
return (
<div className="relative">
<div
className={cn(
"group relative overflow-hidden rounded-2xl bg-[var(--color-white)]",
"shadow-[0_12px_40px_rgba(0,0,0,0.12)]",
"aspect-video w-full",
)}
>
<video
className="h-full w-full object-cover"
src="/videos/landing-hero.mp4"
autoPlay
Comment on lines +15 to +18

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Supply landing hero video file

The hero animation component references /videos/landing-hero.mp4, but no file with that path exists under public/ in this repository. At runtime the <video> tag will 404 and render empty, so users never see the intended animation. Either add the video asset to public/videos/landing-hero.mp4 or adjust the source to an existing file.

Useful? React with πŸ‘Β / πŸ‘Ž.

loop
muted
playsInline
aria-label="PlanMate 데일리 ν”Œλž˜λ„ˆ μ‚¬μš© μ˜ˆμ‹œ μ˜μƒ"
/>
</div>
</div>
);
}
35 changes: 35 additions & 0 deletions src/components/landing/LandingHeroCtas.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { cn } from "@/lib/utils";
import { Button } from "@/shared/button";
import { Icon } from "@/shared/Icon";
import Link from "next/link";

export function LandingHeroCtas() {
return (
<div className={cn("flex flex-col gap-12 mt-20", "md:flex-row items-center gap-8 mt-10")}>
<Link href="/login">
<Button preset="hero" pill>
<span className="inline-flex items-center gap-4">
<Icon name="monitor" />
<span>Desktop</span>
</span>
</Button>
</Link>
Comment on lines +9 to +16

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove button nested inside Link in hero CTAs

Each CTA wraps the shared Button component in next/link. Because Button renders a <button> element, the output becomes <a><button>…</button></a>, which is invalid HTML and can block keyboard interaction in some browsers and screen readers. Consider rendering the link as the button (<Button asChild><Link … /></Button>) or styling the Link directly so only a single interactive element is produced.

Useful? React with πŸ‘Β / πŸ‘Ž.

<Link href="/login">
<Button preset="hero" pill>
<span className="inline-flex items-center gap-4">
<Icon name="laptop" />
<span>Mac</span>
</span>
</Button>
</Link>
<Link href="/login">
<Button preset="hero" pill>
<span className="inline-flex items-center gap-4">
<Icon name="smartphone" />
<span>iOS</span>
</span>
</Button>
</Link>
</div>
);
}
25 changes: 25 additions & 0 deletions src/components/landing/LandingHeroSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { LandingHeroAnimation } from "@/components/landing/LandingHeroAnimation";
import { LandingHeroCtas } from "@/components/landing/LandingHeroCtas";
import { LandingHeroTitle } from "@/components/landing/LandingHeroTitle";
import { cn } from "@/lib/utils";
import { LandingHeroSectionProps } from "@/types/landing";

export function LandingHeroSection({ className }: LandingHeroSectionProps) {
return (
<section
id="landing-hero"
aria-labelledby="landing-hero-title"
className={cn(
"grid gap-10",
"md:grid-cols-[minmax(0,1.1fr)_minmax(0,0.9fr)] md:items-center",
className,
)}
>
<div className="space-y-8">
<LandingHeroTitle />
<LandingHeroCtas />
</div>
<LandingHeroAnimation />
</section>
);
}
19 changes: 19 additions & 0 deletions src/components/landing/LandingHeroTitle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { cn } from "@/lib/utils";

export function LandingHeroTitle() {
return (
<header className="space-y-8">
<h1
id="landing-hero-title"
className={cn("t-40-b leading-tight text-[var(--color-gray-900)]", "md:t-58-b")}
>
λ‚˜λ§Œμ˜ 데일리 ν”Œλž˜λ„ˆ
<br />
PlanMate
</h1>
<p className={cn("t-14-m text-[var(--color-gray-600)]", "md:t-18-m")}>
μ›ν•˜λŠ” κΈ°λŠ₯만 골라 μ“°λŠ” λ§žμΆ€ν˜• 일정 관리 μ„œλΉ„μŠ€μž…λ‹ˆλ‹€.
</p>
</header>
);
}
2 changes: 1 addition & 1 deletion src/components/landing/LandingMainSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export function LandingMainSection({ children, className }: LandingMainSectionPr
return (
<main
id="landing-main"
className={cn("mx-auto w-full max-w-[128rem] px-6 py-15", "space-y-[10rem]", className)}
className={cn("mx-auto w-full max-w-[128rem] px-6 mt-70", "space-y-[10rem]", className)}
>
{children}
</main>
Expand Down
4 changes: 2 additions & 2 deletions src/components/landing/LandingNavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export function LandingNavBar() {
type="button"
className={cn(
"cursor-pointer t-14-m text-[var(--color-gray-600)] hover:text-[var(--color-gray-900)]",
"md: t-16-m",
"md:t-16-m",
)}
aria-label="μ–Έμ–΄ μ „ν™˜"
>
Expand All @@ -39,7 +39,7 @@ export function LandingNavBar() {
href="/login"
className={cn(
"t-14-m text-[var(--color-gray-600)] hover:text-[var(--color-gray-900)]",
"md: t-16-m",
"md:t-16-m",
)}
aria-label="λ‘œκ·ΈμΈνŽ˜μ΄μ§€λ‘œ 이동"
>
Expand Down
Loading