-
Notifications
You must be signed in to change notification settings - Fork 0
Feature/CDP-162-LandingLayout #45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
ede064f
27153f1
6ba6340
033a4f1
8099e63
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| import { useCurrentYear } from "@/hooks/useCurrentYear"; | ||
|
|
||
| export function LandingCopyright() { | ||
| const year = useCurrentYear(); | ||
|
|
||
| return ( | ||
| <p className="text-center text-sm text-[var(--color-gray-500)]"> | ||
| ยฉ {year} MyPlanMate. All rights reserved. | ||
| </p> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| import { FooterLink } from "@/types/landing"; | ||
| import Image from "next/image"; | ||
| import Link from "next/link"; | ||
| import { LandingCopyright } from "./LandingCopyright"; | ||
| import { LandingFooterColumn } from "./LandingFooterColumn"; | ||
|
|
||
| export function LandingFooter() { | ||
| const productLinks: FooterLink[] = [ | ||
| { label: "๊ธฐ๋ฅ ์๊ฐ", href: "/features" }, | ||
| { label: "์๊ธ์ ", href: "/pricing" }, | ||
| { label: "์ ๋ฐ์ดํธ", href: "/changelog" }, | ||
| ]; | ||
|
|
||
| const supportLinks: FooterLink[] = [ | ||
| { label: "FAQ", href: "/faq" }, | ||
| { label: "๋ฌธ์ํ๊ธฐ", href: "/support" }, | ||
| { label: "๊ฐ์ธ์ ๋ณด์ฒ๋ฆฌ๋ฐฉ์นจ", href: "/privacy" }, | ||
| ]; | ||
|
|
||
| return ( | ||
| <footer | ||
| role="contentinfo" | ||
| className="border-t border-[var(--color-gray-100)] bg-[var(--color-gray-50)] text-[var(--color-gray-600)]" | ||
| > | ||
| <div className="mx-auto flex max-w-[128rem] flex-col gap-10 px-12 py-12"> | ||
| {/* ์๋จ: ์ข์ฐ ์ปฌ๋ผ + ์ค์ ๋ก๊ณ */} | ||
| <div className="flex flex-row items-center gap-10 justify-between"> | ||
| {/* ์ข์ธก: ์ ํ ๊ด๋ จ ๋งํฌ */} | ||
| <LandingFooterColumn title="์ ํ" links={productLinks} /> | ||
|
|
||
| {/* ์ค์: ๋ธ๋๋ ๋ก๊ณ /๋ฌธ๊ตฌ */} | ||
| <div className="flex flex-col items-center gap-5"> | ||
| <Link href="/" aria-label="MyPlanMate ํ์ผ๋ก ์ด๋" className="flex items-center gap-2"> | ||
| <Image | ||
| src="/images/logo.png" | ||
| alt="MyPlanMate ๋ก๊ณ " | ||
| width={150} | ||
| height={150} | ||
| className="object-contain select-none" | ||
| draggable={false} | ||
| /> | ||
| </Link> | ||
| <p className="t-14-m text-[var(--color-gray-500)]"> | ||
| ํ๋ฃจ๋ฅผ ์ ๋ฆฌํ๋ ๋๋ง์ ํ๋๋, MyPlanMate | ||
| </p> | ||
| </div> | ||
|
|
||
| {/* ์ฐ์ธก: ์ง์/์ ์ฑ ๋งํฌ */} | ||
| <LandingFooterColumn title="์ง์" links={supportLinks} /> | ||
| </div> | ||
|
|
||
| {/* ํ๋จ: ๊ตฌ๋ถ์ + ์ ์๊ถ */} | ||
| <div className="mt-4 border-t border-[var(--color-gray-100)] pt-6"> | ||
| <div className="flex flex-row items-center justify-between gap-4 "> | ||
| <LandingCopyright /> | ||
| <p className="t-12-r text-[var(--color-gray-400)]"> | ||
| ์๋น์ค ๊ด๋ จ ์๋ด ๋ฐ ๊ณต์ง์ฌํญ์ ํํ์ด์ง๋ฅผ ํตํด ์ ๊ณต๋ฉ๋๋ค. | ||
| </p> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </footer> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| import { LandingFooterColumnProps } from "@/types/landing"; | ||
| import Link from "next/link"; | ||
|
|
||
| export function LandingFooterColumn({ title, links }: LandingFooterColumnProps) { | ||
| return ( | ||
| <div className="flex flex-col gap-3"> | ||
| <h3 className="t-16-m text-[var(--color-gray-900)] text-center">{title}</h3> | ||
| <ul className="flex flex-col gap-3 text-center"> | ||
| {links.map((link) => ( | ||
| <li key={link.label}> | ||
| <Link | ||
| href={link.href} | ||
| className="t-14-m text-[var(--color-gray-500)] | ||
| hover:text-[var(--color-gray-900)] hover:border-b hover:border-[var(--color-gray-900)]" | ||
| > | ||
| {link.label} | ||
| </Link> | ||
| </li> | ||
| ))} | ||
| </ul> | ||
| </div> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| import { cn } from "@/lib/utils"; | ||
| import { LandingNavBar } from "./LandingNavBar"; | ||
|
|
||
| export function LandingHeader() { | ||
| return ( | ||
| <header className={cn("w-full")} role="banner"> | ||
| <LandingNavBar /> | ||
| </header> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| // src/components/landing/LandingNavBar.tsx | ||
| import { cn } from "@/lib/utils"; | ||
| import Image from "next/image"; | ||
| import Link from "next/link"; | ||
|
|
||
| export function LandingNavBar() { | ||
| return ( | ||
| <nav | ||
| className={cn("mx-auto flex h-[9.6rem] max-w-[128rem] items-center justify-between px-12")} | ||
| aria-label="Global navigation" | ||
| > | ||
| {/* ์ข์ธก: ๋ก๊ณ (์ด๋ฏธ์ง) */} | ||
| <Link href="/" aria-label="MyPlanMate ํ์ผ๋ก ์ด๋"> | ||
| <Image | ||
| src="/images/logo.png" | ||
| alt="MyPlanMate ๋ก๊ณ " | ||
| width={150} | ||
|
Comment on lines
+13
to
+17
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The new logo asset was added as Useful? React with ๐ย / ๐. |
||
| height={150} | ||
| className="object-contain select-none" | ||
| draggable={false} | ||
| /> | ||
| </Link> | ||
|
|
||
| {/* ์ฐ์ธก: ์ธ์ด ํ ๊ธ + ๋ก๊ทธ์ธ */} | ||
| <div className="flex items-center gap-12"> | ||
| <button | ||
| type="button" | ||
| className="t-16-m text-[var(--color-gray-600)] hover:text-[var(--color-gray-900)] cursor-pointer" | ||
| aria-label="์ธ์ด ์ ํ" | ||
| > | ||
| ํ๊ตญ์ด | ||
| </button> | ||
| <Link | ||
| href="/login" | ||
| className="t-16-m text-[var(--color-gray-600)] hover:text-[var(--color-gray-900)]" | ||
| aria-label="๋ก๊ทธ์ธํ์ด์ง๋ก ์ด๋" | ||
| > | ||
| ๋ก๊ทธ์ธ | ||
| </Link> | ||
| </div> | ||
| </nav> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| export function useCurrentYear(): number { | ||
| return new Date().getFullYear(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The footer renders the same logo using
src="/images/logo.png", but the only image committed ispublic/images/Logo.png. Because Next.js serves files case-sensitively in production, the footerโs logo will fail to load and display as a broken image. Align the string casing or rename the asset so the served file matches the requested path.Useful? React with ๐ย / ๐.