Erledigte Termine ans Ende + blasser, neuer Tab 'Liste'
- Erledigte Einträge werden nicht mehr durchgestrichen, nur die Textfarbe wird blasser dargestellt - Erledigte Termine werden in der Liste hinter die offenen sortiert - Neuer Tab 'Liste' (Route /liste) mit einer read-only Übersicht aller Termine; TabLayout auf echte Tabs (Link/usePathname) umgestellt - AppointmentList: Handler optional, damit die Liste read-only nutzbar ist Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,9 +4,9 @@ import { Appointment } from '@/types/appointment';
|
||||
|
||||
interface AppointmentListProps {
|
||||
appointments: Appointment[];
|
||||
onToggleDone: (id: string) => void;
|
||||
onEdit: (appointment: Appointment) => void;
|
||||
onDelete: (id: string) => void;
|
||||
onToggleDone?: (id: string) => void;
|
||||
onEdit?: (appointment: Appointment) => void;
|
||||
onDelete?: (id: string) => void;
|
||||
}
|
||||
|
||||
const weekdays = ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'];
|
||||
@@ -33,17 +33,22 @@ export default function AppointmentList({
|
||||
onEdit,
|
||||
onDelete,
|
||||
}: AppointmentListProps) {
|
||||
const hasActions = Boolean(onEdit || onDelete);
|
||||
|
||||
if (appointments.length === 0) {
|
||||
return (
|
||||
<div className="text-center py-8 text-gray-500">
|
||||
Keine Termine vorhanden. Fügen Sie oben einen neuen Termin hinzu!
|
||||
Keine Termine vorhanden.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const sorted = [...appointments].sort(
|
||||
(a, b) => new Date(a.termin).getTime() - new Date(b.termin).getTime()
|
||||
);
|
||||
// Erledigte Einträge hinter die offenen schieben; innerhalb der Gruppen
|
||||
// aufsteigend nach Termin sortieren.
|
||||
const sorted = [...appointments].sort((a, b) => {
|
||||
if (a.erledigt !== b.erledigt) return a.erledigt ? 1 : -1;
|
||||
return new Date(a.termin).getTime() - new Date(b.termin).getTime();
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="overflow-x-auto">
|
||||
@@ -57,17 +62,19 @@ export default function AppointmentList({
|
||||
<th className="p-2 text-center">Tag</th>
|
||||
<th className="p-2 text-center">Zeit</th>
|
||||
<th className="p-2 text-center">Bemerkungen</th>
|
||||
<th className="p-2 text-center">Aktion</th>
|
||||
{hasActions && <th className="p-2 text-center">Aktion</th>}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{sorted.map((app, index) => (
|
||||
<tr
|
||||
key={app.id}
|
||||
onClick={() => onEdit(app)}
|
||||
className={`border-b border-gray-300 hover:bg-gray-100 cursor-pointer ${
|
||||
onClick={onEdit ? () => onEdit(app) : undefined}
|
||||
className={`border-b border-gray-300 hover:bg-gray-100 ${
|
||||
onEdit ? 'cursor-pointer' : ''
|
||||
} ${
|
||||
app.erledigt
|
||||
? 'bg-green-50 text-gray-400 line-through'
|
||||
? 'bg-green-50 text-gray-400'
|
||||
: index % 2 === 0
|
||||
? 'bg-white'
|
||||
: 'bg-gray-50'
|
||||
@@ -79,9 +86,12 @@ export default function AppointmentList({
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
className="w-4 h-4 cursor-pointer"
|
||||
className={`w-4 h-4 ${onToggleDone ? 'cursor-pointer' : ''}`}
|
||||
checked={app.erledigt}
|
||||
onChange={() => onToggleDone(app.id)}
|
||||
disabled={!onToggleDone}
|
||||
onChange={
|
||||
onToggleDone ? () => onToggleDone(app.id) : undefined
|
||||
}
|
||||
/>
|
||||
</td>
|
||||
<td className="p-2 text-center font-medium">{app.arztName}</td>
|
||||
@@ -90,25 +100,31 @@ export default function AppointmentList({
|
||||
<td className="p-2 text-center">{getWeekday(app.termin)}</td>
|
||||
<td className="p-2 text-center">{formatTime(app.termin)}</td>
|
||||
<td className="p-2 text-center">{app.bemerkungen || '-'}</td>
|
||||
<td
|
||||
className="p-2 text-center"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<div className="flex gap-2 justify-center no-underline">
|
||||
<button
|
||||
onClick={() => onEdit(app)}
|
||||
className="text-blue-600 hover:text-blue-800 text-sm no-underline"
|
||||
>
|
||||
Editieren
|
||||
</button>
|
||||
<button
|
||||
onClick={() => onDelete(app.id)}
|
||||
className="text-red-600 hover:text-red-800 text-sm no-underline"
|
||||
>
|
||||
Löschen
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
{hasActions && (
|
||||
<td
|
||||
className="p-2 text-center"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<div className="flex gap-2 justify-center">
|
||||
{onEdit && (
|
||||
<button
|
||||
onClick={() => onEdit(app)}
|
||||
className="text-blue-600 hover:text-blue-800 text-sm"
|
||||
>
|
||||
Editieren
|
||||
</button>
|
||||
)}
|
||||
{onDelete && (
|
||||
<button
|
||||
onClick={() => onDelete(app.id)}
|
||||
className="text-red-600 hover:text-red-800 text-sm"
|
||||
>
|
||||
Löschen
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
)}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
|
||||
Reference in New Issue
Block a user