Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ And that's it! Your `SkateHub Frontend` should now be up and running locally on

### 2024

- 2024-03-31 - Update `authentication` and `session` management [#11](https://github.com/jpcmf/Frontend-GraduateProgram-FullStack-2024/pull/11) _(v0.1.9)_
- 2024-03-29 - Create the `toast` component [#10](https://github.com/jpcmf/Frontend-GraduateProgram-FullStack-2024/pull/10) _(v0.1.8)_
- 2024-03-27 - Add the `favicon` of the SkateHub project [#9](https://github.com/jpcmf/Frontend-GraduateProgram-FullStack-2024/pull/9) _(v0.1.7)_
- 2024-03-27 - Add the `prettier.config.js` file to the project to handle with code formatter [#8](https://github.com/jpcmf/Frontend-GraduateProgram-FullStack-2024/pull/8) _(v0.1.6)_
Expand Down
34 changes: 32 additions & 2 deletions package-lock.json

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

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "frontend",
"version": "0.1.8",
"version": "0.1.9",
"private": true,
"scripts": {
"dev": "next dev",
Expand All @@ -18,13 +18,15 @@
"framer-motion": "^11.0.20",
"next": "latest",
"next-auth": "^4.24.7",
"nookies": "^2.5.2",
"react": "latest",
"react-dom": "latest",
"react-hook-form": "^7.51.2",
"react-icons": "^5.0.1",
"yup": "^1.4.0"
},
"devDependencies": {
"@types/cookie": "^0.6.0",
"@types/node": "latest",
"@types/react": "latest",
"@types/react-dom": "latest",
Expand Down
52 changes: 29 additions & 23 deletions src/components/Header/Profile.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,52 @@
import { useContext } from "react";
import { RiLogoutCircleLine } from "react-icons/ri";
import { signOut, useSession } from "next-auth/react";
import { Box, Flex, Text, Menu, Avatar, MenuList, MenuItem, MenuButton } from "@chakra-ui/react";

import { AuthContext } from "@/contexts/AuthContext";

interface ProfileProps {
showProfileData: boolean | undefined;
}

export function Profile({ showProfileData = true }: ProfileProps) {
const { data: session } = useSession();

console.log("session...", session);
const { user, signOut } = useContext(AuthContext);

return (
<Flex align="center">
{showProfileData && (
<Box mr="4" textAlign="right">
<Text>{session?.user?.username ? session?.user?.username : "Sem nome"}</Text>
<Text>{user?.name}</Text>
<Text color="gray.600" fontSize="small">
{session?.user?.email ? session?.user?.email : "Sem e-mail"}
{user?.email}
</Text>
</Box>
)}
<Menu>
<MenuButton>
<Avatar size="md" name="João Paulo" src="https://github.com/jpcmf.png" />
<Avatar
size="md"
name={user?.name}
bgColor="green.300"
// src="https://github.com/jpcmf.png"
/>
</MenuButton>
{session && (
<MenuList bg="gray.900" borderColor="gray.800">
<>
<MenuItem
icon={<RiLogoutCircleLine size={16} />}
onClick={() => signOut()}
color="gray.600"
bg="gray.900"
_hover={{ color: "white" }}
>
Logout
</MenuItem>
<MenuItem>{session.user.about}</MenuItem>
</>
</MenuList>
)}

<MenuList bg="gray.900" borderColor="gray.800">
<>
<MenuItem
icon={<RiLogoutCircleLine size={16} />}
onClick={signOut}
color="gray.600"
bg="gray.900"
_hover={{ color: "white" }}
>
Logout
</MenuItem>
<MenuItem color="gray.600" bg="gray.900" _hover={{ color: "white" }}>
{user?.about}
</MenuItem>
</>
</MenuList>
</Menu>
</Flex>
);
Expand Down
21 changes: 11 additions & 10 deletions src/components/Sidebar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { SidebarNav } from './SidebarNav'
import { useSidebarDrawer } from '../../contexts/SidebarDrawerContext'
import {
Box,
Drawer,
Expand All @@ -8,16 +6,19 @@ import {
DrawerOverlay,
DrawerContent,
DrawerCloseButton,
useBreakpointValue,
} from '@chakra-ui/react'
useBreakpointValue
} from "@chakra-ui/react";

import { SidebarNav } from "./SidebarNav";
import { useSidebarDrawer } from "@/contexts/SidebarDrawerContext";

export function Sidebar() {
const { isOpen, onClose } = useSidebarDrawer()
const { isOpen, onClose } = useSidebarDrawer();

const isDrawerSidebar = useBreakpointValue({
base: true,
lg: false,
})
lg: false
});

if (isDrawerSidebar) {
return (
Expand All @@ -32,12 +33,12 @@ export function Sidebar() {
</DrawerContent>
</DrawerOverlay>
</Drawer>
)
);
}

return (
<Box as="aside" w="64" mr="8">
<Box as="aside" w="64" mr="8" flexShrink={0}>
<SidebarNav />
</Box>
)
);
}
65 changes: 65 additions & 0 deletions src/contexts/AuthContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import Router from "next/router";
import { destroyCookie, parseCookies, setCookie } from "nookies";
import { createContext, useEffect, useState } from "react";

import { signInRequest, userMe } from "../services/auth";

type SignInData = {
email: string;
password: string;
};

type User = {
name: string;
email: string;
about: string;
};

type AuthContextType = {
isAuthenticated: boolean;
user: User | null;
signIn: (data: SignInData) => Promise<void>;
signOut: () => void;
};

export const AuthContext = createContext({} as AuthContextType);

export function AuthProvider({ children }: { children: React.ReactNode }) {
const [user, setUser] = useState<User | null>(null);

const isAuthenticated = !!user;

useEffect(() => {
const { "nextauth.token": token } = parseCookies();

if (token) {
userMe(token)
.then(response => {
setUser(response);
})
.catch(() => {
signOut();
});
}
}, []);

async function signIn({ email, password }: SignInData) {
const { user, jwt } = await signInRequest({ email, password });

setCookie(undefined, "nextauth.token", jwt, {
// maxAge: 60 * 60 * 1 // 1 hour
maxAge: 180 // 3 minutes
});

setUser(user);

Router.push("/dashboard");
}

function signOut() {
destroyCookie(undefined, "nextauth.token");
Router.push("/auth/signin");
}

return <AuthContext.Provider value={{ user, isAuthenticated, signIn, signOut }}>{children}</AuthContext.Provider>;
}
15 changes: 8 additions & 7 deletions src/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { theme } from "../styles/theme";
import { fonts } from "@/lib/fonts";
import { Session } from "next-auth";
import { AppProps } from "next/app";
import { ChakraProvider } from "@chakra-ui/react";
import { SessionProvider } from "next-auth/react";

import { theme } from "@/styles/theme";
import { fonts } from "@/lib/fonts";
import { AuthProvider } from "@/contexts/AuthContext";
import { SidebarDrawerProvider } from "@/contexts/SidebarDrawerContext";

function MyApp({ Component, pageProps }: AppProps<{ session: Session }>) {
function MyApp({ Component, pageProps }: AppProps) {
return (
<>
<style jsx global>
Expand All @@ -16,13 +16,14 @@ function MyApp({ Component, pageProps }: AppProps<{ session: Session }>) {
}
`}
</style>
<SessionProvider session={pageProps.session}>

<AuthProvider>
<ChakraProvider theme={theme}>
<SidebarDrawerProvider>
<Component {...pageProps} />
</SidebarDrawerProvider>
</ChakraProvider>
</SessionProvider>
</AuthProvider>
</>
);
}
Expand Down
37 changes: 17 additions & 20 deletions src/pages/auth/signin.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import * as yup from "yup";
import { Input } from "../../components/Form/Input";
import { Toast } from "@/components/Toast";
import { signIn } from "next-auth/react";
import { useRouter } from "next/router";
import { useContext } from "react";
import { AxiosError } from "axios";
import { yupResolver } from "@hookform/resolvers/yup";
import { LogoSkateHub } from "@/components/LogoSkateHub";
import { SubmitHandler, useForm } from "react-hook-form";
import { Button, Flex, Stack, Text } from "@chakra-ui/react";

import { Input } from "@/components/Form/Input";
import { Toast } from "@/components/Toast";
import { AuthContext } from "@/contexts/AuthContext";
import { LogoSkateHub } from "@/components/LogoSkateHub";

type SignInFormData = {
email: string;
password: string;
Expand All @@ -19,7 +21,7 @@ const signInFormSchema = yup.object().shape({
});

export default function SignIn() {
const router = useRouter();
const { signIn } = useContext(AuthContext);
const { addToast } = Toast();

const { register, handleSubmit, formState } = useForm({
Expand All @@ -29,22 +31,17 @@ export default function SignIn() {
const { errors } = formState;

const handleSignIn: SubmitHandler<SignInFormData> = async values => {
const result = await signIn("credentials", {
redirect: false,
email: values.email,
password: values.password
});
await signIn(values)
.then(_ => {})
.catch((error: AxiosError) => {
console.error("error: ", error.message);

if (result?.status === 200) {
router.replace("/dashboard");
return;
} else {
addToast({
title: "Erro de autenticação.",
message: "Verifique seus dados de login e tente novamente.",
type: "error"
addToast({
title: "Erro de autenticação.",
message: "Verifique seus dados de login e tente novamente.",
type: "error"
});
});
}
};

return (
Expand Down
Loading