Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4799730abb | |||
| 8f423c70c3 | |||
| de452b55df | |||
| ee16942742 |
+7
-4
@@ -6,7 +6,8 @@ import WerteList from '@/components/WerteList';
|
|||||||
import { WerteEntry } from '@/types/werte';
|
import { WerteEntry } from '@/types/werte';
|
||||||
import TabLayout from '@/components/TabLayout';
|
import TabLayout from '@/components/TabLayout';
|
||||||
|
|
||||||
const MAX_ENTRIES = 15
|
const MAX_ENTRIES = 15;
|
||||||
|
const MOBILE_ENTRIES = 5;
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const [entries, setEntries] = useState<WerteEntry[]>([]);
|
const [entries, setEntries] = useState<WerteEntry[]>([]);
|
||||||
@@ -45,7 +46,7 @@ export default function Home() {
|
|||||||
|
|
||||||
const refreshEntries = async () => {
|
const refreshEntries = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/api/werte?limit=14', {
|
const response = await fetch(`/api/werte?limit=${MAX_ENTRIES}`, {
|
||||||
cache: 'no-store',
|
cache: 'no-store',
|
||||||
headers: {
|
headers: {
|
||||||
'Cache-Control': 'no-cache',
|
'Cache-Control': 'no-cache',
|
||||||
@@ -87,11 +88,13 @@ export default function Home() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="bg-white border border-black rounded-lg shadow-md p-6">
|
<div className="bg-white border border-black rounded-lg shadow-md p-6">
|
||||||
<h2 className="text-xl font-semibold mb-4">Letzte {MAX_ENTRIES} Einträge</h2>
|
<h2 className="text-xl font-semibold mb-4">
|
||||||
|
Letzte <span className="md:hidden">{MOBILE_ENTRIES}</span><span className="hidden md:inline">{MAX_ENTRIES}</span> Einträge
|
||||||
|
</h2>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<div className="text-center py-4">Lade Daten...</div>
|
<div className="text-center py-4">Lade Daten...</div>
|
||||||
) : (
|
) : (
|
||||||
<WerteList entries={entries} onDelete={handleDelete} onEdit={handleEdit} />
|
<WerteList entries={entries} onDelete={handleDelete} onEdit={handleEdit} mobileLimit={MOBILE_ENTRIES} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ export default function TabLayout({ children }: TabLayoutProps) {
|
|||||||
const buildDate = process.env.NEXT_PUBLIC_BUILD_DATE || new Date().toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' });
|
const buildDate = process.env.NEXT_PUBLIC_BUILD_DATE || new Date().toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen py-8 px-4">
|
<div className="min-h-screen py-8 px-2 sm:px-4">
|
||||||
{/* Outer wrapper: ~10% wider than the inner max-w-6xl (72rem → ~79rem), with border */}
|
{/* Outer wrapper: ~10% wider than the inner max-w-6xl (72rem → ~79rem), with border */}
|
||||||
<div className="max-w-316 mx-auto border-2 border-black rounded-xl bg-gray-200 p-6">
|
<div className="max-w-316 mx-auto border-2 border-black rounded-xl bg-gray-200 p-3 sm:p-6">
|
||||||
|
|
||||||
{/* Page title */}
|
{/* Page title */}
|
||||||
<h1 className="text-4xl font-bold text-center mb-6 tracking-tight">Werte-Log</h1>
|
<h1 className="text-4xl font-bold text-center mb-6 tracking-tight">Werte-Log</h1>
|
||||||
@@ -51,7 +51,7 @@ export default function TabLayout({ children }: TabLayoutProps) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Content panel */}
|
{/* Content panel */}
|
||||||
<main className="border-2 border-black rounded-b-lg rounded-tr-lg p-6 bg-[#FFFFDD]">
|
<main className="border-2 border-black rounded-b-lg rounded-tr-lg p-3 sm:p-6 bg-[#FFFFDD]">
|
||||||
{children}
|
{children}
|
||||||
</main>
|
</main>
|
||||||
<footer className="mt-8 flex justify-between items-center text-sm text-gray-600 px-4">
|
<footer className="mt-8 flex justify-between items-center text-sm text-gray-600 px-4">
|
||||||
|
|||||||
+123
-109
@@ -142,122 +142,136 @@ export default function WerteForm({ onSuccess, selectedEntry }: WerteFormProps)
|
|||||||
updateWeekday(now);
|
updateWeekday(now);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const inputClass = "w-full min-w-0 px-2 py-1 text-sm rounded border-2 border-gray-400 bg-white focus:border-blue-500 focus:outline-none";
|
||||||
|
const numberInputClass = `${inputClass} [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none`;
|
||||||
|
// Datum/Zeit/Zucker: schmaler, damit sie bei Tablet-Hochformat (sm:) und schmalem Smartphone nicht überlappen bzw. aus dem Rahmen ragen.
|
||||||
|
// py-1.5 statt py-1 gleicht die geringere Zeilenhöhe von text-xs aus, damit die Felder gleich hoch wie die übrigen (text-sm) Felder bleiben.
|
||||||
|
const compactInputClass = "w-full min-w-0 px-1 py-1.5 text-xs rounded border-2 border-gray-400 bg-white focus:border-blue-500 focus:outline-none";
|
||||||
|
const compactNumberInputClass = `${compactInputClass} [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none`;
|
||||||
|
// Datum/Zeit: nochmal 10px schmaler als die übrigen kompakten Felder.
|
||||||
|
const dateTimeInputClass = "w-[calc(100%-10px)] min-w-0 px-1 py-1.5 text-xs rounded border-2 border-gray-400 bg-white focus:border-blue-500 focus:outline-none";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-[#CCCCFF] border border-black p-6 rounded-lg mb-6">
|
<div className="bg-[#CCCCFF] border border-black p-3 sm:p-6 rounded-lg mb-6">
|
||||||
{editId && (
|
{editId && (
|
||||||
<div className="mb-4 p-3 bg-blue-100 border border-blue-400 rounded text-sm text-blue-800">
|
<div className="mb-4 p-3 bg-blue-100 border border-blue-400 rounded text-sm text-blue-800">
|
||||||
ℹ️ <strong>Bearbeitungsmodus:</strong> Sie bearbeiten einen bestehenden Eintrag. Klicken Sie auf "Aktualisieren", um die Änderungen zu speichern, oder "Abbrechen", um zur Neuerfassung zurückzukehren.
|
ℹ️ <strong>Bearbeitungsmodus:</strong> Sie bearbeiten einen bestehenden Eintrag. Klicken Sie auf "Aktualisieren", um die Änderungen zu speichern, oder "Abbrechen", um zur Neuerfassung zurückzukehren.
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<form onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit}>
|
||||||
<table className="w-full text-center">
|
<div className="grid grid-cols-2 sm:grid-cols-4 md:grid-cols-8 gap-3 sm:gap-2">
|
||||||
<thead>
|
<div className="flex flex-col gap-1">
|
||||||
<tr className="border-b-2 border-gray-400">
|
<label className="text-xs font-medium text-center">
|
||||||
<th className="p-2">Datum</th>
|
Datum
|
||||||
<th className="p-2">Zeit</th>
|
<span className="block text-[10px] font-normal">{weekday}</span>
|
||||||
<th className="p-2">Zucker</th>
|
</label>
|
||||||
<th className="p-2">Essen</th>
|
<input
|
||||||
<th className="p-2">Gewicht</th>
|
type="date"
|
||||||
<th className="p-2">Druck sys</th>
|
className={dateTimeInputClass}
|
||||||
<th className="p-2">Druck dia</th>
|
value={formData.Datum}
|
||||||
<th className="p-2">Puls</th>
|
onChange={(e) => handleDateChange(e.target.value)}
|
||||||
</tr>
|
required
|
||||||
<tr className="border-b-2 border-gray-400">
|
/>
|
||||||
<th className="p-2 font-normal text-sm">{weekday}</th>
|
</div>
|
||||||
<th className="p-2"></th>
|
<div className="flex flex-col gap-1">
|
||||||
<th className="p-2 font-normal text-sm">mg/dl</th>
|
<label className="text-xs font-medium text-center">
|
||||||
<th className="p-2"></th>
|
Zeit
|
||||||
<th className="p-2 font-normal text-sm">kg</th>
|
<span className="block text-[10px] font-normal invisible">.</span>
|
||||||
<th className="p-2 font-normal text-sm">mmHg</th>
|
</label>
|
||||||
<th className="p-2 font-normal text-sm">mmHg</th>
|
<input
|
||||||
<th className="p-2 font-normal text-sm">bpm</th>
|
type="time"
|
||||||
</tr>
|
className={dateTimeInputClass}
|
||||||
</thead>
|
value={formData.Zeit}
|
||||||
<tbody>
|
onChange={(e) => setFormData(prev => ({ ...prev, Zeit: e.target.value }))}
|
||||||
<tr>
|
required
|
||||||
<td className="p-2">
|
/>
|
||||||
<input
|
</div>
|
||||||
type="date"
|
<div className="flex flex-col gap-1">
|
||||||
className="w-full px-2 py-1 text-sm rounded border-2 border-gray-400 bg-white focus:border-blue-500 focus:outline-none"
|
<label className="text-xs font-medium text-center">
|
||||||
value={formData.Datum}
|
Zucker
|
||||||
onChange={(e) => handleDateChange(e.target.value)}
|
<span className="block text-[10px] font-normal">mg/dl</span>
|
||||||
required
|
</label>
|
||||||
/>
|
<input
|
||||||
</td>
|
type="number"
|
||||||
<td className="p-2">
|
className={compactNumberInputClass}
|
||||||
<input
|
min={0}
|
||||||
type="time"
|
max={999}
|
||||||
className="w-full px-2 py-1 text-sm rounded border-2 border-gray-400 bg-white focus:border-blue-500 focus:outline-none"
|
value={formData.Zucker}
|
||||||
value={formData.Zeit}
|
onChange={(e) => setFormData(prev => ({ ...prev, Zucker: e.target.value }))}
|
||||||
onChange={(e) => setFormData(prev => ({ ...prev, Zeit: e.target.value }))}
|
/>
|
||||||
required
|
</div>
|
||||||
/>
|
<div className="flex flex-col gap-1">
|
||||||
</td>
|
<label className="text-xs font-medium text-center">
|
||||||
<td className="p-2">
|
Essen
|
||||||
<input
|
<span className="block text-[10px] font-normal invisible">.</span>
|
||||||
type="number"
|
</label>
|
||||||
className="w-20 px-2 py-1 text-sm rounded border-2 border-gray-400 bg-white focus:border-blue-500 focus:outline-none [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
|
<textarea
|
||||||
min={0}
|
className={`${inputClass} resize-none align-middle`}
|
||||||
max={999}
|
value={formData.Essen}
|
||||||
value={formData.Zucker}
|
onChange={(e) => setFormData(prev => ({ ...prev, Essen: e.target.value }))}
|
||||||
onChange={(e) => setFormData(prev => ({ ...prev, Zucker: e.target.value }))}
|
rows={1}
|
||||||
/>
|
/>
|
||||||
</td>
|
</div>
|
||||||
<td className="p-2">
|
<div className="flex flex-col gap-1">
|
||||||
<textarea
|
<label className="text-xs font-medium text-center">
|
||||||
className="w-full px-2 py-1 text-sm rounded border-2 border-gray-400 bg-white focus:border-blue-500 focus:outline-none resize-none align-middle"
|
Gewicht
|
||||||
style={{ height: '28px' }}
|
<span className="block text-[10px] font-normal">kg</span>
|
||||||
value={formData.Essen}
|
</label>
|
||||||
onChange={(e) => setFormData(prev => ({ ...prev, Essen: e.target.value }))}
|
<input
|
||||||
rows={1}
|
type="number"
|
||||||
/>
|
step="0.1"
|
||||||
</td>
|
className={numberInputClass}
|
||||||
<td className="p-2">
|
min={0}
|
||||||
<input
|
max={300}
|
||||||
type="number"
|
value={formData.Gewicht}
|
||||||
step="0.1"
|
onChange={(e) => setFormData(prev => ({ ...prev, Gewicht: e.target.value }))}
|
||||||
className="w-20 px-2 py-1 text-sm rounded border-2 border-gray-400 bg-white focus:border-blue-500 focus:outline-none [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
|
/>
|
||||||
min={0}
|
</div>
|
||||||
max={300}
|
<div className="flex flex-col gap-1">
|
||||||
value={formData.Gewicht}
|
<label className="text-xs font-medium text-center">
|
||||||
onChange={(e) => setFormData(prev => ({ ...prev, Gewicht: e.target.value }))}
|
Druck sys
|
||||||
/>
|
<span className="block text-[10px] font-normal">mmHg</span>
|
||||||
</td>
|
</label>
|
||||||
<td className="p-2">
|
<input
|
||||||
<input
|
type="number"
|
||||||
type="number"
|
className={numberInputClass}
|
||||||
className="w-20 px-2 py-1 text-sm rounded border-2 border-gray-400 bg-white focus:border-blue-500 focus:outline-none [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
|
min={0}
|
||||||
min={0}
|
max={300}
|
||||||
max={300}
|
value={formData.DruckS}
|
||||||
value={formData.DruckS}
|
onChange={(e) => setFormData(prev => ({ ...prev, DruckS: e.target.value }))}
|
||||||
onChange={(e) => setFormData(prev => ({ ...prev, DruckS: e.target.value }))}
|
/>
|
||||||
/>
|
</div>
|
||||||
</td>
|
<div className="flex flex-col gap-1">
|
||||||
<td className="p-2">
|
<label className="text-xs font-medium text-center">
|
||||||
<input
|
Druck dia
|
||||||
type="number"
|
<span className="block text-[10px] font-normal">mmHg</span>
|
||||||
className="w-20 px-2 py-1 text-sm rounded border-2 border-gray-400 bg-white focus:border-blue-500 focus:outline-none [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
|
</label>
|
||||||
min={0}
|
<input
|
||||||
max={200}
|
type="number"
|
||||||
value={formData.DruckD}
|
className={numberInputClass}
|
||||||
onChange={(e) => setFormData(prev => ({ ...prev, DruckD: e.target.value }))}
|
min={0}
|
||||||
/>
|
max={200}
|
||||||
</td>
|
value={formData.DruckD}
|
||||||
<td className="p-2">
|
onChange={(e) => setFormData(prev => ({ ...prev, DruckD: e.target.value }))}
|
||||||
<input
|
/>
|
||||||
type="number"
|
</div>
|
||||||
className="w-20 px-2 py-1 text-sm rounded border-2 border-gray-400 bg-white focus:border-blue-500 focus:outline-none [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
|
<div className="flex flex-col gap-1">
|
||||||
min={0}
|
<label className="text-xs font-medium text-center">
|
||||||
max={250}
|
Puls
|
||||||
value={formData.Puls}
|
<span className="block text-[10px] font-normal">bpm</span>
|
||||||
onChange={(e) => setFormData(prev => ({ ...prev, Puls: e.target.value }))}
|
</label>
|
||||||
/>
|
<input
|
||||||
</td>
|
type="number"
|
||||||
</tr>
|
className={numberInputClass}
|
||||||
</tbody>
|
min={0}
|
||||||
</table>
|
max={250}
|
||||||
|
value={formData.Puls}
|
||||||
<div className="flex justify-center gap-4 mt-6">
|
onChange={(e) => setFormData(prev => ({ ...prev, Puls: e.target.value }))}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex justify-center gap-2 sm:gap-4 mt-6">
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
|
|||||||
+101
-58
@@ -7,6 +7,7 @@ interface WerteListProps {
|
|||||||
entries: WerteEntry[];
|
entries: WerteEntry[];
|
||||||
onDelete?: (id: number) => void;
|
onDelete?: (id: number) => void;
|
||||||
onEdit?: (entry: WerteEntry) => void;
|
onEdit?: (entry: WerteEntry) => void;
|
||||||
|
mobileLimit?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ConfirmDialog({
|
function ConfirmDialog({
|
||||||
@@ -18,7 +19,7 @@ function ConfirmDialog({
|
|||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40">
|
<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">
|
<div className="bg-white border border-gray-300 rounded-lg shadow-lg p-6 w-80 max-w-[calc(100vw-2rem)] mx-4 text-center">
|
||||||
<p className="mb-6 text-gray-800 font-medium">Eintrag wirklich löschen?</p>
|
<p className="mb-6 text-gray-800 font-medium">Eintrag wirklich löschen?</p>
|
||||||
<div className="flex justify-center gap-4">
|
<div className="flex justify-center gap-4">
|
||||||
<button
|
<button
|
||||||
@@ -39,7 +40,7 @@ function ConfirmDialog({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function WerteList({ entries, onDelete, onEdit }: WerteListProps) {
|
export default function WerteList({ entries, onDelete, onEdit, mobileLimit }: WerteListProps) {
|
||||||
const [confirmId, setConfirmId] = useState<number | null>(null);
|
const [confirmId, setConfirmId] = useState<number | null>(null);
|
||||||
const formatValue = (value: number | string | null | undefined) => {
|
const formatValue = (value: number | string | null | undefined) => {
|
||||||
if (value === null || value === undefined || value === '' || value === '0' || value === '0.0') {
|
if (value === null || value === undefined || value === '' || value === '0' || value === '0.0') {
|
||||||
@@ -103,69 +104,111 @@ export default function WerteList({ entries, onDelete, onEdit }: WerteListProps)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="overflow-x-auto">
|
<div>
|
||||||
{confirmId !== null && (
|
{confirmId !== null && (
|
||||||
<ConfirmDialog
|
<ConfirmDialog
|
||||||
onConfirm={() => handleDelete(confirmId)}
|
onConfirm={() => handleDelete(confirmId)}
|
||||||
onCancel={() => setConfirmId(null)}
|
onCancel={() => setConfirmId(null)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<table className="w-full border-collapse">
|
<div className="hidden md:block overflow-x-auto">
|
||||||
<thead>
|
<table className="w-full border-collapse">
|
||||||
<tr className="bg-[#CCCCFF] border-b-2 border-gray-400">
|
<thead>
|
||||||
<th className="p-2 text-center">Datum</th>
|
<tr className="bg-[#CCCCFF] border-b-2 border-gray-400">
|
||||||
<th className="p-2 text-center">Tag</th>
|
<th className="p-2 text-center">Datum</th>
|
||||||
<th className="p-2 text-center">Zeit</th>
|
<th className="p-2 text-center">Tag</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">Zeit</th>
|
||||||
<th className="p-2 text-center">Essen</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">Gewicht<br/><span className="text-xs font-normal">kg</span></th>
|
<th className="p-2 text-center">Essen</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">Gewicht<br/><span className="text-xs font-normal">kg</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">Druck sys<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>
|
<th className="p-2 text-center">Druck dia<br/><span className="text-xs font-normal">mmHg</span></th>
|
||||||
{onDelete && <th className="p-2 text-center">Aktion</th>}
|
<th className="p-2 text-center">Puls<br/><span className="text-xs font-normal">bpm</span></th>
|
||||||
</tr>
|
{onDelete && <th className="p-2 text-center">Aktion</th>}
|
||||||
</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>
|
</tr>
|
||||||
))}
|
</thead>
|
||||||
</tbody>
|
<tbody>
|
||||||
</table>
|
{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>
|
||||||
|
|
||||||
|
<div className="md:hidden flex flex-col gap-2">
|
||||||
|
{(mobileLimit ? entries.slice(0, mobileLimit) : entries).map((entry, index) => (
|
||||||
|
<div
|
||||||
|
key={entry.ID}
|
||||||
|
className={`border border-gray-300 rounded-lg p-2 ${index % 2 === 0 ? 'bg-white' : 'bg-gray-50'}`}
|
||||||
|
>
|
||||||
|
<div className="flex justify-between items-center text-sm font-medium">
|
||||||
|
<span>{formatDate(entry.Datum)} ({getWeekday(entry.Datum)}) · {formatTime(entry.Zeit)}</span>
|
||||||
|
{(onDelete || onEdit) && (
|
||||||
|
<div className="flex gap-2">
|
||||||
|
{onEdit && (
|
||||||
|
<button
|
||||||
|
onClick={() => onEdit(entry)}
|
||||||
|
className="text-blue-600 hover:text-blue-800 text-xs"
|
||||||
|
>
|
||||||
|
Editieren
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
{onDelete && (
|
||||||
|
<button
|
||||||
|
onClick={() => entry.ID && setConfirmId(entry.ID)}
|
||||||
|
className="text-red-600 hover:text-red-800 text-xs"
|
||||||
|
>
|
||||||
|
Löschen
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-wrap gap-x-3 gap-y-0.5 text-xs text-gray-700 mt-1">
|
||||||
|
<span>Zucker: {formatValue(entry.Zucker)}</span>
|
||||||
|
<span>Essen: {formatValue(entry.Essen)}</span>
|
||||||
|
<span>Gewicht: {formatValue(entry.Gewicht)}</span>
|
||||||
|
<span>RR: {formatValue(entry.DruckS)}/{formatValue(entry.DruckD)}</span>
|
||||||
|
<span>Puls: {formatValue(entry.Puls)}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "werte_next",
|
"name": "werte_next",
|
||||||
"version": "2.3.0",
|
"version": "2.3.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "werte_next",
|
"name": "werte_next",
|
||||||
"version": "2.3.0",
|
"version": "2.3.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"highcharts": "^12.5.0",
|
"highcharts": "^12.5.0",
|
||||||
"highcharts-react-official": "^3.2.3",
|
"highcharts-react-official": "^3.2.3",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "werte_next",
|
"name": "werte_next",
|
||||||
"version": "2.3.0",
|
"version": "2.3.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
|
|||||||
Reference in New Issue
Block a user