-
Notifications
You must be signed in to change notification settings - Fork 3
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
Changes from all commits
99797cf
4ab3eac
2c232ae
b3e1d22
81f6568
e29b797
1c21750
b21db95
054826c
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,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
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. 이거 어떤 역할을 하나요?? 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. 스크롤 위치에 따라서 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
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. 조건부 렌더링으로 처리하기보다 asChild는 덕분에 알았습니다. 👍 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. 사용하는 쪽에서 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. 음.. 글로 쓰기가 어렵네요 시간이 늦어서 머리가 굳었나 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. 좋습니다! |
||
); | ||
} | ||
|
||
export default Header; |
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; |
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; |
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; |
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 }; |
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 }; |
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; |
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.
주엽님도 이거 없앴군요.. ㅋㅋㅋㅋ
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.
넵 ㅜㅜ