Skip to content

Commit

Permalink
๐Ÿ’„ ํ—ค๋” ๋„ค๋น„ ํ‘ธํ„ฐ ๋””์ž์ธ ์ ์šฉ (#124)
Browse files Browse the repository at this point in the history
* fix: dot_fill, dot_empty๋ฅผ SVG๋กœ ์ˆ˜์ •

* design: Header ๋””์ž์ธ ์ ์šฉ

* design: ๋„ค๋น„๋ฐ” ๋””์ž์ธ ์ ์šฉ, ๋ฆฌํŒฉํ„ฐ๋ง

* design: ํ‘ธํ„ฐ ๋””์ž์ธ ์ ์šฉ

* fix: ๋„ค๋น„๋ฐ” ์ ๊ณผ ํ…์ŠคํŠธ ๋ฏธ์„ธ์กฐ์ •
  • Loading branch information
yeolyi authored Feb 8, 2024
1 parent 5830ccb commit efe55ce
Show file tree
Hide file tree
Showing 14 changed files with 295 additions and 271 deletions.
1 change: 1 addition & 0 deletions .eslintcache
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"/Users/seongyeolyi/Developer/csereal-web/lint-staged.config.js":"1","/Users/seongyeolyi/Developer/csereal-web/app/[locale]/reservations/privacy-policy/page.tsx":"2","/Users/seongyeolyi/Developer/csereal-web/components/layout/pageLayout/PageTitle.tsx":"3"},{"size":149,"mtime":1707396207012,"results":"4","hashOfConfig":"5"},{"size":3003,"mtime":1707396228182,"results":"6","hashOfConfig":"5"},{"size":2893,"mtime":1707396207012,"results":"7","hashOfConfig":"5"},{"filePath":"8","messages":"9","suppressedMessages":"10","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"vi4zds",{"filePath":"11","messages":"12","suppressedMessages":"13","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"14","messages":"15","suppressedMessages":"16","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/Users/seongyeolyi/Developer/csereal-web/lint-staged.config.js",[],[],"/Users/seongyeolyi/Developer/csereal-web/app/[locale]/reservations/privacy-policy/page.tsx",[],[],"/Users/seongyeolyi/Developer/csereal-web/components/layout/pageLayout/PageTitle.tsx",[],[]]
82 changes: 42 additions & 40 deletions components/layout/footer/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,49 +18,58 @@ import {
snucomLink,
snuEngLink,
snuLink,
contactPath,
directionsPath,
privacyPath,
} from '@/constants/footer';

import useModal from '@/hooks/useModal';

import { contact, directions } from '@/types/page';
import useFooterDesignMode, { FooterMode } from './useFooterToDesignMode';

import { getPath } from '@/utils/page';
export default function Footer() {
const mode = useFooterDesignMode();

// TODO: ๊ฐœ์ธ์ •๋ณด์ฒ˜๋ฆฌ๋ฐฉ์นจ ๋งํฌ
const privacyPath = '/404';
const contactPath = getPath(contact);
const directionsPath = getPath(directions);
const topBg = mode === 'light' ? 'bg-neutral-50' : 'bg-neutral-900';
const bottomBg = mode === 'light' ? 'bg-neutral-100' : 'bg-[rgb(30,30,30)]';

export default function Footer() {
return (
<footer className="z-30">
<FooterTop />
<FooterBottom />
<footer>
<div className={`${topBg} px-[3.75rem] py-10 flex`}>
<LinkGroup groupName="About" links={aboutLinks} width="w-[7.5rem]" mode={mode} />
<LinkGroup groupName="Resources" links={resourcesLinks} width="w-[8.25rem]" mode={mode} />
<LinkGroup groupName="Research" links={researchLinks} width="w-[9rem]" mode={mode} />
<LinkGroup groupName="More" links={moreLinks} width="w-[8rem]" mode={mode} />
</div>
<div className={`${bottomBg} px-[3.75rem] py-8 flex justify-between items-center`}>
<FooterBottomLeft />
<FooterBottomRight />
</div>
</footer>
);
}

function FooterTop() {
type LinkGroupProps = {
groupName: string;
links: FooterLink[];
width: string;
mode: FooterMode;
};

function LinkGroup({ groupName, links, width, mode }: LinkGroupProps) {
const t = useTranslations('Footer');

return (
<div className="bg-neutral-900 px-[3.75rem] py-10 flex gap-8">
<LinkGroup groupName={t('About')} links={aboutLinks} />
<LinkGroup groupName={t('Resources')} links={resourcesLinks} />
<LinkGroup groupName={t('Research')} links={researchLinks} />
<LinkGroup groupName={t('More')} links={moreLinks} />
</div>
);
}
const titleColor = mode === 'light' ? 'text-neutral-600' : 'text-white';

function LinkGroup({ groupName, links }: { groupName: string; links: FooterLink[] }) {
const t = useTranslations('Footer');
return (
<section>
<h3 className={`text-white text-xs font-medium mb-[.625rem]`}>{groupName}</h3>
<ul className="text-neutral-500 text-[.6875rem] font-normal tracking-[.0125rem]">
<section className={width}>
<h3 className={`${titleColor} text-[0.9375rem] font-medium mb-[.44rem] tracking-[0.025rem]`}>
{t(groupName)}
</h3>

<ul className="text-neutral-500 text-sm font-normal flex flex-col gap-[0.63rem]">
{links.map((link, i) => (
<li key={i} className="mb-2">
<li key={i}>
<Link href={link.href}>{t(link.title)}</Link>
</li>
))}
Expand All @@ -69,30 +78,23 @@ function LinkGroup({ groupName, links }: { groupName: string; links: FooterLink[
);
}

function FooterBottom() {
return (
<div className="bg-neutral-800 px-[3.75rem] py-8 flex justify-between items-center">
<FooterBottomLeft />
<FooterBottomRight />
</div>
);
}

function FooterBottomLeft() {
const { openModal } = useModal();
const t = useTranslations('Footer');

return (
<div className="text-neutral-500 text-[.6875rem] tracking-[.01125rem]">
<div className="flex [&>a]:font-bold [&>a]:font-noto gap-1">
<div className="text-neutral-500 text-sm">
<div className="flex [&>a]:font-bold gap-[1ch]">
<Link href={privacyPath}>{t('๊ฐœ์ธ์ •๋ณด์ฒ˜๋ฆฌ๋ฐฉ์นจ')}</Link>
<span>|</span>
<Link href={contactPath}>{t('ํ•™๋ถ€ ์—ฐ๋ฝ์ฒ˜')}</Link>
<span>|</span>
<Link href={directionsPath}>{t('์ฐพ์•„์˜ค์‹œ๋Š” ๊ธธ')}</Link>
</div>
<address className="not-italic mb-4">{t('address')}</address>
<p className="font-normal">

<address className="not-italic mb-[1.37rem]">{t('address')}</address>

<p>
Powered by{' '}
<span
className="cursor-pointer hover:underline"
Expand All @@ -109,7 +111,7 @@ function FooterBottomLeft() {

function FooterBottomRight() {
return (
<div className="flex items-end gap-7">
<div className="flex items-center gap-7">
<Link href={snucomLink}>
<SnucomIcon />
</Link>
Expand Down
12 changes: 12 additions & 0 deletions components/layout/footer/useFooterToDesignMode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import useCurrentSegmentNode from '@/hooks/useCurrentSegmentNode';

import { main } from '@/types/page';

export type FooterMode = 'light' | 'dark';

// TODO: ํŽ˜์ด์ง€๋ณ„ ๋ชจ๋“œ ์ ์šฉํ•˜๊ธฐ
export default function useFooterDesignMode(): FooterMode {
const node = useCurrentSegmentNode();
if (node === main) return 'dark';
else return 'light';
}
72 changes: 29 additions & 43 deletions components/layout/header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
'use client';
'use-client';

import { usePathname, useRouter, useSearchParams } from 'next/navigation';
import { useTranslations } from 'next-intl';
import Link from 'next-intl/link';

import { BASE_URL } from '@/apis';
import { useSessionContext } from '@/contexts/SessionContext';
import HeaderLogo from '@/public/image/header_logo.svg';
import HeaderLogo from '@/public/image/header/header_logo.svg';

import useLanguage from '@/hooks/useLanguage';

import HeaderSearchBar from './HeaderSearchBar';

Expand All @@ -17,9 +18,7 @@ export default function Header() {
const goToMainPage = () => (window.location.href = '/');

return (
<header
className={`top-0 bg-[#1f2021] px-[3.75rem] pt-[40px] pb-8 flex w-full justify-between gap-4`}
>
<header className={`bg-[#1f2021] px-[3.75rem] pt-12 pb-[2.44rem] flex justify-between`}>
<div onClick={goToMainPage} className="cursor-pointer">
<HeaderLogo />
</div>
Expand All @@ -37,30 +36,31 @@ function HeaderRight() {
const langButtonText = isEnglish ? 'ํ•œ๊ตญ์–ด' : 'ENG';

return (
<div className="flex flex-col gap-4 items-end flex-grow">
<div className="font-yoon text-xs font-normal flex gap-3 text-white">
{user ? (
<div className="flex flex-col justify-between gap-[0.94rem] items-end">
<div className="font-yoon text-xs font-normal flex items-center gap-3 text-white">
{user?.isStaff && (
<>
{user.isStaff && (
<>
<Link href={'/admin'} className="hover:text-main-orange">
๊ด€๋ฆฌ์ž ๋ฉ”๋‰ด <div className=""></div>
</Link>
<span>|</span>
</>
)}
<a href={LOGOUT_URL} className="hover:text-main-orange">
{t('๋กœ๊ทธ์•„์›ƒ')}
</a>
<Link href={'/admin'} className="hover:text-main-orange">
๊ด€๋ฆฌ์ž ๋ฉ”๋‰ด <div className=""></div>
</Link>
<Divider />
</>
) : (
<a href={LOGIN_URL} className="hover:text-main-orange">
{t('๋กœ๊ทธ์ธ')}
</a>
)}
<span>|</span>

<button onClick={changeLanguage} className="hover:text-main-orange">
{/* prefetch๋ฅผ ๋ง‰๊ธฐ ์œ„ํ•ด Link๊ฐ€ ์•„๋‹Œ anchor๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. */}
<a
href={user ? LOGOUT_URL : LOGIN_URL}
className="hover:text-main-orange text-sm font-normal"
>
{t(user ? '๋กœ๊ทธ์•„์›ƒ' : '๋กœ๊ทธ์ธ')}
</a>

<Divider />

<button
onClick={changeLanguage}
className="hover:text-main-orange text-sm font-normal tracking-[0.025rem]"
>
{langButtonText}
</button>
</div>
Expand All @@ -69,20 +69,6 @@ function HeaderRight() {
);
}

const useLanguage = () => {
const router = useRouter();
const path = usePathname();
const searchParams = useSearchParams();

const isEnglish = path.startsWith('/en');

const changeLanguage = () => {
if (isEnglish) {
router.push(`/ko${path.slice(3)}?${searchParams}`);
} else {
router.push(`/en${path}?${searchParams}`);
}
};

return { isEnglish, changeLanguage };
};
function Divider() {
return <div className="bg-white w-[0.03125rem] h-3" />;
}
49 changes: 25 additions & 24 deletions components/layout/header/HeaderSearchBar.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,43 @@
'use client';

import { useRouter } from 'next/navigation';
import { useState, ChangeEventHandler, FormEventHandler } from 'react';
import { useState } from 'react';

export default function HeaderSearchBar() {
const [text, setText] = useState('');
const router = useRouter();

const handleChange: ChangeEventHandler<HTMLInputElement> = (e) => {
setText(e.target.value);
};

const searchText: FormEventHandler<HTMLFormElement> = (e) => {
e.preventDefault();
const query = text.trim();
if (query) {
router.push(`/search?query=${query}`);
}
};
const { text, setText, searchText } = useSearch();

return (
<form
className="flex justify-center outline-none rounded-[.0625rem] min-w-[8rem] w-[13.5rem] h-[1.875rem] bg-neutral-200 pr-2"
onSubmit={searchText}
className="flex justify-center outline-none rounded-[.0625rem] w-[13.5rem] h-[1.875rem] bg-neutral-200 pr-2"
onSubmit={(e) => {
e.preventDefault();
searchText();
}}
>
<input
type="text"
id="search"
className="outline-none font-yoon text-xs w-full px-2 bg-transparent autofill-bg-neutral-200"
className="outline-none text-xs w-full px-2 bg-transparent autofill-bg-neutral-200"
value={text}
onChange={handleChange}
onChange={(e) => setText(e.target.value)}
/>
<button className="flex justify-center items-center w-fit">
{/* TODO: ๋‹๋ณด๊ธฐ ํ˜ธ๋ฒ„ ์ƒ‰ */}
<span className="material-symbols-rounded text-[1.25rem] font-light text-[#1f2021]">
search
</span>
<button className="material-symbols-rounded text-[1.25rem] text-neutral-800 hover:text-neutral-500">
search
</button>
</form>
);
}

function useSearch() {
const [text, setText] = useState('');
const router = useRouter();

const searchText = () => {
const query = text.trim();
if (query) {
router.push(`/search?query=${query}`);
}
};

return { text, setText, searchText };
}
19 changes: 8 additions & 11 deletions components/layout/navbar/NavbarDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,28 @@ import { SegmentNode } from '@/types/page';
import NavTreeRow from './NavtreeRow';

export default function NavbarDetail({ segmentNode }: { segmentNode: SegmentNode }) {
const currentSegmentNode = useCurrentSegmentNode();
const curNode = useCurrentSegmentNode();

return (
<div className="bg-[#1f2021] backdrop-blur-[2px] pt-[8.8125rem] pl-[14.75rem] w-[33rem] overflow-x-hidden overflow-y-scroll no-scrollbar absolute top-0 bottom-0 z-40">
<NavTree node={segmentNode} currentNode={currentSegmentNode} isRoot />
// ๋„ค๋น„๋ฐ”๊ฐ€ ํŽผ์ณ์งˆ ๋•Œ ๋’ท๋ฐฐ๊ฒฝ์ด ์ผ์‹œ์ ์œผ๋กœ ๋ณด์ด๋Š” ๋ฌธ์ œ๋ฅผ ๋ง‰๊ธฐ ์œ„ํ•ด ํ™”๋ฉด ์™ผ์ชฝ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
<div className="bg-[#1f2021] backdrop-blur-[2px] pt-[8.8125rem] pl-[14.75rem] w-[33rem] overflow-y-scroll no-scrollbar absolute left-0 top-0 bottom-0 z-40">
<NavTree node={segmentNode} curNode={curNode} isRoot />
</div>
);
}

interface NavTreeProps {
// ์ˆœํšŒ์ค‘์ธ ํŠธ๋ฆฌ์˜ ๋ฃจํŠธ ๋…ธ๋“œ
node: SegmentNode;
// ํ˜„์žฌ URL๋กœ๋ถ€ํ„ฐ ์–ป์–ด๋‚ธ ๋…ธ๋“œ
currentNode: SegmentNode;
curNode: SegmentNode;
isRoot?: boolean;
}

function NavTree({ node: segmentNode, isRoot = false, currentNode }: NavTreeProps) {
function NavTree({ node, isRoot = false, curNode }: NavTreeProps) {
return (
<>
{!isRoot && <NavTreeRow segmentNode={segmentNode} highlight={currentNode === segmentNode} />}
{!isRoot && <NavTreeRow segmentNode={node} highlight={curNode === node} />}
<div className="ml-5">
{segmentNode.children?.map((child, i) => (
<NavTree key={i} node={child} currentNode={currentNode} />
))}
{node.children?.map((child, i) => <NavTree key={i} node={child} curNode={curNode} />)}
</div>
</>
);
Expand Down
Loading

0 comments on commit efe55ce

Please sign in to comment.