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] : 로그인, 회원가입 UI 구현 #6

Merged
merged 14 commits into from
Feb 8, 2025
Binary file added public/images/scenery.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/spotshare-deco.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@
border-color: #999;
}
}
@theme {
--color-primary: rgb(255, 123, 165);
--color-primary-200: rgb(255, 187, 206);
--color-sub: rgb(123, 185, 255);
--color-sub-200: rgb(166, 206, 255);
--color-third: rgb(255, 229, 123);
--color-gray: rgb(153, 153, 153);
--color-gray-600: rgb(130, 130, 130);
}

:root {
--background: #f4f4f4;
Expand Down
13 changes: 13 additions & 0 deletions src/app/join/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { JoinLayout } from "@/widgets/join/ui";
import React from "react";

export default function page() {
return (
<div
className="flex h-screen w-screen items-center justify-center bg-cover bg-center"
style={{ backgroundImage: 'url("/images/scenery.png")' }}
>
<JoinLayout />
</div>
);
}
13 changes: 13 additions & 0 deletions src/app/login/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { LoginLayout } from "@/widgets/login/ui";
import React from "react";

export default function page() {
return (
<div
className="flex h-screen w-screen items-center justify-center bg-cover bg-center"
style={{ backgroundImage: 'url("/images/scenery.png")' }}
>
<LoginLayout />
</div>
);
}
21 changes: 21 additions & 0 deletions src/shared/ui/Button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ComponentProps } from "react";
import { cn } from "../utils";

interface ButtonProps extends ComponentProps<"button"> {
name: string;
className?: string;
}

export default function Button({ name, className, ...props }: ButtonProps) {
return (
<button
className={cn(
"hover:bg-sub z-10 w-fit cursor-pointer rounded-lg border bg-white p-2 px-4 transition duration-300 ease-in-out hover:text-white focus:outline-hidden",
className,
)}
{...props}
>
{name}
</button>
);
}
23 changes: 23 additions & 0 deletions src/shared/ui/LoginJoinContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Image from "next/image";
import React from "react";

export default function LoginJoinContainer({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="relative flex w-[80%] flex-col justify-center gap-4 rounded-lg bg-white/60 shadow-lg backdrop-blur-md xl:w-[45%]">
<div className="z-10 flex flex-col gap-y-2 px-12 py-24 md:px-24">
{children}
</div>
<Image
width="300"
height="300"
src="/images/spotshare-deco.png"
alt="deco"
className="absolute bottom-0 z-0 rounded-b-lg"
/>
</div>
);
}
13 changes: 13 additions & 0 deletions src/shared/ui/LoginJoinHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Link from "next/link";
import React from "react";

export default function LoginJoinHeader({ name }: { name: string }) {
return (
<div className="mb-2 flex w-full justify-between">
<span className="text-2xl font-bold">{name}</span>
<Link href="/" className="prompt-extrabold text-3xl">
SpotShare
</Link>
</div>
);
}
2 changes: 1 addition & 1 deletion src/shared/ui/ProfileButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default function ProfileButton({
const [isVisible, setVisible] = useState(false);
return (
<div
className={cn("w-fit", className, flex ? "flex" : "absolute")}
className={cn("z-10 w-fit", className, flex ? "flex" : "absolute")}
onClick={() => setVisible(!isVisible)}
// onMouseEnter={() => setVisible(true)}
// onMouseLeave={() => setVisible(false)}
Expand Down
2 changes: 1 addition & 1 deletion src/shared/ui/ProfileModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export default function ProfileModal() {
return (
<div className="flex size-full flex-col gap-y-1 rounded-md bg-white p-2 px-4 focus:outline-hidden">
<Link href="/profile">내 페이지</Link>
<Link href="/">로그인</Link>
<Link href="/login">로그인</Link>
</div>
);
}
7 changes: 7 additions & 0 deletions src/shared/ui/TextField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from "react";

export default function TextField() {
return (
<input className="focus:border-sub h-10 w-full rounded-lg border bg-white/80 p-3 transition delay-100 ease-in-out focus:outline-hidden" />
);
}
4 changes: 4 additions & 0 deletions src/shared/ui/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
export { default as ProfileButton } from "./ProfileButton";
export { default as ProfileModal } from "./ProfileModal";
export { default as TextField } from "./TextField";
export { default as Button } from "./Button";
export { default as LoginJoinHeader } from "./LoginJoinHeader";
export { default as LoginJoinContainer } from "./LoginJoinContainer";
20 changes: 17 additions & 3 deletions src/widgets/home/ui/HomeLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,27 @@ import { ProfileButton } from "@/shared/ui";

export default function HomeLayout() {
return (
<div className="flex min-h-screen flex-col items-center justify-center">
<div
className="flex min-h-screen flex-col items-center justify-center bg-cover bg-center"
style={{ backgroundImage: 'url("/images/scenery.png")' }}
>
<AnimatedSlider />
<ProfileButton className="top-16 right-2 md:right-4" />
<span className="prompt-extrabold mb-10 text-6xl">SpotShare</span>
<span className="prompt-extrabold mb-10 text-6xl text-white">
SpotShare
</span>
<HomeSearch />
<span className="mt-2">실시간 인기 포토스팟을 찾아보세요!</span>
<span className="z-10 mt-2 text-white">
실시간 인기 포토스팟을 찾아보세요!
</span>
<HomeRegionButtons />
<div
className="b absolute bottom-0 z-0 h-screen w-screen"
style={{
backgroundImage:
"linear-gradient(to top, #f4f4f4 20%, transparent 60%)",
}}
></div>
</div>
);
}
6 changes: 3 additions & 3 deletions src/widgets/home/ui/HomeRegionButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default function HomeRegionButtons() {
return (
<button
onClick={() => handleRegionClick(name)}
className="group relative h-40 w-80 cursor-pointer rounded-lg bg-cover bg-center px-4"
className="group relative z-10 h-40 w-80 cursor-pointer rounded-lg bg-cover bg-center px-4"
style={{
backgroundImage: `url(/images/${name}.png)`,
}}
Expand All @@ -37,8 +37,8 @@ export default function HomeRegionButtons() {
}

return (
<div className="absolute bottom-3 flex h-fit w-full flex-col gap-y-4 p-10 md:gap-y-5">
<p className="text-3xl font-extrabold">지역으로 찾아보기</p>
<div className="absolute bottom-3 z-10 flex h-fit w-full flex-col gap-y-4 p-10 md:gap-y-5">
<p className="text-xl font-extrabold md:text-2xl">지역으로 찾아보기</p>
<div className="flex gap-2 md:gap-5">
{regions.map((region, index) => (
<RegionButton key={index} name={region} />
Expand Down
2 changes: 1 addition & 1 deletion src/widgets/home/ui/HomeSearch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { IoSearch } from "react-icons/io5";

export default function HomeSearch() {
return (
<div className="border-border-color/80 relative h-[50px] w-[80%] rounded-lg border bg-white p-2 px-4 sm:w-[60%]">
<div className="border-border-color/80 relative z-10 h-[50px] w-[80%] rounded-lg border bg-white p-2 px-4 sm:w-[60%]">
<button
className="absolute top-0 right-0 h-full w-fit cursor-pointer rounded-2xl bg-white p-2"
onClick={() => alert("아직 만드는중!")}
Expand Down
44 changes: 44 additions & 0 deletions src/widgets/join/ui/JoinLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {
Button,
LoginJoinContainer,
LoginJoinHeader,
TextField,
} from "@/shared/ui";
import React from "react";

export default function JoinLayout() {
return (
<LoginJoinContainer>
<LoginJoinHeader name="회원가입" />
<div className="flex flex-col gap-y-4">
<FormUnit name="닉네임" />
<FormUnit name="아이디" />
<FormUnit name="비밀번호" repeatCheck={false} />
</div>
<Button
name="회원가입 하기"
className="mt-6 w-full bg-black text-white"
/>
</LoginJoinContainer>
);
}

interface FormUnitProps {
name: string;
repeatCheck?: boolean;
}

function FormUnit({ name, repeatCheck = true }: FormUnitProps) {
return (
<div className="flex w-full flex-col gap-y-1">
<label className="text-md">{name}</label>
<div className="flex gap-x-1">
<TextField />
{repeatCheck && (
<Button name="중복확인" className="w-fit text-sm text-nowrap" />
)}
<Button name="완료" className="w-fit text-sm text-nowrap" />
</div>
</div>
);
}
1 change: 1 addition & 0 deletions src/widgets/join/ui/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as JoinLayout } from "./JoinLayout";
52 changes: 52 additions & 0 deletions src/widgets/login/ui/LoginLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {
Button,
LoginJoinContainer,
LoginJoinHeader,
TextField,
} from "@/shared/ui";
import Link from "next/link";

export default function LoginLayout() {
return (
<LoginJoinContainer>
<LoginJoinHeader name="로그인" />
<LoginUnit name="아이디" />
<LoginUnit name="비밀번호" />
<LoginFooter />
</LoginJoinContainer>
);
}

interface LoginUnitProps {
name: string;
}

function LoginUnit({ name }: LoginUnitProps) {
return (
<div className="flex w-full flex-col gap-y-1">
<label className="text-md">{name}</label>
<div className="flex gap-x-1">
<TextField />
</div>
</div>
);
}

function LoginFooter() {
return (
<div className="mt-2 flex w-full items-center justify-between">
<div className="flex w-[55%] justify-between">
<Link href="/join">
<span className="text-md cursor-pointer hover:text-black/50">
회원가입
</span>
</Link>
<span className="text-md hidden md:block">|</span>
<button className="l text-md hidden cursor-pointer hover:text-black/50 md:block">
비밀번호를 잊어버렸어요!
</button>
</div>
<Button name="로그인" />
</div>
);
}
1 change: 1 addition & 0 deletions src/widgets/login/ui/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as LoginLayout } from "./LoginLayout";