issue # 회원가입 화면 구현 중

This commit is contained in:
민건희
2025-11-05 23:14:32 +09:00
parent 3a6e3eb70b
commit 917bef73b0
13 changed files with 176 additions and 91 deletions

View File

@@ -1,16 +1,26 @@
import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
import SignUpPage from './ui/page/signup/SignUpPage'
import { useState } from 'react';
import reactLogo from './assets/react.svg';
import viteLogo from '/vite.svg';
import './App.css';
import SignUpPage from './ui/page/signup/SignUpPage';
import Layout from './layouts/Layout';
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
import { useAuthStore } from './store/authStore';
import { PageRouting } from './data/RoutingData';
function App() {
const { authData } = useAuthStore();
return (
<div className="w-full h-full flex flex-col justify-center items-center">
<SignUpPage></SignUpPage>
</div>
)
<Router>
<Routes>
<Route element={<Layout />}>
<Route element={<SignUpPage />} path={PageRouting["SIGN_UP"].path} />
{!(authData?.isLogedIn) ? <Route element={<Navigate to={`/${PageRouting["SIGN_UP"].path}`} />} path="*" /> : null}
</Route>
</Routes>
</Router>
);
}
export default App

5
src/data/AuthData.ts Normal file
View File

@@ -0,0 +1,5 @@
export type AuthData = {
accessToken: string;
refreshToken: string;
isLogedIn: boolean;
}

20
src/data/RoutingData.ts Normal file
View File

@@ -0,0 +1,20 @@
type PageRoutingInfo = {
path: string;
title: string;
}
export const PageRouting: Record<string, PageRoutingInfo> = {
LOGIN: { path: "login", title: "" },
SIGN_UP: { path: "signup", title: "" },
RESET_PASSWORD: { path: "reset-password", title: "" },
HOME: { path: "home", title: "홈" },
SCHEDULES: { path: "schedules", title: "일정" },
SCHEDULES_NEW: { path: "schedules/new", title: "일정 생성" },
SCHEDULES_EDIT: { path: "schedules/edit", title: "일정 수정" },
SCHEDULES_DETAIL: { path: "schedules/detail", title: "일정 상세" },
USER_INFO: { path: "info", title: "사용자 정보" },
USER_FOLLOWING: { path: "info/following", title: "팔로잉 목록" },
USER_FOLLOWER: { path: "info/follower", title: "팔로워 목록" },
SETTINGS: { path: "settings", title: "설정" },
NOT_FOUD: { path: "not-found", title: "존재하지 않는 페이지" },
} as const;

5
src/data/UserInfoData.ts Normal file
View File

@@ -0,0 +1,5 @@
export type UserInfoData = {
name: string;
nickname: string;
email: string;
}

23
src/layouts/Layout.tsx Normal file
View File

@@ -0,0 +1,23 @@
import SideBar from "@/ui/component/SideBar";
import { Outlet } from "react-router-dom";
import { SidebarProvider } from "@/components/ui/sidebar";
import Header from "@/ui/component/Header";
import { useAuthStore } from '@/store/authStore';
export default function Layout() {
const { authData } = useAuthStore();
return (
<SidebarProvider
defaultOpen={false}
id="root"
>
<SideBar />
<div className="flex flex-col w-full h-full">
{ authData?.isLogedIn ? <Header /> : null}
{/* <Header /> */}
<Outlet />
</div>
</SidebarProvider>
);
}

View File

13
src/store/authStore.ts Normal file
View File

@@ -0,0 +1,13 @@
import type { AuthData } from '@/data/AuthData';
import { create } from 'zustand';
interface AuthStoreProps {
authData: AuthData | undefined;
login: (data: AuthData) => void;
}
export const useAuthStore = create<AuthStoreProps>((set) => ({
authData: undefined,
login: (data: AuthData) => set({ authData: data }),
logout: () => set({ authData: undefined })
}));

View File

@@ -1,14 +1,14 @@
import { Label } from '@/components/ui/label';
import { SidebarTrigger } from '@/components/ui/sidebar';
import { Separator } from '@/components/ui/separator';
import { useState } from 'react';
import Routing from './RoutingData';
export default function Header() {
return (
<header className="flex shrink-0 items-center gap-2 border-b px-4 w-full h-12">
<SidebarTrigger className="-ml-1" />
<Separator orientation="vertical" className="mr-2 data-[orientation=vertical]:h-4"/>
<Label>{import.meta.env.BASE_URL}</Label>
</header>
);
return (
<header className="flex shrink-0 items-center gap-2 border-b px-4 w-full h-12">
<SidebarTrigger className="-ml-1" />
<Separator orientation="vertical" className="mr-2 data-[orientation=vertical]:h-4" />
<Label>{import.meta.env.BASE_URL}</Label>
</header>
);
}

View File

@@ -1,20 +0,0 @@
type PageRoutingInfo = {
path: string;
title: string;
}
export const PageRouting: Record<string, PageRoutingInfo> = {
LOGIN: { path: "login", title: "" },
SIGN_UP: { path: "signup", title: "" },
RESET_PASSWORD: { path: "reset-password", title: "" },
HOME: { path: "home", title: "홈" },
SCHEDULES: { path: "schedules", title: "일정" },
SCHEDULES_NEW: { path: "schedules/new", title: "일정 생성" },
SCHEDULES_EDIT: { path: "schedules/edit", title: "일정 수정" },
SCHEDULES_DETAIL: { path: "schedules/detail", title: "일정 상세" },
USER_INFO: { path: "info", title: "사용자 정보" },
USER_FOLLOWING: { path: "info/following", title: "팔로잉 목록" },
USER_FOLLOWER: { path: "info/follower", title: "팔로워 목록" },
SETTINGS: { path: "settings", title: "설정" },
NOT_FOUD: { path: "not-found", title: "존재하지 않는 페이지" },
} as const;

View File

@@ -1,11 +1,15 @@
import { useState } from 'react';
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarHeader
} from './components/ui/sidebar';
Sidebar,
SidebarContent,
SidebarFooter,
SidebarHeader
} from '@/components/ui/sidebar';
export default function SideBar() {
return (<Sidebar></Sidebar>)
return (
<Sidebar>
</Sidebar>
);
}

View File

@@ -1,58 +1,28 @@
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { useState } from 'react';
import { format } from 'date-fns';
import { Label } from '@/components/ui/label';
import { Calendar } from '@/components/ui/calendar';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle
} from '@/components/ui/card';
import { Form, FormField } from '@/components/ui/form';
export default function SignUpPage() {
const [open, setOpen] = useState<boolean>(false);
const [date, setDate] = useState<Date>(new Date());
return (
<div className="w-full h-full flex flex-row justify-center items-center">
<div className="flex flex-col gap-4 justify-center items-center">
<Label>Date Picker</Label>
<Popover
open={open}
onOpenChange={setOpen}
>
<PopoverTrigger asChild>
<Button
variant="outline"
id="date"
className="w-fit justify-between font-normal"
>
{date ? format(date, "yyyy/MM/dd") : "Select Date"}
</Button>
</PopoverTrigger>
<PopoverContent>
<Calendar
mode="single"
timeZone="Asia/Seoul"
formatters={{
formatCaption: (month) =>
format(month, "yyyy년 MM월")
}}
onSelect={(date) => {
if (date) {
setDate(date);
setOpen(false);
}
}}
selected={date}
defaultMonth={date}
captionLayout="dropdown"
/>
</PopoverContent>
</Popover>
<Input
type="time"
id="time"
defaultValue={format(date, "HH:mm")}
/>
</div>
<div className="w-full h-full flex flex-col justify-center items-center">
<Card className="w-xl h-4/6">
<CardHeader className="ml-2.5 select-none">
<CardTitle className="text-3xl"></CardTitle>
</CardHeader>
<CardContent>
<Label>a</Label>
</CardContent>
</Card>
</div>
);
}