Skip to content

Commit

Permalink
Merge pull request #235 from RMoodsTeam/227-migrate-user-profile-page…
Browse files Browse the repository at this point in the history
…-to-tanstack-query

227 migrate user profile page to tanstack query
  • Loading branch information
SebastianNowak01 authored Dec 8, 2024
2 parents 1100994 + 75c046b commit 6ff1d45
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 67 deletions.
4 changes: 2 additions & 2 deletions frontend/src/components/navbar/RateLimitStatus.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useQuery, useQueryClient } from '@tanstack/react-query';
import authFetch from '../../rmoods/client/authFetch.ts';
import { Center, HoverCard, Progress, Stack, Text } from '@mantine/core';
import { Center, HoverCard, Loader, Progress, Stack, Text } from '@mantine/core';
import { IconBrandReddit } from '@tabler/icons-react';
import React, { useEffect } from 'react';
import dayjs from 'dayjs';
Expand Down Expand Up @@ -104,7 +104,7 @@ const RateLimitStatus = () => {
});

if (query.isLoading) {
return <div>Loading...</div>;
return <Loader color="blue" size={20} />;
}

if (query.isError) {
Expand Down
70 changes: 34 additions & 36 deletions frontend/src/components/navbar/UserMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import Cookies from 'js-cookie';
import { useNavigate } from 'react-router-dom';
import { Avatar, Menu } from '@mantine/core';
import authFetch from '../../rmoods/client/authFetch.ts';
import { useEffect, useState } from 'react';
import { jwtDecode } from 'jwt-decode';
import { JwtClaims } from '../../rmoods/jwt.ts';
import { changeDefaultGoogleProfilePictureSize } from '../../utility/changeDefaultGoogleProfilePictureSize.ts';
import { useQuery } from '@tanstack/react-query';

/**
* User interface representing the user data.
Expand All @@ -15,56 +15,54 @@ interface User {
picture: string;
}

/**
* Fetches the user data from the server.
* @returns {Promise<User>} The user data.
*/
const fetchUserData = async (): Promise<User> => {
const token = Cookies.get('RMOODS_JWT');
if (!token) {
throw new Error('No JWT token found');
}

const data = jwtDecode<JwtClaims>(token);
const id = data.userInfo.id;
const response = await authFetch(`http://localhost:8001/api/user?id=${id}`);
if (!response.ok) {
throw new Error('Failed to fetch user data');
}

return response.json();
};


/**
* UserMenu component that displays the user menu.
* @returns {JSX.Element} The UserMenu component.
*/
const UserMenu = () => {
const navigate = useNavigate();
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);

useEffect(() => {
const token = Cookies.get('RMOODS_JWT');
if (!token) {
navigate('/login');
return;
}

let isMounted = true;
try {
const data = jwtDecode<JwtClaims>(token);
const id = data.userInfo.id;

authFetch('http://localhost:8001/api/user?id=' + id).then((response) => {
response.json().then((data) => {
if (isMounted) {
setUser(data);
setLoading(false);
}
});
});
} catch (error) {
console.error('JWT token could not be decoded.', error);
if (isMounted) {
setLoading(false);
}
}
return () => {
isMounted = false;
};
}, [navigate]);
const { data, error } = useQuery<User, Error>({
queryKey: ['userData'],
queryFn: fetchUserData,
refetchInterval: 5000,
});

const handleLogout = () => {
console.log('Logging out');
Cookies.remove('RMOODS_JWT');
navigate('/login');
};

if (error) {
throw new Error('Failed to fetch user data');
}

const size = 45;
const resizedPicture = user
? changeDefaultGoogleProfilePictureSize(user.picture, size)
const resizedPicture = data?.picture
? changeDefaultGoogleProfilePictureSize(data.picture, size)
: '';

return (
<Menu id="user-dropdown">
<Menu.Target>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/routes/user/UserCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const UserCard: React.FC<UserCardProps> = ({ user }) => {
{user.name}
</Title>
<Text size='sm' c='dimmed' style={{ fontSize: '18px' }}>
{user.givenName}
{user.given_name}
</Text>
<Divider my='sm' />
<Text size='sm' c='dimmed' style={{ fontSize: '18px' }}>
Expand Down
73 changes: 45 additions & 28 deletions frontend/src/routes/user/page.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { Box, Text } from '@mantine/core';
import { Box, Text, Loader } from '@mantine/core';
import Cookies from 'js-cookie';
import { jwtDecode } from 'jwt-decode';
import { useEffect, useState } from 'react';
import UserCard from './UserCard';
import StatisticItem from './StatisticItem';
import { JwtClaims } from '../../rmoods/jwt.ts';
import authFetch from '../../rmoods/client/authFetch.ts';
import { useQuery } from '@tanstack/react-query';

/**
* User interface representing the user data.
*/
export interface User {
name: string;
givenName: string;
given_name: string;
email: string;
picture: string;
}
Expand All @@ -31,37 +31,54 @@ const statistics = {
longestReportTime: '2 hours',
};

/**
* Fetches the user data from the server.
* @returns {Promise<User>} The user data.
*/
const fetchUserData = async (): Promise<User> => {
const token = Cookies.get('RMOODS_JWT');
if (!token) {
throw new Error('No JWT token found');
}

const data = jwtDecode<JwtClaims>(token);
const id = data.userInfo.id;
const response = await authFetch(`http://localhost:8001/api/user?id=${id}`);
if (!response.ok) {
throw new Error('Failed to fetch user data');
}

return response.json();
};

/**
* UserPage component that displays the user's profile and statistics.
* @returns {JSX.Element} The UserPage component.
*/
const UserPage = () => {
const [user, setUser] = useState<User | null>(null);

useEffect(() => {
const token = Cookies.get('RMOODS_JWT');
if (!token) {
console.error('No JWT token found');
throw new Error('No JWT token found');
}
const { data, error, isLoading } = useQuery<User, Error>({
queryKey: ['userData'],
queryFn: fetchUserData,
refetchInterval: 5000,
});

try {
const data = jwtDecode<JwtClaims>(token);
const id = data.userInfo.id;

authFetch('http://localhost:8001/api/user?id=' + id).then((response) => {
response.json().then((data) => {
setUser(data);
});
});
} catch (error) {
console.error('JWT token could not be decoded.', error);
throw new Error('JWT token could not be decoded.');
}
}, []);
if (isLoading) {
return (
<Box
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '50vh',
}}
>
<Loader color="blue" size={40} />
</Box>
);
}

if (!user) {
return <Text>Loading...</Text>;
if (error) {
return <Text>Error: {error.message}</Text>;
}

return (
Expand All @@ -73,7 +90,7 @@ const UserPage = () => {
}}
>
<Box style={{ flex: '0 0 350px', marginRight: '20px' }}>
<UserCard user={user} />
{data && <UserCard user={data} />}
</Box>
<Box style={{ flex: '1', display: 'flex', flexWrap: 'wrap' }}>
<Box style={{ flex: '1 1 50%', padding: '10px' }}>
Expand Down

0 comments on commit 6ff1d45

Please sign in to comment.