|
|
|
@@ -0,0 +1,178 @@ |
|
|
|
"use client"; |
|
|
|
|
|
|
|
import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react'; |
|
|
|
import { |
|
|
|
Box, |
|
|
|
Typography, |
|
|
|
FormControl, |
|
|
|
InputLabel, |
|
|
|
Select, |
|
|
|
MenuItem, |
|
|
|
Card, |
|
|
|
CardContent, |
|
|
|
Stack, |
|
|
|
Table, |
|
|
|
TableBody, |
|
|
|
TableCell, |
|
|
|
TableContainer, |
|
|
|
TableHead, |
|
|
|
TableRow, |
|
|
|
Paper, |
|
|
|
CircularProgress, |
|
|
|
Chip |
|
|
|
} from '@mui/material'; |
|
|
|
import { useTranslation } from 'react-i18next'; |
|
|
|
import dayjs from 'dayjs'; |
|
|
|
|
|
|
|
// Placeholder interface - to be defined when implementing details |
|
|
|
interface GoodsReceiptStatusItem { |
|
|
|
id: string; |
|
|
|
// Add fields as needed when implementing |
|
|
|
} |
|
|
|
|
|
|
|
const GoodsReceiptStatus: React.FC = () => { |
|
|
|
const { t } = useTranslation("dashboard"); |
|
|
|
const [selectedFilter, setSelectedFilter] = useState<string>(""); |
|
|
|
const [data, setData] = useState<GoodsReceiptStatusItem[]>([]); |
|
|
|
const [loading, setLoading] = useState<boolean>(false); |
|
|
|
const [currentTime, setCurrentTime] = useState<dayjs.Dayjs | null>(null); |
|
|
|
const [isClient, setIsClient] = useState<boolean>(false); |
|
|
|
|
|
|
|
// Set client flag and time on mount |
|
|
|
useEffect(() => { |
|
|
|
setIsClient(true); |
|
|
|
setCurrentTime(dayjs()); |
|
|
|
}, []); |
|
|
|
|
|
|
|
// Load data from API - placeholder for now |
|
|
|
const loadData = useCallback(async () => { |
|
|
|
try { |
|
|
|
// TODO: Implement API call when ready |
|
|
|
// const result = await fetchGoodsReceiptStatusClient(); |
|
|
|
// setData(result); |
|
|
|
setData([]); |
|
|
|
} catch (error) { |
|
|
|
console.error('Error fetching goods receipt status:', error); |
|
|
|
} finally { |
|
|
|
setLoading(false); |
|
|
|
} |
|
|
|
}, []); |
|
|
|
|
|
|
|
// Initial load and auto-refresh every 5 minutes |
|
|
|
useEffect(() => { |
|
|
|
loadData(); |
|
|
|
|
|
|
|
const refreshInterval = setInterval(() => { |
|
|
|
loadData(); |
|
|
|
}, 5 * 60 * 1000); // 5 minutes |
|
|
|
|
|
|
|
return () => clearInterval(refreshInterval); |
|
|
|
}, [loadData]); |
|
|
|
|
|
|
|
// Update current time every 1 minute |
|
|
|
useEffect(() => { |
|
|
|
if (!isClient) return; |
|
|
|
|
|
|
|
const timeInterval = setInterval(() => { |
|
|
|
setCurrentTime(dayjs()); |
|
|
|
}, 60 * 1000); // 1 minute |
|
|
|
|
|
|
|
return () => clearInterval(timeInterval); |
|
|
|
}, [isClient]); |
|
|
|
|
|
|
|
// Filter data by selected filter |
|
|
|
const filteredData = useMemo(() => { |
|
|
|
if (!selectedFilter) return data; |
|
|
|
return data.filter(item => true); // TODO: Implement filter logic |
|
|
|
}, [data, selectedFilter]); |
|
|
|
|
|
|
|
return ( |
|
|
|
<Card sx={{ mb: 2 }}> |
|
|
|
<CardContent> |
|
|
|
{/* Title */} |
|
|
|
<Typography variant="h5" sx={{ mb: 3, fontWeight: 600 }}> |
|
|
|
{t("Goods Receipt Status")} |
|
|
|
</Typography> |
|
|
|
|
|
|
|
{/* Filter */} |
|
|
|
<Stack direction="row" spacing={2} sx={{ mb: 3 }}> |
|
|
|
<FormControl sx={{ minWidth: 150 }} size="small"> |
|
|
|
<InputLabel id="filter-select-label" shrink={true}> |
|
|
|
{t("Filter")} |
|
|
|
</InputLabel> |
|
|
|
<Select |
|
|
|
labelId="filter-select-label" |
|
|
|
id="filter-select" |
|
|
|
value={selectedFilter} |
|
|
|
label={t("Filter")} |
|
|
|
onChange={(e) => setSelectedFilter(e.target.value)} |
|
|
|
displayEmpty |
|
|
|
> |
|
|
|
<MenuItem value="">{t("All")}</MenuItem> |
|
|
|
{/* TODO: Add filter options when implementing */} |
|
|
|
</Select> |
|
|
|
</FormControl> |
|
|
|
|
|
|
|
<Typography variant="body2" sx={{ alignSelf: 'center', color: 'text.secondary' }}> |
|
|
|
{t("Auto-refresh every 5 minutes")} | {t("Last updated")}: {isClient && currentTime ? currentTime.format('HH:mm:ss') : '--:--:--'} |
|
|
|
</Typography> |
|
|
|
</Stack> |
|
|
|
|
|
|
|
{/* Table */} |
|
|
|
<Box sx={{ mt: 2 }}> |
|
|
|
{loading ? ( |
|
|
|
<Box sx={{ display: 'flex', justifyContent: 'center', p: 3 }}> |
|
|
|
<CircularProgress /> |
|
|
|
</Box> |
|
|
|
) : ( |
|
|
|
<TableContainer component={Paper}> |
|
|
|
<Table size="small" sx={{ minWidth: 1200 }}> |
|
|
|
<TableHead> |
|
|
|
<TableRow sx={{ backgroundColor: 'grey.100' }}> |
|
|
|
<TableCell sx={{ fontWeight: 600 }}>{t("Column 1")}</TableCell> |
|
|
|
<TableCell sx={{ fontWeight: 600 }}>{t("Column 2")}</TableCell> |
|
|
|
<TableCell sx={{ fontWeight: 600 }}>{t("Column 3")}</TableCell> |
|
|
|
{/* TODO: Add table columns when implementing */} |
|
|
|
</TableRow> |
|
|
|
</TableHead> |
|
|
|
<TableBody> |
|
|
|
{filteredData.length === 0 ? ( |
|
|
|
<TableRow> |
|
|
|
<TableCell colSpan={3} align="center"> |
|
|
|
<Typography variant="body2" color="text.secondary"> |
|
|
|
{t("No data available")} |
|
|
|
</Typography> |
|
|
|
</TableCell> |
|
|
|
</TableRow> |
|
|
|
) : ( |
|
|
|
filteredData.map((row, index) => ( |
|
|
|
<TableRow |
|
|
|
key={row.id || index} |
|
|
|
sx={{ |
|
|
|
'&:hover': { backgroundColor: 'grey.50' } |
|
|
|
}} |
|
|
|
> |
|
|
|
<TableCell> |
|
|
|
{/* TODO: Add table cell content when implementing */} |
|
|
|
- |
|
|
|
</TableCell> |
|
|
|
<TableCell> |
|
|
|
- |
|
|
|
</TableCell> |
|
|
|
<TableCell> |
|
|
|
- |
|
|
|
</TableCell> |
|
|
|
</TableRow> |
|
|
|
)) |
|
|
|
)} |
|
|
|
</TableBody> |
|
|
|
</Table> |
|
|
|
</TableContainer> |
|
|
|
)} |
|
|
|
</Box> |
|
|
|
</CardContent> |
|
|
|
</Card> |
|
|
|
); |
|
|
|
}; |
|
|
|
|
|
|
|
export default GoodsReceiptStatus; |