Skip to content

Commit

Permalink
feat: zustand store 적용 (#55)
Browse files Browse the repository at this point in the history
* WIP: auth

* feat: zustand store 적용 (#54)

---------

Co-authored-by: David Kim <[email protected]>
  • Loading branch information
0plan and frankkim92 authored Apr 15, 2024
1 parent 97a6283 commit 3e0d195
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 40 deletions.
17 changes: 9 additions & 8 deletions src/components/SignIn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,42 +11,43 @@ import { Button } from '@/components/ui/button';
import { Label } from '@/components/ui/label';
import { Input } from '@/components/ui/input';
import { useToast } from '@/components/ui/use-toast';
import { useState, useEffect } from 'react';
import { useState } from 'react';
import NProgress from 'nprogress';
import { useTranslation } from 'react-i18next';
import { LogIn } from 'lucide-react';
import authStore from '@/stores/auth';

export default function SignIn({ setIsAuth, setStoreAuth }) {
export default function SignIn() {
const { t } = useTranslation();
const { toast } = useToast();
const [open, setOpen] = useState(false);
const [loading, setLoading] = useState(false);
const { login } = authStore();

const signIn = () => new Promise((resolve) => {
NProgress.start();
setLoading(true);
setTimeout(resolve, 1000);
}).then(() => {
NProgress.done();
login();
setLoading(false);
setOpen(false);
setIsAuth(true);
localStorage.setItem('isAuth', true);
setStoreAuth(true);
toast({
description: 'Signed in successfully!',
});
});
const handleEmailKeyPress = (e) => {
if (e.key === 'Enter') document.getElementById('password').focus();
};
const handlePasswordKeyPress = (e) => {
if (e.key === 'Enter') signIn();
const handlePasswordKeyPress = async (e) => {
if (e.key === 'Enter') await signIn();
};

return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button>{t('signIn')}</Button>
<LogIn className="ml-2" />
</DialogTrigger>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
Expand Down
43 changes: 12 additions & 31 deletions src/components/layouts/header/index.tsx
Original file line number Diff line number Diff line change
@@ -1,48 +1,31 @@
import { Link, useNavigate } from 'react-router-dom';
import { Link } from 'react-router-dom';
import Menu from '@/components/layouts/header/menu';
import MobileMenu from '@/components/layouts/header/mobileMenu';
import { useTranslation } from 'react-i18next';
import {
Globe, Moon, Sun, User,
Globe, LogOut, Moon, Sun, User,
} from 'lucide-react';
import useLanguage from '@/stores/language';
import { Button } from '@/components/ui/button';
import SignIn from '@/components/SignIn';
import { useDarkMode } from '@/lib/dark-mode';
import { useState, useEffect } from 'react';
import { useLocalStorage } from 'usehooks-ts';
import { useToast } from '@/components/ui/use-toast';
import authStore from '@/stores/auth';

function Header() {
const { t } = useTranslation();
const { toast } = useToast();
const { isDarkMode, toggle } = useDarkMode();
const { toggle } = useDarkMode();
const { toggleLang } = useLanguage();
const [isAuth, setIsAuth] = useState(false);
const [storeauth, setStoreAuth] = useLocalStorage('isAuth', false);

const navigate = useNavigate();
const { logout, isAuth } = authStore();
const menuItems = [{ path: '/example', name: t('menu.example') }];

const signOut = () => {
setIsAuth(false);
setStoreAuth(false);
localStorage.setItem('isAuth', 'false');
logout();
toast({
description: 'Signed out successfully!',
});
};

useEffect(() => {
const storedAuth = localStorage.getItem('isAuth');
if (storedAuth === 'true') {
setIsAuth(true);
setStoreAuth(true);
} else {
navigate('/');
}
}, [isAuth]);

return (
<header className="z-50 flex w-full flex-wrap justify-start py-4 text-sm fixed top-0 backdrop-blur-sm">
<nav className="mx-auto flex w-full max-w-[85rem] items-center justify-between px-4">
Expand All @@ -56,14 +39,6 @@ function Header() {
<Menu menuItems={menuItems} />
</div>
<div className="flex items-center justify-end sm:px-10">
{isAuth ? (
<Button onClick={signOut} variant="destructive">
{t('signOut')}
</Button>
) : (
<SignIn setIsAuth={setIsAuth} setStoreAuth={setStoreAuth} />
)}

<Sun
className="cursor-pointer ml-2 hidden dark:block"
onClick={toggle}
Expand All @@ -77,6 +52,12 @@ function Header() {
</Link>
)
}
{isAuth ? (
<LogOut onClick={signOut} className="cursor-pointer ml-2" />
) : (

<SignIn />
)}
</div>
</nav>
</header>
Expand Down
1 change: 0 additions & 1 deletion src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { HelmetProvider } from 'react-helmet-async';
import '@/lib/locales';
import { createRoot } from 'react-dom/client';
import { Routes } from '@generouted/react-router';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
import '@/style/nprogress.css';

Expand Down
20 changes: 20 additions & 0 deletions src/pages/(auth)/_layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { useEffect } from 'react';
import authStore from '@/stores/auth';
import { useNavigate, Outlet } from 'react-router-dom';

export default function Index() {
const { isAuth } = authStore();
const nav = useNavigate();

useEffect(() => {
if (!isAuth) {
nav('/', { replace: true });
}
}, [isAuth]);

return (
<main>
<Outlet />
</main>
);
}
24 changes: 24 additions & 0 deletions src/stores/auth.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { create } from 'zustand';

type Auth = {
isAuth: boolean
login: () => void
logout: () => void
}

const authStore = create<Auth>((set) => ({
isAuth: localStorage.getItem('isAuth') === 'true' || false,

login: () => set(() => {
localStorage.setItem('isAuth', 'true');
return { isAuth: true };
}),

logout: () => set(() => {
localStorage.removeItem('isAuth');
return { isAuth: false };
}),

}));

export default authStore;

0 comments on commit 3e0d195

Please sign in to comment.