127 lines
3.4 KiB
TypeScript
127 lines
3.4 KiB
TypeScript
'use client';
|
|
|
|
import { useState, useTransition } from 'react';
|
|
import { parseErrorResponse } from '../../lib/error-handler';
|
|
import type { InventoryConsumption } from '../../features/inventory/types';
|
|
|
|
type Props = {
|
|
id: number;
|
|
};
|
|
|
|
function formatDateTime(value: string) {
|
|
return new Date(value).toLocaleString('sv-SE');
|
|
}
|
|
|
|
export default function InventoryConsumptionHistory({ id }: Props) {
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
const [isPending, startTransition] = useTransition();
|
|
const [error, setError] = useState<string | null>(null);
|
|
const [history, setHistory] = useState<InventoryConsumption[] | null>(null);
|
|
|
|
const loadHistory = () => {
|
|
setError(null);
|
|
|
|
startTransition(async () => {
|
|
try {
|
|
const res = await fetch(`/api/inventory-history-proxy?id=${id}`, {
|
|
method: 'GET',
|
|
cache: 'no-store',
|
|
});
|
|
|
|
if (!res.ok) {
|
|
const errorMessage = await parseErrorResponse(res);
|
|
throw new Error(errorMessage);
|
|
}
|
|
|
|
const data: InventoryConsumption[] = await res.json();
|
|
setHistory(data);
|
|
setIsOpen(true);
|
|
} catch (err) {
|
|
const message = err instanceof Error ? err.message : 'Ett okänt fel inträffade.';
|
|
setError(message);
|
|
}
|
|
});
|
|
};
|
|
|
|
if (!isOpen) {
|
|
return (
|
|
<div style={{ display: 'grid', gap: '0.5rem' }}>
|
|
<button
|
|
type="button"
|
|
onClick={loadHistory}
|
|
disabled={isPending}
|
|
style={{ padding: '0.5rem 0.75rem' }}
|
|
>
|
|
{isPending ? 'Hämtar historik...' : 'Visa historik'}
|
|
</button>
|
|
{error ? <p style={{ color: 'crimson', margin: 0 }}>{error}</p> : null}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div
|
|
style={{
|
|
width: '100%',
|
|
display: 'grid',
|
|
gap: '0.75rem',
|
|
marginTop: '0.5rem',
|
|
border: '1px solid #eee',
|
|
borderRadius: '8px',
|
|
padding: '0.75rem',
|
|
background: '#fafafa',
|
|
}}
|
|
>
|
|
<div
|
|
style={{
|
|
display: 'flex',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'center',
|
|
gap: '0.75rem',
|
|
flexWrap: 'wrap',
|
|
}}
|
|
>
|
|
<strong>Förbrukningshistorik</strong>
|
|
<button
|
|
type="button"
|
|
onClick={() => setIsOpen(false)}
|
|
style={{ padding: '0.45rem 0.75rem' }}
|
|
>
|
|
Dölj
|
|
</button>
|
|
</div>
|
|
|
|
{history && history.length > 0 ? (
|
|
<div style={{ display: 'grid', gap: '0.5rem' }}>
|
|
{history.map((entry) => (
|
|
<article
|
|
key={entry.id}
|
|
style={{
|
|
border: '1px solid #e5e5e5',
|
|
borderRadius: '6px',
|
|
padding: '0.6rem',
|
|
background: '#fff',
|
|
}}
|
|
>
|
|
<div>
|
|
<strong>Använt:</strong> {entry.amountUsed}{entry.inventoryItem?.unit ? ` ${entry.inventoryItem.unit}` : ''}
|
|
</div>
|
|
<div>
|
|
<strong>Tid:</strong> {formatDateTime(entry.createdAt)}
|
|
</div>
|
|
{entry.comment ? (
|
|
<div>
|
|
<strong>Kommentar:</strong> {entry.comment}
|
|
</div>
|
|
) : null}
|
|
</article>
|
|
))}
|
|
</div>
|
|
) : (
|
|
<p style={{ margin: 0 }}>Ingen förbrukningshistorik ännu.</p>
|
|
)}
|
|
|
|
{error ? <p style={{ color: 'crimson', margin: 0 }}>{error}</p> : null}
|
|
</div>
|
|
);
|
|
} |