Files
zod-backend/client/src/components/juniors/JuniorsList.tsx
2025-01-07 01:46:58 -05:00

122 lines
3.2 KiB
TypeScript

import React, { useEffect, useState } from 'react';
import {
Box,
Typography,
Grid,
Card,
CardContent,
CardMedia,
Button,
CircularProgress,
Pagination
} from '@mui/material';
import { juniorsApi } from '../../api/client';
import { Junior, PaginatedResponse } from '../../types/junior';
import { useNavigate } from 'react-router-dom';
export const JuniorsList = () => {
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
const [juniors, setJuniors] = useState<Junior[]>([]);
const [page, setPage] = useState(1);
const [totalPages, setTotalPages] = useState(1);
const navigate = useNavigate();
const fetchJuniors = async (pageNum: number) => {
try {
setLoading(true);
const response = await juniorsApi.getJuniors(pageNum);
const data = response.data as PaginatedResponse<Junior>;
setJuniors(data.data);
setTotalPages(data.meta.pageCount);
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to load juniors');
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchJuniors(page);
}, [page]);
const handlePageChange = (event: React.ChangeEvent<unknown>, value: number) => {
setPage(value);
};
if (loading) {
return (
<Box display="flex" justifyContent="center" alignItems="center" minHeight="200px">
<CircularProgress />
</Box>
);
}
if (error) {
return (
<Box p={3}>
<Typography color="error">{error}</Typography>
</Box>
);
}
return (
<Box p={3}>
<Box display="flex" justifyContent="space-between" alignItems="center" mb={3}>
<Typography variant="h4">Juniors</Typography>
<Button
variant="contained"
color="primary"
onClick={() => navigate('/juniors/new')}
>
Add Junior
</Button>
</Box>
<Grid container spacing={3}>
{juniors.map((junior) => (
<Grid item xs={12} sm={6} md={4} key={junior.id}>
<Card>
<CardMedia
component="img"
height="140"
image={junior.profilePicture?.url || '/default-avatar.png'}
alt={junior.fullName}
sx={{ objectFit: 'contain', bgcolor: 'grey.100' }}
/>
<CardContent>
<Typography variant="h6" gutterBottom>
{junior.fullName}
</Typography>
<Typography color="textSecondary">
{junior.relationship}
</Typography>
<Box mt={2}>
<Button
variant="outlined"
fullWidth
onClick={() => navigate(`/juniors/${junior.id}`)}
>
View Details
</Button>
</Box>
</CardContent>
</Card>
</Grid>
))}
</Grid>
{totalPages > 1 && (
<Box display="flex" justifyContent="center" mt={4}>
<Pagination
count={totalPages}
page={page}
onChange={handlePageChange}
color="primary"
/>
</Box>
)}
</Box>
);
};