mirror of
https://github.com/HamzaSha1/zod-backend.git
synced 2025-08-25 05:42:27 +00:00
122 lines
3.2 KiB
TypeScript
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>
|
|
);
|
|
};
|