Skip to content
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

[Feat] 홈, 회원가입, 로그인 페이지 작성 #57

Merged
merged 9 commits into from
Nov 11, 2024
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
1 change: 1 addition & 0 deletions apps/client/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ module.exports = {
'import/prefer-default-export': 0,
'react/require-default-props': 0,
'react/jsx-props-no-spreading': 0,
'react/prop-types': 0,
Copy link
Collaborator

Choose a reason for hiding this comment

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

주엽님도 이거 없앴군요.. ㅋㅋㅋㅋ

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

넵 ㅜㅜ

},
};
1 change: 1 addition & 0 deletions apps/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
"dependencies": {
"@radix-ui/react-icons": "^1.3.1",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@tanstack/react-router": "^1.79.0",
"class-variance-authority": "^0.7.0",
Expand Down
74 changes: 74 additions & 0 deletions apps/client/src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { useEffect, useState } from 'react';
import { Link, useRouterState } from '@tanstack/react-router';
import { Harmony } from '@/components/logo';
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';

interface HeaderProps {
className?: string;
}

function Header({ className }: HeaderProps) {
const router = useRouterState();
const { pathname } = router.location;
const [isTop, setIsTop] = useState(true);

useEffect(() => {
const handleScroll = () => {
const currentScrollY = window.scrollY;
setIsTop(currentScrollY <= 10);
};

handleScroll();
window.addEventListener('scroll', handleScroll, { passive: true });

return () => window.removeEventListener('scroll', handleScroll);
}, []);
Comment on lines +16 to +26
Copy link
Collaborator

Choose a reason for hiding this comment

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

이거 어떤 역할을 하나요??

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

스크롤 위치에 따라서 Header 의 아래에 border 및 shadow 를 보여줄 지 정하기 위해 사용됩니다.
현재 로그인/회원가입 페이지에서는 확인하실 수 있습니다~


const isLoginPage = pathname === '/login';
const isSignupPage = pathname === '/signup';

const headerClasses = cn(
'fixed top-0 w-full h-16',
'flex items-center justify-between',
'px-6 bg-white dark:bg-black',
'text-black dark:text-white',
'transition-all duration-200',
{
'border-b border-gray-200 dark:border-gray-800 shadow-sm': !isTop,
},
className
);

return (
<header className={headerClasses}>
{/* Logo Section */}
<div className="flex items-center space-x-4">
<Link to="/" className="transition-opacity hover:opacity-80">
<Harmony size={32} />
</Link>
</div>

{/* Navigation Buttons */}
<nav className="flex items-center space-x-3">
{!isLoginPage && (
<Button variant={isSignupPage ? 'outline' : 'ghost'} asChild>
<Link to="/login" className="hover:text-primary font-medium transition-colors">
로그인
</Link>
</Button>
)}

{!isSignupPage && (
<Button variant="outline" asChild>
<Link to="/signup" className="hover:text-primary font-medium transition-colors">
회원가입
</Link>
</Button>
)}
</nav>
</header>
Comment on lines +44 to +70
Copy link
Collaborator

Choose a reason for hiding this comment

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

조건부 렌더링으로 처리하기보다
사용하는 쪽에서 주입하는 쪽이 더 좋을 것 같아요!

asChild는 덕분에 알았습니다. 👍

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

사용하는 쪽에서 path 를 주입하신다는 말씀이실까요?

Copy link
Collaborator

Choose a reason for hiding this comment

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

음.. 글로 쓰기가 어렵네요 시간이 늦어서 머리가 굳었나
낼 말로 이야기할게요 ㅋㅋㅋㅋ

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

좋습니다!

);
}

export default Header;
28 changes: 28 additions & 0 deletions apps/client/src/components/logo/GitHub.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
function Github({
size = 24,
color = 'currentColor',
className = '',
}: {
size?: number;
color?: string;
className?: string;
}) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width={size}
height={size}
viewBox="0 0 24 24"
fill="none"
stroke={color}
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className={`${className}`}
>
<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22" />
</svg>
);
}

export default Github;
62 changes: 62 additions & 0 deletions apps/client/src/components/logo/Harmony.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
function Harmony({ size = 24 }: { size?: number }) {
return (
<svg xmlns="http://www.w3.org/2000/svg" width={size * 4} height={size} viewBox="0 0 1000 250">
<g>
<path
className="fill-primary"
d="M143.8,146.67l-.07-.17c-1.55-4.18-7.11-13.97-26.91-32.64-6.08-5.73-11.91-10.79-15.74-14.02-.74-.63-1.82-1.54-2.89-2.43-19.35,15.86-41.09,37.26-45.51,49.08l-.07.17c-1.39,3.47-2.09,7.16-2.09,10.96,0,15.03,11.1,27.25,24.73,27.26,5.61,0,10.95-2.61,15.29-6.39l-5.57,13.66h26.43l-5.57-13.66c4.34,3.78,9.68,6.39,15.29,6.39,13.64,0,24.73-12.23,24.73-27.26,0-3.8-.7-7.47-2.08-10.95Z"
/>
<g>
<path
className="fill-black dark:fill-white"
d="M179.23,78.67h17.2v-21.98c0-17.71-13.59-32.23-30.91-33.74v29.68c0,8.69-7.07,15.75-15.75,15.75s-15.75-7.07-15.75-15.75v-29.82H62.41v29.82c0,8.69-7.07,15.75-15.75,15.75s-15.75-7.07-15.75-15.75v-29.68C13.59,24.45,0,38.98,0,56.68v21.98h179.23Z"
/>
<path
className="fill-black dark:fill-white"
d="M46.66,60.56c4.38,0,7.93-3.55,7.93-7.93V19.81c0-4.38-3.55-7.93-7.93-7.93s-7.93,3.55-7.93,7.93v32.81c0,4.38,3.55,7.93,7.93,7.93Z"
/>
<path
className="fill-black dark:fill-white"
d="M149.77,60.56c4.38,0,7.93-3.55,7.93-7.93V19.81c0-4.38-3.55-7.93-7.93-7.93s-7.93,3.55-7.93,7.93v32.81c0,4.38,3.55,7.93,7.93,7.93Z"
/>
</g>
<path
className="fill-black dark:fill-white"
d="M179.23,78.67h0v115.55c0,9.21-7.47,16.68-16.68,16.68H33.87c-9.21,0-16.68-7.47-16.68-16.68v-115.55h0s-17.2,0-17.2,0v115.55C0,212.93,15.17,228.1,33.87,228.1h128.68c18.71,0,33.87-15.17,33.87-33.87v-115.55h-17.2Z"
/>
</g>
<g>
<path
className="fill-black dark:fill-white"
d="M330.03,198.35v-64.7h-51.27v64.7h-29.17V51.44h29.17v56.92h51.27v-56.92h29.17v146.9h-29.17Z"
/>
<path
className="fill-black dark:fill-white"
d="M403.39,198.35c-21.21,0-29.17-7.95-29.17-25.63v-14.5c0-17.68,7.95-25.63,29.17-25.63h38.01v-4.42c0-5.3-2.65-7.96-7.95-7.96h-52.5v-22.98h57.81c21.21,0,29.17,7.95,29.17,25.63v56.04c0,14.14-5.3,19.45-19.45,19.45h-45.08ZM441.4,153.8h-32.7c-5.3,0-7.95,2.65-7.95,7.95v5.66c0,5.3,2.65,7.96,7.95,7.96h27.4c4.42,0,5.3-.88,5.3-5.3v-16.26Z"
/>
<path
className="fill-black dark:fill-white"
d="M482.06,198.35v-63.29c0-25.63,12.73-37.83,39.78-37.83h14.14v22.98h-12.55c-9.9,0-14.85,4.24-14.85,15.91v62.23h-26.52Z"
/>
<path
className="fill-black dark:fill-white"
d="M650.88,198.35v-62.23c0-11.67-4.95-15.91-14.85-15.91h-11.67v78.14h-26.52v-78.14h-21.21c-4.42,0-5.3.88-5.3,5.3v72.83h-26.52v-81.67c0-14.14,5.3-19.45,19.45-19.45h73.36c27.05,0,39.78,12.2,39.78,37.83v63.29h-26.52Z"
/>
<path
className="fill-black dark:fill-white"
d="M729.54,199.05c-27.05,0-39.78-12.2-39.78-37.83v-26.87c0-25.63,12.73-37.83,39.78-37.83h17.68c27.05,0,39.77,12.2,39.77,37.83v26.87c0,25.63-12.73,37.83-39.77,37.83h-17.68ZM760.48,135.41c0-11.67-4.95-15.91-14.85-15.91h-14.5c-9.9,0-14.85,4.24-14.85,15.91v24.75c0,11.67,4.95,15.91,14.85,15.91h14.5c9.9,0,14.85-4.24,14.85-15.91v-24.75Z"
/>
<path
className="fill-black dark:fill-white"
d="M866.54,198.35v-62.23c0-11.67-4.95-15.91-14.85-15.91h-20.51c-4.42,0-5.3.88-5.3,5.3v72.83h-26.52v-81.67c0-14.14,5.3-19.45,19.45-19.45h34.47c27.05,0,39.78,12.2,39.78,37.83v63.29h-26.52Z"
/>
<path
className="fill-black dark:fill-white"
d="M915.15,238.12v-22.98h53.03c4.42,0,5.3-.88,5.3-5.3v-11.49h-38.01c-21.21,0-29.17-7.95-29.17-25.63v-75.48h26.52v70.18c0,5.3,2.65,7.96,7.96,7.96h32.7v-78.14h26.52v121.45c0,14.14-5.3,19.45-19.45,19.45h-65.41Z"
/>
</g>
</svg>
);
}

export default Harmony;
30 changes: 30 additions & 0 deletions apps/client/src/components/logo/HarmonyIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
function HarmonyIcon({ size = 24 }: { size?: number }) {
return (
<svg xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 600 600">
<path
className="fill-primary"
d="M426.51,374.05l-.18-.48c-4.31-11.59-19.73-38.77-74.66-90.56-16.87-15.91-33.06-29.93-43.67-38.9-2.05-1.74-5.04-4.26-8.02-6.75-53.68,44-114.02,103.4-126.29,136.2l-.18.48c-3.84,9.63-5.79,19.86-5.79,30.41,0,41.7,30.79,75.63,68.64,75.63,15.57,0,30.39-7.23,42.42-17.72l-15.44,37.9h73.35l-15.44-37.9c12.03,10.49,26.86,17.72,42.43,17.72,37.85,0,68.64-33.93,68.64-75.63,0-10.55-1.93-20.73-5.79-30.39Z"
/>
<g>
<path
className="fill-black dark:fill-white"
d="M524.82,185.34h47.72v-61.01c0-49.14-37.71-89.44-85.76-93.62v82.36c0,24.1-19.61,43.71-43.71,43.71s-43.71-19.61-43.71-43.71V30.33h-198.72v82.75c0,24.1-19.61,43.71-43.71,43.71s-43.71-19.61-43.71-43.71V30.71c-48.05,4.18-85.76,44.48-85.76,93.62v61.01h497.36Z"
/>
<path
className="fill-black dark:fill-white"
d="M156.93,135.1c12.16,0,22.02-9.86,22.02-22.02V22.02c0-12.16-9.86-22.02-22.02-22.02s-22.02,9.86-22.02,22.02v91.06c0,12.16,9.86,22.02,22.02,22.02Z"
/>
<path
className="fill-black dark:fill-white"
d="M443.07,135.1c12.16,0,22.02-9.86,22.02-22.02V22.02c0-12.16-9.86-22.02-22.02-22.02s-22.02,9.86-22.02,22.02v91.06c0,12.16,9.86,22.02,22.02,22.02Z"
/>
</g>
<path
className="fill-black dark:fill-white"
d="M524.82,185.34h0v320.66c0,25.56-20.72,46.28-46.28,46.28H121.46c-25.56,0-46.28-20.72-46.28-46.28V185.34h0s-47.72,0-47.72,0v320.66c0,51.91,42.08,94,94,94h357.08c51.91,0,94-42.08,94-94V185.34h-47.72Z"
/>
</svg>
);
}

export default HarmonyIcon;
5 changes: 5 additions & 0 deletions apps/client/src/components/logo/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Github from '@/components/logo/GitHub';
import Harmony from '@/components/logo/Harmony';
import HarmonyIcon from '@/components/logo/HarmonyIcon';

export { Harmony, HarmonyIcon, Github };
6 changes: 3 additions & 3 deletions apps/client/src/components/ui/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ const buttonVariants = cva(
{
variants: {
variant: {
default: 'bg-primary text-primary-foreground shadow hover:bg-primary/90',
default: 'bg-primary text-primary-foreground shadow hover:bg-green-700',
destructive: 'bg-destructive text-destructive-foreground shadow hover:bg-destructive/90',
outline:
'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',
'border border-input bg-background shadow-sm hover:bg-black hover:border-white hover:text-white',
secondary: 'bg-secondary text-secondary-foreground shadow hover:bg-secondary/80',
ghost: 'hover:bg-accent hover:text-accent-foreground',
ghost: 'hover:text-primary',
link: 'text-secondary underline-offset-4 hover:underline',
},
size: {
Expand Down
23 changes: 23 additions & 0 deletions apps/client/src/components/ui/input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as React from 'react';

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

const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<'input'>>(
({ className, type, ...props }, ref) => {
return (
<input
type={type}
className={cn(
'border-input file:text-foreground placeholder:text-muted-foreground focus-visible:ring-ring flex h-9 w-full rounded-md border bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
className
)}
ref={ref}
{...props}
/>
);
}
);

Input.displayName = 'Input';

export { Input };
84 changes: 84 additions & 0 deletions apps/client/src/pages/Home.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { Link } from '@tanstack/react-router';
import { Button } from '@/components/ui/button';
import { Github } from '@/components/logo';
import Header from '@/components/Header.tsx';

function Home() {
return (
<div className="flex min-h-screen flex-col">
<Header />

<main className="mt-16 flex-grow bg-white text-black dark:bg-black dark:text-white">
<section className="container mx-auto max-w-6xl from-pink-500 via-red-500 to-yellow-500 px-6 py-20 text-center">
<h1 className="mb-6 text-3xl font-bold md:text-5xl">
<span className="animate-gradient-rotate bg-gradient-conic via-purple-500-500 from-green-500 to-blue-500 bg-clip-text text-transparent">
Plan.
<br />
Collaborate.
<br />
Estimate.
</span>
</h1>
<p className="mb-8 break-keep text-lg text-gray-600 md:text-xl">
Harmony 는 프로젝트 계획부터, 팀원 모두의 생각이 실시간으로 반영되는 협업 플랫폼입니다.
</p>

<div className="col-span-3 flex justify-center">
<Button size="lg" className="rounded-full" asChild>
<Link to="/login">로그인</Link>
</Button>
<Button variant="outline" size="lg" className="ml-4 rounded-full">
데모보기
</Button>
</div>
</section>

<section className="container mx-auto max-w-6xl px-6 py-20">
<div className="grid grid-cols-1 gap-8 break-keep md:grid-cols-3">
<div className="hover:text-primary text-center">
<h2 className="mb-4 text-2xl font-bold">Plan.</h2>
<p>
직관적인 인터페이스로 프로젝트의 일정과 작업을 체계적으로 관리하세요. 팀의 목표와
마일스톤을 명확히 설정하고, 진행 상황을 한눈에 파악할 수 있습니다.
</p>
</div>
<div className="hover:text-primary text-center">
<h2 className="mb-4 text-2xl font-bold">Collaborate.</h2>
<p>
실시간 동시편집으로 팀원들의 아이디어와 업데이트가 즉시 반영됩니다. 시간과 장소에
구애받지 않고, 모든 팀원이 함께 작업할 수 있는 진정한 협업 환경을 제공합니다.
</p>
</div>
<div className="hover:text-primary text-center">
<h2 className="mb-4 text-2xl font-bold">Estimate.</h2>
<p>
플래닝 포커를 통해 팀원들의 다양한 관점을 수렴하고 합리적인 일정을 산출합니다.
실시간 추정 과정을 통해 더 정확하고 투명한 프로젝트 계획을 수립할 수 있습니다.
</p>
</div>
</div>
</section>
</main>

<footer className="bg-black p-5 text-white">
<div className="container mx-auto flex max-w-6xl flex-col items-center justify-between md:flex-row">
<div className="flex items-center space-x-4">
<span>2024 Naver Boostcamp Project</span>
</div>
<div className="mt-4 flex space-x-4 md:mt-0">
<a
target="_blank"
rel="noreferrer"
href="https://github.com/boostcampwm-2024/web06-harmony"
className="hover:text-secondary"
>
<Github size={24} color="currentColor" />
</a>
</div>
</div>
</footer>
</div>
);
}

export default Home;
Loading
Loading