issue # 회원가입 화면 구현 중
This commit is contained in:
54
package-lock.json
generated
54
package-lock.json
generated
@@ -50,6 +50,7 @@
|
||||
"react-dom": "^19.1.1",
|
||||
"react-hook-form": "^7.66.0",
|
||||
"react-resizable-panels": "^3.0.6",
|
||||
"react-router-dom": "^7.9.5",
|
||||
"recharts": "^2.15.4",
|
||||
"sonner": "^2.0.7",
|
||||
"tailwind-merge": "^3.3.1",
|
||||
@@ -4069,6 +4070,15 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/cookie": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz",
|
||||
"integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
@@ -5773,6 +5783,44 @@
|
||||
"react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/react-router": {
|
||||
"version": "7.9.5",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.9.5.tgz",
|
||||
"integrity": "sha512-JmxqrnBZ6E9hWmf02jzNn9Jm3UqyeimyiwzD69NjxGySG6lIz/1LVPsoTCwN7NBX2XjCEa1LIX5EMz1j2b6u6A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cookie": "^1.0.1",
|
||||
"set-cookie-parser": "^2.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=18",
|
||||
"react-dom": ">=18"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-router-dom": {
|
||||
"version": "7.9.5",
|
||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.9.5.tgz",
|
||||
"integrity": "sha512-mkEmq/K8tKN63Ae2M7Xgz3c9l9YNbY+NHH6NNeUmLA3kDkhKXRsNb/ZpxaEunvGo2/3YXdk5EJU3Hxp3ocaBPw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"react-router": "7.9.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=18",
|
||||
"react-dom": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/react-smooth": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz",
|
||||
@@ -5960,6 +6008,12 @@
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
},
|
||||
"node_modules/set-cookie-parser": {
|
||||
"version": "2.7.2",
|
||||
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz",
|
||||
"integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"react-dom": "^19.1.1",
|
||||
"react-hook-form": "^7.66.0",
|
||||
"react-resizable-panels": "^3.0.6",
|
||||
"react-router-dom": "^7.9.5",
|
||||
"recharts": "^2.15.4",
|
||||
"sonner": "^2.0.7",
|
||||
"tailwind-merge": "^3.3.1",
|
||||
|
||||
30
src/App.tsx
30
src/App.tsx
@@ -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
5
src/data/AuthData.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export type AuthData = {
|
||||
accessToken: string;
|
||||
refreshToken: string;
|
||||
isLogedIn: boolean;
|
||||
}
|
||||
20
src/data/RoutingData.ts
Normal file
20
src/data/RoutingData.ts
Normal 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
5
src/data/UserInfoData.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export type UserInfoData = {
|
||||
name: string;
|
||||
nickname: string;
|
||||
email: string;
|
||||
}
|
||||
23
src/layouts/Layout.tsx
Normal file
23
src/layouts/Layout.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
0
src/request/user/LoginRequest.ts
Normal file
0
src/request/user/LoginRequest.ts
Normal file
13
src/store/authStore.ts
Normal file
13
src/store/authStore.ts
Normal 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 })
|
||||
}));
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user