This repository has no description
1'use client';
2
3import { useEffect, useState, useMemo, useCallback } from 'react';
4import { useRouter } from 'next/navigation';
5import { ApiClient } from '@/api-client/ApiClient';
6import { getAccessToken } from '@/services/auth';
7import UrlCard from '@/features/cards/components/urlCard/UrlCard';
8import type { GetMyUrlCardsResponse } from '@/api-client/types';
9import {
10 Button,
11 Group,
12 Loader,
13 SimpleGrid,
14 Stack,
15 Title,
16 Text,
17} from '@mantine/core';
18
19export default function DashboardPage() {
20 const [urlCards, setUrlCards] = useState<GetMyUrlCardsResponse['cards']>([]);
21 const [loading, setLoading] = useState(true);
22 const [cardsLoading, setCardsLoading] = useState(true);
23 const router = useRouter();
24
25 // Memoize API client instance to prevent recreation on every render
26 const apiClient = useMemo(
27 () =>
28 new ApiClient(
29 process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:3000',
30 () => getAccessToken(),
31 ),
32 [],
33 );
34
35 // Memoize the fetch function to prevent useEffect from running on every render
36 const fetchData = useCallback(async () => {
37 try {
38 // Fetch URL cards
39 setCardsLoading(true);
40 const cardsResponse = await apiClient.getMyUrlCards({ limit: 10 });
41 setUrlCards(cardsResponse.cards);
42 } catch (error) {
43 console.error('Error fetching data:', error);
44 } finally {
45 setLoading(false);
46 setCardsLoading(false);
47 }
48 }, [apiClient]);
49
50 useEffect(() => {
51 fetchData();
52 }, [fetchData]);
53
54 if (loading) {
55 return <Loader />;
56 }
57
58 return (
59 <div>
60 {/* Recent Cards Section */}
61 <Stack>
62 {cardsLoading ? (
63 <Loader />
64 ) : urlCards.length > 0 ? (
65 <SimpleGrid
66 cols={{ base: 1, xs: 2, sm: 3, lg: 4, xl: 5 }}
67 spacing={'md'}
68 >
69 {urlCards.map((card) => (
70 <UrlCard
71 key={card.id}
72 id={card.id}
73 url={card.url}
74 cardContent={card.cardContent}
75 note={card.note}
76 collections={card.collections}
77 />
78 ))}
79 </SimpleGrid>
80 ) : (
81 <Stack align="center" gap={'xs'}>
82 <Text c={'grey'}>No cards yet</Text>
83 <Button onClick={() => router.push('/cards/add')}>
84 Add Your First Card
85 </Button>
86 </Stack>
87 )}
88 </Stack>
89 </div>
90 );
91}