React auth provider
This commit is contained in:
parent
02956c9ef1
commit
fef736f547
21 changed files with 200 additions and 122 deletions
|
@ -1,2 +1,2 @@
|
|||
NEXT_PUBLIC_API_URL=API
|
||||
NEXT_PUBLIC_SITE_URL=SITE
|
||||
NEXT_PUBLIC_API_URL=API
|
|
@ -1,11 +1,11 @@
|
|||
import Badge from '@/ui/Badge';
|
||||
'use client';
|
||||
|
||||
export const metadata = {
|
||||
title: 'Mes badges - Peer-at Code'
|
||||
};
|
||||
import { UserContext } from '@/context/user';
|
||||
import Badge from '@/ui/Badge';
|
||||
import { useContext } from 'react';
|
||||
|
||||
export default function Page() {
|
||||
// TODO: Fetch badges from API and display them
|
||||
const { data: me } = useContext(UserContext);
|
||||
return (
|
||||
<div className="flex h-full w-full flex-col space-y-4">
|
||||
<div className="w-full">
|
||||
|
@ -18,15 +18,19 @@ export default function Page() {
|
|||
</header>
|
||||
<main className="flex flex-col justify-between space-x-0 space-y-4">
|
||||
<div className="flex space-x-2">
|
||||
<Badge title="Je suis un teste" path="/assets/badges/java.png" alt="je suis un alt" />
|
||||
<Badge title="Je suis un teste" path="/assets/badges/java.png" alt="je suis un alt" />
|
||||
{me?.badges ? (
|
||||
me?.badges.map((badge, i) => (
|
||||
<Badge
|
||||
title="Peer-at What ?"
|
||||
path="/assets/badges/java.png"
|
||||
type="hard"
|
||||
alt="je suis un alt"
|
||||
earned
|
||||
key={i}
|
||||
name={badge.name}
|
||||
src={badge.logo || '/assets/badges/java.png'}
|
||||
alt={badge.name}
|
||||
level={badge.level}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<p className="text-muted">Aucun badge</p>
|
||||
)}
|
||||
</div>
|
||||
</main>
|
||||
</section>
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
import { type ReactNode } from 'react';
|
||||
|
||||
import { UserProvider } from '@/context/user';
|
||||
import Wrapper from '@/ui/dashboard/Wrapper';
|
||||
import { cookies } from 'next/headers';
|
||||
|
||||
export default function Layout({ children }: { children: ReactNode }) {
|
||||
export default async function Layout({ children }: { children: ReactNode }) {
|
||||
const token = cookies().get('token')!.value;
|
||||
return (
|
||||
<div className="flex h-screen w-full flex-col">
|
||||
<UserProvider token={token}>
|
||||
<Wrapper>{children}</Wrapper>
|
||||
</UserProvider>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
'use client';
|
||||
|
||||
import { useMe } from '@/lib/hooks/use-players';
|
||||
import { UserContext } from '@/context/user';
|
||||
import Card from '@/ui/Card';
|
||||
import cookies from 'js-cookie';
|
||||
import { useContext } from 'react';
|
||||
|
||||
export default function Page() {
|
||||
const token = cookies.get('token');
|
||||
const { data: me, isLoading } = useMe({ token: token! });
|
||||
const { data: me, isLoading } = useContext(UserContext);
|
||||
return (
|
||||
<div className="flex h-full w-full flex-col space-y-4">
|
||||
<div className="w-full">
|
||||
|
@ -19,21 +18,16 @@ export default function Page() {
|
|||
<Card
|
||||
isLoading={isLoading}
|
||||
icon="pie-chart-line"
|
||||
title="Puzzles"
|
||||
title="Puzzles résolus"
|
||||
data={me?.completions}
|
||||
/>
|
||||
<Card
|
||||
isLoading={isLoading}
|
||||
icon="award-line"
|
||||
title="Badges"
|
||||
data={me?.badges || 'Aucun'}
|
||||
/>
|
||||
<Card
|
||||
isLoading={isLoading}
|
||||
icon="bar-chart-line"
|
||||
title="Score (classement plus tard)"
|
||||
data={me?.score}
|
||||
title="Badges obtenus"
|
||||
data={me?.badges?.length || 'Aucun'}
|
||||
/>
|
||||
<Card isLoading={isLoading} icon="bar-chart-line" title="Rang actuel" data={me?.rank} />
|
||||
</main>
|
||||
</section>
|
||||
</div>
|
||||
|
|
20
context/user.tsx
Normal file
20
context/user.tsx
Normal file
|
@ -0,0 +1,20 @@
|
|||
'use client';
|
||||
|
||||
import { useMe } from '@/lib/hooks/use-players';
|
||||
import type { Player } from '@/lib/players';
|
||||
import { createContext, type ReactNode } from 'react';
|
||||
|
||||
export const UserContext = createContext<{
|
||||
data: Player | null | undefined;
|
||||
isLoading: boolean;
|
||||
error: Error | null;
|
||||
}>({
|
||||
data: null,
|
||||
isLoading: true,
|
||||
error: null
|
||||
});
|
||||
|
||||
export const UserProvider = ({ token, children }: { token: string; children: ReactNode }) => {
|
||||
const { data, isLoading, error } = useMe({ token });
|
||||
return <UserContext.Provider value={{ data, isLoading, error }}>{children}</UserContext.Provider>;
|
||||
};
|
|
@ -2,9 +2,7 @@ import useSWR from 'swr';
|
|||
import { getPlayer } from '../players';
|
||||
|
||||
export function useMe({ token }: { token: string }) {
|
||||
return useSWR('me', () => getPlayer({ token }), {
|
||||
revalidateOnReconnect: false
|
||||
});
|
||||
return useSWR('me', () => getPlayer({ token }));
|
||||
}
|
||||
|
||||
export function usePlayer({ token, username }: { token: string; username: string }) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import fetcher from './fetcher';
|
||||
import type { Group } from './players';
|
||||
|
||||
export const getScores = async ({ token }: { token: string }): Promise<Score[]> => {
|
||||
const { data, status } = await fetcher.get(`/leaderboard`, {
|
||||
|
@ -25,6 +26,7 @@ export type Score = {
|
|||
tries: number;
|
||||
completions: number;
|
||||
pseudo: string;
|
||||
group: string;
|
||||
groups: Group[];
|
||||
avatar: string;
|
||||
rank: number;
|
||||
};
|
||||
|
|
|
@ -48,6 +48,6 @@ export const navItems: NavItem[] = [
|
|||
name: 'Paramètres',
|
||||
slug: 'settings',
|
||||
icon: 'equalizer-line',
|
||||
disabled: false
|
||||
disabled: true
|
||||
}
|
||||
];
|
||||
|
|
|
@ -28,14 +28,26 @@ export const getPlayer = async ({
|
|||
|
||||
export type Player = {
|
||||
email: string;
|
||||
pseudo: string;
|
||||
firstnames: string;
|
||||
lastname: string;
|
||||
description: string;
|
||||
avatar: string;
|
||||
group: string;
|
||||
groups: Group[];
|
||||
score: number;
|
||||
tries: number;
|
||||
completions: number;
|
||||
pseudo: string;
|
||||
badges: any[];
|
||||
rank: number;
|
||||
badges: Badge[] | null;
|
||||
};
|
||||
|
||||
export type Badge = {
|
||||
name: string;
|
||||
level: number;
|
||||
logo?: string;
|
||||
};
|
||||
|
||||
export type Group = {
|
||||
name: string;
|
||||
chapter?: number;
|
||||
};
|
||||
|
|
|
@ -7,7 +7,7 @@ export const getChapters = async ({ token }: { token: string }): Promise<Chapter
|
|||
}
|
||||
});
|
||||
|
||||
let chapters = data;
|
||||
const chapters = data;
|
||||
|
||||
if (status !== 200) {
|
||||
throw new Error('Failed to fetch puzzles');
|
||||
|
@ -17,8 +17,6 @@ export const getChapters = async ({ token }: { token: string }): Promise<Chapter
|
|||
return [];
|
||||
}
|
||||
|
||||
chapters = chapters.filter((chapter: Chapter) => chapter.id !== 0);
|
||||
|
||||
return chapters as Chapter[];
|
||||
};
|
||||
|
||||
|
@ -48,24 +46,17 @@ export const getChapter = async ({
|
|||
return chapter as Chapter;
|
||||
};
|
||||
|
||||
export const getPuzzles = async ({
|
||||
token
|
||||
}: {
|
||||
token: string;
|
||||
}): Promise<{ chapters: Chapter[]; puzzles: Puzzle[] }> => {
|
||||
export const getPuzzles = async ({ token }: { token: string }): Promise<Chapter[]> => {
|
||||
const chapters = await getChapters({ token });
|
||||
const puzzles: Puzzle[] = [];
|
||||
|
||||
for (const chapter of chapters) {
|
||||
const puzzlesByChapter = await getChapter({ token, id: chapter.id });
|
||||
if (!puzzlesByChapter?.puzzles) continue;
|
||||
puzzles.push(...puzzlesByChapter!.puzzles);
|
||||
for (let i = 0; i < chapters.length; i++) {
|
||||
const chapter = chapters[i];
|
||||
const chapterData = await getChapter({ token, id: chapter.id });
|
||||
if (!chapterData) continue;
|
||||
chapters[i].puzzles = chapterData.puzzles;
|
||||
}
|
||||
|
||||
return {
|
||||
chapters: chapters as Chapter[],
|
||||
puzzles: puzzles as Puzzle[]
|
||||
};
|
||||
return chapters as Chapter[];
|
||||
};
|
||||
|
||||
export const getPuzzle = async ({ token, id }: { token: string; id: number }): Promise<Puzzle> => {
|
||||
|
@ -92,10 +83,17 @@ export type Puzzle = {
|
|||
id: number;
|
||||
name: string;
|
||||
content: string;
|
||||
tags: Tag[] | null;
|
||||
};
|
||||
|
||||
export type Chapter = {
|
||||
name: string;
|
||||
id: number;
|
||||
name: string;
|
||||
puzzles: Puzzle[];
|
||||
startDay?: string;
|
||||
endDay?: string;
|
||||
};
|
||||
|
||||
export type Tag = {
|
||||
name: string;
|
||||
};
|
||||
|
|
|
@ -9,10 +9,6 @@ import { getURL } from './lib/utils';
|
|||
export async function middleware(req: NextRequest) {
|
||||
const res = NextResponse.next();
|
||||
|
||||
// on donne accès à l'API depuis n'importe quelle origine
|
||||
res.headers.set('Access-Control-Allow-Origin', '*');
|
||||
res.headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
|
||||
|
||||
const token = req.cookies.get('token')?.value;
|
||||
|
||||
if (req.nextUrl.pathname.includes('dashboard') && !token)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"name": "peer-at-code",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 364 KiB After Width: | Height: | Size: 1.2 MiB |
|
@ -1,3 +1,4 @@
|
|||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const defaultTheme = require('tailwindcss/defaultTheme');
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
|
|
37
ui/Badge.tsx
37
ui/Badge.tsx
|
@ -2,42 +2,37 @@ import Image from 'next/image';
|
|||
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
export type Difficulty = 'easy' | 'medium' | 'hard';
|
||||
|
||||
export const DIFFICULTY = {
|
||||
1: 'easy',
|
||||
2: 'medium',
|
||||
3: 'hard'
|
||||
}
|
||||
export const DIFFICULTY_COLOR = {
|
||||
1: 'green',
|
||||
2: 'yellow',
|
||||
3: 'red'
|
||||
};
|
||||
|
||||
export default function Badge({
|
||||
title,
|
||||
path,
|
||||
name,
|
||||
src,
|
||||
alt,
|
||||
type = 'easy',
|
||||
earned = false
|
||||
level
|
||||
}: {
|
||||
title: string;
|
||||
path: string;
|
||||
name: string;
|
||||
src: string;
|
||||
alt: string;
|
||||
type?: Difficulty;
|
||||
earned?: boolean;
|
||||
level: number;
|
||||
}) {
|
||||
return (
|
||||
<div className="flex w-24 flex-col space-y-2 text-center">
|
||||
<Image
|
||||
src={path}
|
||||
src={`data:image;base64,${src}`}
|
||||
alt={alt}
|
||||
className={cn(`rounded-full border-2 lg:border-4`, {
|
||||
'border-green-600': type === 'easy',
|
||||
'border-yellow-600': type === 'medium',
|
||||
'border-red-600': type === 'hard',
|
||||
'border-gray-600 opacity-40': !earned
|
||||
'border-green-600': level === 1,
|
||||
'border-yellow-600': level === 2,
|
||||
'border-red-600': level === 3
|
||||
})}
|
||||
width={500}
|
||||
height={500}
|
||||
/>
|
||||
<span className="text-sm font-semibold">{earned ? title : '****'}</span>
|
||||
<span className="text-sm font-semibold">{name}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { forwardRef } from 'react';
|
||||
import ErrorMessage from './ErrorMessage';
|
||||
import Icon from './Icon';
|
||||
import Label from './Label';
|
||||
|
||||
const Input = forwardRef<
|
||||
|
|
|
@ -6,22 +6,23 @@ import { useMemo, useState } from 'react';
|
|||
import AvatarComponent from './Avatar';
|
||||
import Select from './Select';
|
||||
|
||||
const scoreColors = ['text-yellow-400', 'text-gray-400', 'text-orange-400'];
|
||||
const SCORE_COLORS = ['text-yellow-400', 'text-gray-400', 'text-orange-400'];
|
||||
|
||||
export default function Leaderboard({ token }: { token: string }) {
|
||||
const { data, isLoading } = useLeaderboard({ token });
|
||||
|
||||
const [filter, setFilter] = useState('');
|
||||
|
||||
let options;
|
||||
let options = [] as { value: string; title: string }[];
|
||||
|
||||
if (data) {
|
||||
options = data
|
||||
.filter((score, index, self) => {
|
||||
return index === self.findIndex((t) => t.group === score.group) && score.group !== '';
|
||||
})
|
||||
.sort((a, b) => (a.group > b.group ? 1 : -1))
|
||||
.map((score) => ({ value: score.group, title: score.group }));
|
||||
.filter((score) => score.groups && score.groups.length > 0)
|
||||
.map((score) => score.groups.map((group) => ({ value: group.name, title: group.name })))
|
||||
.flat()
|
||||
.filter((group, index, self) => self.findIndex((g) => g.value === group.value) === index)
|
||||
.sort((a, b) => a.title.localeCompare(b.title));
|
||||
|
||||
options.unshift({ value: '', title: 'Tous' });
|
||||
options.push({ value: 'no-group', title: 'Sans groupe' });
|
||||
}
|
||||
|
@ -29,9 +30,9 @@ export default function Leaderboard({ token }: { token: string }) {
|
|||
const filteredData = useMemo(() => {
|
||||
if (filter) {
|
||||
if (filter === 'no-group') {
|
||||
return data?.filter((score) => score.group === '');
|
||||
return data?.filter((score) => !score.groups || score.groups.length === 0);
|
||||
}
|
||||
return data?.filter((score) => score.group === filter);
|
||||
return data?.filter((score) => score.groups?.find((group) => group.name === filter));
|
||||
}
|
||||
return data;
|
||||
}, [data, filter]);
|
||||
|
@ -65,12 +66,16 @@ export default function Leaderboard({ token }: { token: string }) {
|
|||
filteredData?.map((score, key) => (
|
||||
<li key={key} className="flex justify-between space-x-2">
|
||||
<div className="flex items-center space-x-4">
|
||||
<span className={cn('font-semibold', scoreColors[key])}>{key + 1}</span>
|
||||
<span className={cn('font-semibold', SCORE_COLORS[score.rank - 1])}>
|
||||
{score.rank}
|
||||
</span>
|
||||
<div className="flex items-center space-x-2">
|
||||
<AvatarComponent name={score.pseudo} src={score.avatar} className="h-9 w-9" />
|
||||
<div className="flex flex-col gap-x-2 sm:flex-row sm:items-center">
|
||||
<span className="text-lg">{score.pseudo}</span>
|
||||
<span className="text-sm text-muted">{score.group}</span>
|
||||
<span className="text-sm text-muted">
|
||||
{score.groups?.map((g) => g.name).join(', ')}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,30 +1,82 @@
|
|||
'use client';
|
||||
|
||||
import { usePuzzles } from '@/lib/hooks/use-puzzles';
|
||||
import { type Chapter } from '@/lib/puzzles';
|
||||
import { cn } from '@/lib/utils';
|
||||
import AppLink from './AppLink';
|
||||
import Icon from './Icon';
|
||||
|
||||
export default function Puzzles({ token }: { token: string }) {
|
||||
const { data, isLoading } = usePuzzles({ token });
|
||||
console.log(data);
|
||||
|
||||
// SOme chapters have a start date and a end date (for example, the first chapter is only available for 2 weeks), I want to want to lock the chapter if the current date is not between the start and end date
|
||||
// I want to display a message to the user if the chapter is locked
|
||||
|
||||
function isChapterLocked(chapter: Chapter) {
|
||||
return (
|
||||
chapter.startDay &&
|
||||
chapter.endDay &&
|
||||
new Date() > new Date(chapter.startDay) &&
|
||||
new Date() < new Date(chapter.endDay)
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{(!isLoading &&
|
||||
data?.chapters?.map((chapter) => (
|
||||
data?.map((chapter) => (
|
||||
<div key={chapter.id} className="flex flex-col space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<h3 className="text-xl font-semibold sm:text-2xl">
|
||||
Chapitre {chapter.id} - {chapter.name}
|
||||
Chapitre {chapter.id} - {chapter.name}{' '}
|
||||
</h3>
|
||||
<div className="h-1 w-1/4 rounded-lg bg-gray-200">
|
||||
<div className="h-1 w-1/2 rounded-lg bg-gradient-to-tl from-brand to-brand-accent" />
|
||||
</div>
|
||||
</div>
|
||||
<ul className="flex flex-col space-y-4">
|
||||
{data?.puzzles.map((puzzle) => (
|
||||
<ul
|
||||
className={cn('flex flex-col space-y-4', {
|
||||
// If the chapter is locked i want to add a class to li children to make them unclickable
|
||||
'pointer-events-none': isChapterLocked(chapter)
|
||||
})}
|
||||
>
|
||||
{chapter.puzzles &&
|
||||
chapter.puzzles.map((puzzle) => (
|
||||
<AppLink key={puzzle.id} href={`/dashboard/puzzles/${puzzle.id}`}>
|
||||
<li className="group flex items-center justify-between rounded-md bg-primary-700 p-4 font-code hover:bg-primary-600">
|
||||
<li
|
||||
className={cn(
|
||||
'group flex items-center justify-between rounded-md border-2 bg-primary-700 p-4 font-code hover:bg-primary-600',
|
||||
{
|
||||
'border-green-600/30': puzzle.tags
|
||||
?.map((tag) => tag.name.toLowerCase())
|
||||
.includes('easy'),
|
||||
'border-yellow-600/30': puzzle.tags
|
||||
?.map((tag) => tag.name.toLowerCase())
|
||||
.includes('medium'),
|
||||
'border-red-600/30': puzzle.tags
|
||||
?.map((tag) => tag.name.toLowerCase())
|
||||
.includes('hard'),
|
||||
'border-highlight-secondary/30': !puzzle.tags?.length
|
||||
}
|
||||
)}
|
||||
>
|
||||
<div className="flex gap-x-2">
|
||||
<span className="text-base font-semibold">{puzzle.name}</span>
|
||||
{puzzle.tags?.length && (
|
||||
<div className="flex gap-x-2 text-sm text-muted">
|
||||
{puzzle.tags
|
||||
.filter((tag) => !['easy', 'medium', 'hard'].includes(tag.name))
|
||||
.map((tag, i) => (
|
||||
<span
|
||||
key={i}
|
||||
className={cn('inline-block rounded-md bg-primary-900 px-2 py-1')}
|
||||
>
|
||||
{tag.name}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<Icon
|
||||
className="-translate-x-2 transform-gpu duration-300 group-hover:translate-x-0"
|
||||
name="arrow-right-line"
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { forwardRef } from 'react';
|
||||
import type { UseFormRegister } from 'react-hook-form';
|
||||
import ErrorMessage from './ErrorMessage';
|
||||
import Label from './Label';
|
||||
|
||||
|
@ -17,7 +16,7 @@ const Select = forwardRef<
|
|||
<Label label={label} description={description} required={props.required} className={className}>
|
||||
<select
|
||||
className={
|
||||
'w-full cursor-pointer overflow-hidden rounded-lg border-2 border-highlight-primary bg-transparent px-5 py-2.5 text-sm font-medium text-secondary opacity-80 outline-none transition-opacity hover:opacity-100 disabled:opacity-50'
|
||||
'w-full cursor-pointer overflow-hidden rounded-lg border-2 border-highlight-primary bg-transparent px-5 py-2.5 text-sm font-medium text-secondary opacity-80 outline-none outline-0 transition-opacity hover:opacity-100 focus:outline-none focus:ring-1 focus:ring-brand disabled:opacity-50'
|
||||
}
|
||||
{...props}
|
||||
ref={ref}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import { NavItem, navItems } from '@/lib/nav-items';
|
||||
import { cn } from '@/lib/utils';
|
||||
import Image from 'next/image';
|
||||
import { useSelectedLayoutSegment } from 'next/navigation';
|
||||
import AppLink from '../AppLink';
|
||||
import Icon from '../Icon';
|
||||
|
@ -18,12 +19,12 @@ export default function Sidenav({ isOpen, toggle }: { isOpen: boolean; toggle: (
|
|||
)}
|
||||
>
|
||||
<div className="flex h-full flex-col">
|
||||
<div className="flex p-6">
|
||||
<AppLink className="truncate" href="/">
|
||||
<h1>Peer-at Code</h1>
|
||||
<div className="flex w-full justify-center p-[9px]">
|
||||
<AppLink href="/">
|
||||
<Image src="/assets/brand/peerat.png" alt="Peer-at" width={50} height={50} />
|
||||
</AppLink>
|
||||
</div>
|
||||
<div className=" px-4 ">
|
||||
<div className="px-4">
|
||||
<hr className="border-highlight-primary" />
|
||||
</div>
|
||||
<div className="px-4 pt-4">
|
||||
|
@ -76,7 +77,7 @@ function NavItem({
|
|||
className={cn('flex justify-center rounded-md px-3 py-3 text-sm lg:justify-start', {
|
||||
'text-muted hover:text-secondary': !isActive,
|
||||
'bg-highlight-primary text-secondary': isActive,
|
||||
'text-gray-600 hover:text-gray-600': item.disabled,
|
||||
'cursor-not-allowed text-gray-600 hover:text-gray-600': item.disabled,
|
||||
'justify-center lg:justify-start': isOpen,
|
||||
'justify-start sm:justify-center': !isOpen
|
||||
})}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
'use client';
|
||||
|
||||
import { useMe } from '@/lib/hooks/use-players';
|
||||
import { UserContext } from '@/context/user';
|
||||
import { titleCase } from '@/lib/utils';
|
||||
import cookies from 'js-cookie';
|
||||
import { useRouter, useSelectedLayoutSegment } from 'next/navigation';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
import AvatarComponent from '../Avatar';
|
||||
import Icon from '../Icon';
|
||||
import Popover from '../Popover';
|
||||
|
@ -14,9 +14,7 @@ export default function Usernav({ isOpen, toggle }: { isOpen: boolean; toggle: (
|
|||
const router = useRouter();
|
||||
const segment = useSelectedLayoutSegment();
|
||||
|
||||
const token = cookies.get('token');
|
||||
|
||||
const { data: me, isLoading } = useMe({ token: token! });
|
||||
const { data: me, isLoading } = useContext(UserContext);
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
|
|
Loading…
Add table
Reference in a new issue