Skip to content

Commit

Permalink
feat: finish us1
Browse files Browse the repository at this point in the history
Co-Authored-By: Joaovitor045 <joaovitoralvestf@gmail.com>
Co-Authored-By: gsVieiraaa <Gabriel.vieira.santos.110@gmail.com>
  • Loading branch information
3 people committed Dec 8, 2024
1 parent 5978267 commit 5202fbe
Show file tree
Hide file tree
Showing 19 changed files with 585 additions and 48 deletions.
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 12 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ import NotFound from "./pages/NotFound"
import { AuthProvider } from "./hooks/useAuth"
import { ChakraProvider } from "@chakra-ui/react"
import { system } from "./theme"
import Profile from "./pages/Profile"
import ProfileEdit from "./pages/ProfileEdit"
import Warnings from "./pages/Warnings"
import Loans from "./pages/Loans"
import { Toaster } from "./components/ui/toaster"
import PrivateRoute from './PrivateRoute';

function App() {
return (
Expand All @@ -13,11 +19,16 @@ function App() {
<BrowserRouter>
<Routes>
<Route path="*" element={<NotFound />} />
<Route path="/" element={<Home />} />
<Route path="/cadastro" element={<SignUp />} />
<Route path="/inicio" element={<PrivateRoute><Home /></PrivateRoute>} />
<Route path="/perfil" element={<PrivateRoute><Profile /></PrivateRoute>} />
<Route path="/perfil/editar" element={<PrivateRoute><ProfileEdit /></PrivateRoute>} />
<Route path="/avisos" element={<PrivateRoute><Warnings /></PrivateRoute>} />
<Route path="/emprestimos" element={<PrivateRoute><Loans /></PrivateRoute>} />
</Routes>
</BrowserRouter>
</AuthProvider>
<Toaster />
</ChakraProvider>
)
}
Expand Down
17 changes: 17 additions & 0 deletions src/PrivateRoute.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useNavigate } from "react-router";
import { useAuth } from "./hooks/useAuth"
import { useEffect } from "react";

const PrivateRoute = ({ children }: { children: any }) => {
const navigate = useNavigate();
const { token } = useAuth();

useEffect(() => {
if (token) return;
navigate('/cadastro');
})

return children;
}

export default PrivateRoute
39 changes: 39 additions & 0 deletions src/components/NavBar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Box, Center, Flex, Stack, Text } from "@chakra-ui/react"
import { Button } from "../ui/button"
import { BsHouse, BsBell, BsBook, BsPerson } from 'react-icons/bs';
import { useLocation, useNavigate } from "react-router";

export const NavBar = () => {
const navigate = useNavigate()
const location = useLocation()

const selectedTab = location.pathname.replace('/', '');
const tabs = [
{ label: 'Início', value: 'inicio', icon: <BsHouse /> },
{ label: 'Empréstimos', value: 'emprestimos', icon: <BsBook /> },
{ label: 'Avisos', value: 'avisos', icon: <BsBell /> },
{ label: 'Perfil', value: 'perfil', icon: <BsPerson /> },
]

return (
<Box position='fixed' width='100%' bottom='0' boxShadow='2xl'>
<Center>
<Flex width={'100%'} justifyContent={'space-between'} padding={'20px'}>
{tabs.map(tab => (
<Button
key={tab.value}
variant='plain'
onClick={() => navigate('/' + tab.value)}
color={selectedTab === tab.value ? 'blue.100' : ''}
>
<Stack align='center'>
{tab.icon}
<Text textAlign='center'>{tab.label}</Text>
</Stack>
</Button>
))}
</Flex>
</Center>
</Box>
);
}
43 changes: 43 additions & 0 deletions src/components/ui/toaster.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"use client"

import {
Toaster as ChakraToaster,
Portal,
Spinner,
Stack,
Toast,
createToaster,
} from "@chakra-ui/react"

export const toaster = createToaster({
placement: "bottom-end",
pauseOnPageIdle: true,
})

export const Toaster = () => {
return (
<Portal>
<ChakraToaster toaster={toaster} insetInline={{ mdDown: "4" }}>
{(toast) => (
<Toast.Root width={{ md: "sm" }}>
{toast.type === "loading" ? (
<Spinner size="sm" color="blue.solid" />
) : (
<Toast.Indicator />
)}
<Stack gap="1" flex="1" maxWidth="100%">
{toast.title && <Toast.Title>{toast.title}</Toast.Title>}
{toast.description && (
<Toast.Description>{toast.description}</Toast.Description>
)}
</Stack>
{toast.action && (
<Toast.ActionTrigger>{toast.action.label}</Toast.ActionTrigger>
)}
{toast.meta?.closable && <Toast.CloseTrigger />}
</Toast.Root>
)}
</ChakraToaster>
</Portal>
)
}
41 changes: 39 additions & 2 deletions src/hooks/useApi/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,8 @@ const createApiInstance = (url: string) => {
const getDefaultErrorUseAPIMessage = (err: any) => {
return {
error: true,
...err?.toJSON?.call(),
...err?.response,
...err?.response?.data,
...err?.data,
};
};

Expand All @@ -30,6 +28,18 @@ const useApi = () => {
);

return {
getProfile: (token: string): Promise<{ data: User }> => {
return new Promise((resolve) => {
api
.get('/auth/profile', {
headers: {
Authorization: `Bearer ${token}`,
}
})
.then((res) => resolve(res))
.catch((err) => resolve(getDefaultErrorUseAPIMessage(err)));
});
},
signUp: (data: {
firstName: string;
lastName: string;
Expand All @@ -46,6 +56,33 @@ const useApi = () => {
.then((res) => resolve(res))
.catch((err) => resolve(getDefaultErrorUseAPIMessage(err)));
});
},
editProfile: async (id: string, data: {
firstName: string;
lastName: string;
email: string;
phone: string;
oldPassword?: string
newPassword?: string
}): Promise<{ data: {
id: string;
} }> => {
return new Promise((resolve) => {
api
.put(`/users/${id}`, data)
.then((res) => resolve(res))
.catch((err) => resolve(getDefaultErrorUseAPIMessage(err)));
});
},
deleteProfile: async (id: string): Promise<{ data: {
id: string;
} }> => {
return new Promise((resolve) => {
api
.delete(`/users/${id}`)
.then((res) => resolve(res))
.catch((err) => resolve(getDefaultErrorUseAPIMessage(err)));
});
}
}
}
Expand Down
45 changes: 41 additions & 4 deletions src/hooks/useAuth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { createContext, useState, useContext, ReactNode } from 'react';

import useApi from './useApi';
import { toaster } from '../components/ui/toaster';

interface SignUpParams {
firstName: string;
Expand All @@ -12,17 +13,27 @@ interface SignUpParams {
password: string;
}

interface EditProfileParams {
firstName: string;
lastName: string;
email: string;
phone: string;
oldPassword?: string;
newPassword?: string;
}

type AuthContextType = {
isAuthenticated: boolean;
token: string | null;
signOut: () => void;
signUp: (userToSignUp: SignUpParams) => Promise<void>;
signUp: (userToSignUp: SignUpParams) => Promise<boolean>;
editProfile: (id: string, profileToEdit: EditProfileParams) => Promise<boolean>;
};

const AuthContext = createContext({} as AuthContextType);

export const AuthProvider = ({ children }: { children: ReactNode }) => {
const { signUp: authSignUp } = useApi();
const { signUp: authSignUp, editProfile: authEditProfile } = useApi();

const localToken =
typeof window !== 'undefined'
Expand All @@ -32,13 +43,38 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
localToken ? localToken : null,
);

async function signUp(userToSignUp: SignUpParams) {
async function signUp(userToSignUp: SignUpParams): Promise<boolean> {
const { data } = await authSignUp(userToSignUp);
if (!data.accessToken) return;
if (!data.accessToken) {
toaster.create({
title: 'Erro ao criar conta',
description: 'Verifique os campos e tente novamente.',
type: 'error',
})
return false;
};
setToken(data.accessToken);
if (typeof window !== 'undefined') {
localStorage.setItem('@livrolivre:token', data.accessToken);
}
return true;
}

async function editProfile(id: string, profileToEdit: EditProfileParams): Promise<boolean> {
const { data } = await authEditProfile(id, profileToEdit);
if (data.id) {
toaster.create({
title: 'Perfil editado com sucesso!',
type: 'success',
})
return true;
};
toaster.create({
title: 'Erro ao editar perfil',
description: 'Verifique os campos e tente novamente.',
type: 'error',
})
return false;
}

function signOut(): void {
Expand All @@ -55,6 +91,7 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
token,
signOut,
signUp,
editProfile,
}}
>
{children}
Expand Down
1 change: 1 addition & 0 deletions src/interfaces/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export interface User {
id: string;
firstName: string;
lastName: string;
phone: string;
email: string;
createdAt: string;
updatedAt: string;
Expand Down
9 changes: 5 additions & 4 deletions src/pages/Home/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import styles from './styles';
import { Box } from '@chakra-ui/react';
import { NavBar } from '../../components/NavBar';

function Home() {
return (
<styles.Container>
<h1>Home</h1>
</styles.Container>
<Box>
<NavBar />
</Box>
);
}

Expand Down
5 changes: 0 additions & 5 deletions src/pages/Home/styles.ts

This file was deleted.

12 changes: 12 additions & 0 deletions src/pages/Loans/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Box } from '@chakra-ui/react';
import { NavBar } from '../../components/NavBar';

function Loans() {
return (
<Box>
<NavBar />
</Box>
);
}

export default Loans
Loading

0 comments on commit 5202fbe

Please sign in to comment.