Skip to content

Commit

Permalink
feat(auth): create router template and change return type of /api/user
Browse files Browse the repository at this point in the history
  • Loading branch information
ngyngcphu committed Sep 19, 2023
1 parent 0ccbef6 commit e2b5cca
Show file tree
Hide file tree
Showing 23 changed files with 186 additions and 64 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
VITE_BACKEND_URL=
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="icon" type="image/svg+xml+jpg" href="/ssps-logo.jpg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Smart Service Printing System</title>
</head>
Expand Down
Binary file added public/ssps-logo.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion public/vite.svg

This file was deleted.

75 changes: 70 additions & 5 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,75 @@
import { AuthLayout } from '@layouts';
import { AuthPage } from '@pages';
import { useEffect } from 'react';
import { HomeIcon } from '@heroicons/react/24/outline';
import { AppLayout, AuthLayout } from '@layouts';
import { AuthPage, HomePage } from '@pages';
import { useUserStore } from '@states';
import { AppSkeleton } from '@components';

export default function App() {
const { userStatus, getUserData } = useUserStore();

useEffect(() => {
getUserData();
}, [getUserData]);

if (userStatus === 'UNINIT' || userStatus === 'PENDING') {
return <AppSkeleton />;
}

if (userStatus === 'REJECT') {
return (
<AuthLayout>
<AuthPage />
</AuthLayout>
);
}

return (
<AuthLayout>
<AuthPage />
</AuthLayout>
<AppLayout
menu={[
{
type: 'item',
icon: <HomeIcon className='h-5 w-5' />,
path: '/home',
name: 'Trang chủ',
element: <HomePage />
}
// {
// type: 'list',
// icon: <CurrencyDollarIcon className='h-5 w-5' />,
// name: 'Quỹ lab',
// routes: [
// {
// type: 'item',
// name: 'Thống kê',
// icon: <ChartBarSquareIcon strokeWidth={2} className='h-4 w-4' />,
// path: '/finance/statistic',
// element: <></>
// },
// {
// type: 'item',
// icon: <CreditCardIcon strokeWidth={2} className='h-4 w-4' />,
// name: 'Giao dịch',
// path: '/finance/transaction',
// element: <></>
// }
// ]
// },
// 'divider',
// {
// type: 'item',
// icon: <UserCircleIcon className='h-5 w-5' />,
// path: '/user',
// name: 'Cá nhân',
// element: <></>
// },
// {
// type: 'logout-btn',
// icon: <PowerIcon className='h-5 w-5' />,
// name: 'Đăng xuất',
// //onClick: () => authService.logout().then(() => getData())
// }
]}
/>
);
}
File renamed without changes
File renamed without changes
File renamed without changes
11 changes: 0 additions & 11 deletions src/assets/login.svg

This file was deleted.

File renamed without changes
1 change: 0 additions & 1 deletion src/assets/react.svg

This file was deleted.

35 changes: 32 additions & 3 deletions src/layouts/AppLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,32 @@
export function AppLayout() {
return <></>;
}
import { useMemo } from 'react';
import { Routes, Route } from 'react-router-dom';

export const AppLayout: Component<{ menu: RouteMenu }> = ({ menu }) => {
const routeItems = useMemo(() => {
const items: { path: string; element: React.ReactElement }[] = [];
for (const menuItem of menu) {
if (menuItem === 'divider' || menuItem.type === 'logout-btn') continue;
if (menuItem.type === 'list') {
for (const route of menuItem.routes) {
items.push({ path: route.path, element: route.element });
}
} else {
items.push({ path: menuItem.path, element: menuItem.element });
}
}

return items;
}, [menu]);

return (
<div className='flex flex-col h-screen sm:min-h-screen'>
<div className='lg:p-4 flex-1 h-full'>
<Routes>
{routeItems.map((item) => (
<Route path={item.path} element={item.element} key={item.path} />
))}
</Routes>
</div>
</div>
);
};
7 changes: 4 additions & 3 deletions src/layouts/AuthLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import logo from '@assets/logobk.png';
import corner from '@assets/corner.png';
import { ILayout } from '@interfaces';
import logo from '@assets/images/logobk.png';
import corner from '@assets/images/corner.png';

export const AuthLayout: ILayout = ({ children }) => {
return (
<div className='flex flex-col items-center w-full h-[100vh] gap-6 bg-[#F8F9FA] fixed'>
<div className="bg-[url('./src/assets/images/header.png')] bg-no-repeat bg-cover bg-center py-5">
<div className="bg-[url('./src/assets/header.png')] bg-no-repeat bg-cover bg-center py-5">
<div className='flex items-center justify-center sm:justify-start sm:px-20'>
<div className='w-[10%] mr-[5px] sm:w-[10%] lg:w-[5%]'>
<img src={logo} alt='' />
Expand Down
19 changes: 11 additions & 8 deletions src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css';
import 'react-toastify/dist/ReactToastify.css';
import { BrowserRouter } from 'react-router-dom';
import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import { ThemeProvider } from '@material-tailwind/react';
import './index.css';
import App from './App';

ReactDOM.createRoot(document.getElementById('root')!).render(
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<React.StrictMode>
<ThemeProvider>
<ToastContainer limit={1} />
<App />
</ThemeProvider>
<BrowserRouter>
<ThemeProvider>
<ToastContainer limit={1} />
<App />
</ThemeProvider>
</BrowserRouter>
</React.StrictMode>
);
42 changes: 27 additions & 15 deletions src/pages/AuthPage.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
import { useForm } from 'react-hook-form';
import { useState } from 'react';
import { NavigateFunction, useNavigate } from 'react-router-dom';
import { toast } from 'react-toastify';
import { useForm } from 'react-hook-form';
import * as Yup from 'yup';
import { yupResolver } from '@hookform/resolvers/yup';
import { Card, Input, Button, Typography } from '@material-tailwind/react';
import { EyeIcon, EyeSlashIcon } from '@heroicons/react/24/outline';
import { authService } from '@services';
import { useUserStore } from '@states';
import { useState } from 'react';
import { EyeIcon, EyeSlashIcon } from '@heroicons/react/24/outline';
import { validateSchema } from './validateSchema';
import { yupResolver } from '@hookform/resolvers/yup';

export const AuthPage = () => {
const navigate: NavigateFunction = useNavigate();
const { getUserData } = useUserStore();

const validateSchema = Yup.object().shape({
email: Yup.string()
.required('Username is required!')
.min(5, 'Username must be at least 5 characters'),
password: Yup.string()
.required('Password is required!')
.min(8, 'Password must be at least 8 characters')
});

const {
register,
handleSubmit,
Expand All @@ -17,17 +30,16 @@ export const AuthPage = () => {
resolver: yupResolver(validateSchema)
});
const [showPassword, setShowPassword] = useState<string>('password');
const { getUserData } = useUserStore();

const submit = (data: LoginFormData) => {
authService
.login(data)
.then(() => {
getUserData();
})
.catch((err) => {
toast.error(err.message);
});
const submit = async (data: LoginFormData) => {
try {
await authService.login(data);
getUserData();
navigate('/home');
} catch (err) {
const errorMessage = (err as ResponseError).message;
toast.error(errorMessage);
}
};

return (
Expand Down
3 changes: 3 additions & 0 deletions src/pages/HomePage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function HomePage() {
return <div>Đăng nhập thành công</div>;
}
2 changes: 1 addition & 1 deletion src/pages/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
*/

export * from './AuthPage';
export * from './HomePage';
export * from './ProjectDetailPage';
export * from './ProjectGeneralPage';
export * from './validateSchema';
9 changes: 0 additions & 9 deletions src/pages/validateSchema.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/services/user.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { server, invoke } from './common';

export const userService = {
getInfo: () => invoke<string[]>(server.get('/api/user'))
getInfo: () => invoke<UserReturnValue>(server.get('/api/user'))
};
5 changes: 4 additions & 1 deletion src/states/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import { userService } from '@services';

export const useUserStore = create<UserStore>()((set) => ({
userStatus: 'UNINIT',
userData: [],
userData: {
id: '',
email: ''
},
getUserData: async () => {
set(() => ({ userStatus: 'PENDING' }));
try {
Expand Down
24 changes: 24 additions & 0 deletions src/types/routeSetting.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
type BaseRoute = {
icon: React.ReactElement;
name: string;
};

type RoutesList = BaseRoute & {
type: 'list';
routes: RouteItem[];
};

type RouteItem = BaseRoute & {
type: 'item';
path: string;
element: React.ReactElement;
};

type LogoutBtn = BaseRoute & {
type: 'logout-btn';
onClick: () => void;
};

type RouteMenuItem = RouteItem | RoutesList | 'divider' | LogoutBtn;

type RouteMenu = RouteMenuItem[];
7 changes: 6 additions & 1 deletion src/types/user.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
type UserReturnValue = {
id: string;
email: string;
};

type UserStore = {
userStatus: StoreStatus;
userData: string[];
userData: UserReturnValue;
getUserData: () => Promise<void>;
};
4 changes: 1 addition & 3 deletions tailwind.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ module.exports = withMT({
decimal: 'decimal',
circle: 'circle'
},
extend: {

}
extend: {}
},
plugins: []
});
Expand Down

0 comments on commit e2b5cca

Please sign in to comment.