172 lines
6.0 KiB
TypeScript
172 lines
6.0 KiB
TypeScript
'use client';
|
|
|
|
import { useState } from 'react';
|
|
import { WerteEntry } from '@/types/werte';
|
|
|
|
interface WerteListProps {
|
|
entries: WerteEntry[];
|
|
onDelete?: (id: number) => void;
|
|
onEdit?: (entry: WerteEntry) => void;
|
|
}
|
|
|
|
function ConfirmDialog({
|
|
onConfirm,
|
|
onCancel,
|
|
}: {
|
|
onConfirm: () => void;
|
|
onCancel: () => void;
|
|
}) {
|
|
return (
|
|
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40">
|
|
<div className="bg-white border border-gray-300 rounded-lg shadow-lg p-6 w-80 text-center">
|
|
<p className="mb-6 text-gray-800 font-medium">Eintrag wirklich löschen?</p>
|
|
<div className="flex justify-center gap-4">
|
|
<button
|
|
onClick={onConfirm}
|
|
className="bg-red-500 hover:bg-red-600 text-white font-medium py-1.5 px-6 rounded-lg transition-colors"
|
|
>
|
|
Löschen
|
|
</button>
|
|
<button
|
|
onClick={onCancel}
|
|
className="bg-[#85B7D7] hover:bg-[#6a9fc5] text-black font-medium py-1.5 px-6 rounded-lg transition-colors"
|
|
>
|
|
Abbrechen
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default function WerteList({ entries, onDelete, onEdit }: WerteListProps) {
|
|
const [confirmId, setConfirmId] = useState<number | null>(null);
|
|
const formatValue = (value: number | string | null | undefined) => {
|
|
if (value === null || value === undefined || value === '' || value === '0' || value === '0.0') {
|
|
return '-';
|
|
}
|
|
return value;
|
|
};
|
|
|
|
const formatDate = (dateStr: string) => {
|
|
// Convert YYYY-MM-DD to DD.MM.YYYY
|
|
if (!dateStr) return '-';
|
|
// Parse the date string directly (MySQL returns YYYY-MM-DD)
|
|
const parts = dateStr.toString().split('T')[0].split('-');
|
|
if (parts.length === 3) {
|
|
return `${parts[2]}.${parts[1]}.${parts[0]}`;
|
|
}
|
|
return dateStr;
|
|
};
|
|
|
|
const formatTime = (timeStr: string) => {
|
|
// Convert HH:MM:SS to HH:MM
|
|
if (!timeStr) return '-';
|
|
const timeString = timeStr.toString();
|
|
return timeString.substring(0, 5);
|
|
};
|
|
|
|
const getWeekday = (dateStr: string) => {
|
|
if (!dateStr) return '-';
|
|
const weekdays = ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'];
|
|
// Parse date parts to avoid timezone issues
|
|
const [year, month, day] = dateStr.toString().split('T')[0].split('-');
|
|
const date = new Date(Number(year), Number(month) - 1, Number(day));
|
|
return weekdays[date.getDay()];
|
|
};
|
|
|
|
const handleDelete = async (id: number) => {
|
|
try {
|
|
const response = await fetch(`/api/werte/${id}`, {
|
|
method: 'DELETE',
|
|
});
|
|
|
|
if (response.ok && onDelete) {
|
|
onDelete(id);
|
|
} else {
|
|
alert('Fehler beim Löschen!');
|
|
}
|
|
} catch (error) {
|
|
console.error('Error:', error);
|
|
alert('Fehler beim Löschen!');
|
|
} finally {
|
|
setConfirmId(null);
|
|
}
|
|
};
|
|
|
|
if (entries.length === 0) {
|
|
return (
|
|
<div className="text-center py-8 text-gray-500">
|
|
Keine Einträge vorhanden
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="overflow-x-auto">
|
|
{confirmId !== null && (
|
|
<ConfirmDialog
|
|
onConfirm={() => handleDelete(confirmId)}
|
|
onCancel={() => setConfirmId(null)}
|
|
/>
|
|
)}
|
|
<table className="w-full border-collapse">
|
|
<thead>
|
|
<tr className="bg-[#CCCCFF] border-b-2 border-gray-400">
|
|
<th className="p-2 text-center">Datum</th>
|
|
<th className="p-2 text-center">Tag</th>
|
|
<th className="p-2 text-center">Zeit</th>
|
|
<th className="p-2 text-center">Zucker<br/><span className="text-xs font-normal">mg/dl</span></th>
|
|
<th className="p-2 text-center">Essen</th>
|
|
<th className="p-2 text-center">Gewicht<br/><span className="text-xs font-normal">kg</span></th>
|
|
<th className="p-2 text-center">Druck sys<br/><span className="text-xs font-normal">mmHg</span></th>
|
|
<th className="p-2 text-center">Druck dia<br/><span className="text-xs font-normal">mmHg</span></th>
|
|
<th className="p-2 text-center">Puls<br/><span className="text-xs font-normal">bpm</span></th>
|
|
{onDelete && <th className="p-2 text-center">Aktion</th>}
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{entries.map((entry, index) => (
|
|
<tr
|
|
key={entry.ID}
|
|
className={`border-b border-gray-300 hover:bg-gray-50 ${index % 2 === 0 ? 'bg-white' : 'bg-gray-50'}`}
|
|
>
|
|
<td className="p-2 text-center">{formatDate(entry.Datum)}</td>
|
|
<td className="p-2 text-center">{getWeekday(entry.Datum)}</td>
|
|
<td className="p-2 text-center">{formatTime(entry.Zeit)}</td>
|
|
<td className="p-2 text-center">{formatValue(entry.Zucker)}</td>
|
|
<td className="p-2 text-center">{formatValue(entry.Essen)}</td>
|
|
<td className="p-2 text-center">{formatValue(entry.Gewicht)}</td>
|
|
<td className="p-2 text-center">{formatValue(entry.DruckS)}</td>
|
|
<td className="p-2 text-center">{formatValue(entry.DruckD)}</td>
|
|
<td className="p-2 text-center">{formatValue(entry.Puls)}</td>
|
|
{(onDelete || onEdit) && (
|
|
<td className="p-2 text-center">
|
|
<div className="flex gap-2 justify-center">
|
|
{onEdit && (
|
|
<button
|
|
onClick={() => onEdit(entry)}
|
|
className="text-blue-600 hover:text-blue-800 text-sm"
|
|
>
|
|
Editieren
|
|
</button>
|
|
)}
|
|
{onDelete && (
|
|
<button
|
|
onClick={() => entry.ID && setConfirmId(entry.ID)}
|
|
className="text-red-600 hover:text-red-800 text-sm"
|
|
>
|
|
Löschen
|
|
</button>
|
|
)}
|
|
</div>
|
|
</td>
|
|
)}
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
);
|
|
}
|