Files
aerzte/components/AppointmentList.tsx
T
admin 1a0fe18e89 Umstellung auf Next.js (App Router), Design analog werte-next
Führt das getrennte React/Vite-Frontend und Express/MongoDB-Backend in
eine einzelne Next.js-Anwendung zusammen:

- UI: React-Client-Komponenten (TabLayout, AppointmentForm, -List,
  ConfirmationModal) im Look von werte-next (Farben #CCCCFF/#85B7D7/
  #FFFFDD, Rahmenbox, Tabellen-Liste, Footer mit Version/Datum)
- API: Next.js Route Handler unter /api/appointments (GET/POST/PUT/DELETE,
  Soft-Delete beibehalten)
- DB: MongoDB via lib/db.ts (gecachter Client, Standard appointmentsdb)
- Tailwind 4 + TypeScript, Standalone-Docker-Build wie werte-next
- Druckansicht der aktuellen offenen Termine beibehalten
- Deployment: Dockerfile (multi-stage), docker-compose(.prod), deploy.sh

Entfernt die alten frontend/- und backend/-Verzeichnisse.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 14:24:34 +02:00

119 lines
3.9 KiB
TypeScript

'use client';
import { Appointment } from '@/types/appointment';
interface AppointmentListProps {
appointments: Appointment[];
onToggleDone: (id: string) => void;
onEdit: (appointment: Appointment) => void;
onDelete: (id: string) => void;
}
const weekdays = ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'];
const formatDate = (iso: string) => {
const d = new Date(iso);
const day = String(d.getDate()).padStart(2, '0');
const m = String(d.getMonth() + 1).padStart(2, '0');
return `${day}.${m}.${d.getFullYear()}`;
};
const formatTime = (iso: string) => {
const d = new Date(iso);
const h = String(d.getHours()).padStart(2, '0');
const min = String(d.getMinutes()).padStart(2, '0');
return `${h}:${min}`;
};
const getWeekday = (iso: string) => weekdays[new Date(iso).getDay()];
export default function AppointmentList({
appointments,
onToggleDone,
onEdit,
onDelete,
}: AppointmentListProps) {
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!
</div>
);
}
const sorted = [...appointments].sort(
(a, b) => new Date(a.termin).getTime() - new Date(b.termin).getTime()
);
return (
<div className="overflow-x-auto">
<table className="w-full border-collapse">
<thead>
<tr className="bg-[#CCCCFF] border-b-2 border-gray-400">
<th className="p-2 text-center">Erledigt</th>
<th className="p-2 text-center">Arzt</th>
<th className="p-2 text-center">Fachrichtung</th>
<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">Bemerkungen</th>
<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 ${
app.erledigt
? 'bg-green-50 text-gray-400 line-through'
: index % 2 === 0
? 'bg-white'
: 'bg-gray-50'
}`}
>
<td
className="p-2 text-center"
onClick={(e) => e.stopPropagation()}
>
<input
type="checkbox"
className="w-4 h-4 cursor-pointer"
checked={app.erledigt}
onChange={() => onToggleDone(app.id)}
/>
</td>
<td className="p-2 text-center font-medium">{app.arztName}</td>
<td className="p-2 text-center">{app.arztArt || '-'}</td>
<td className="p-2 text-center">{formatDate(app.termin)}</td>
<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>
</tr>
))}
</tbody>
</table>
</div>
);
}