import React, { useState, useEffect } from 'react';
import { User, Home, Briefcase, Calendar, AlertCircle, Plus, Edit, Trash2, Check, X, ChevronLeft, Moon, Sun } from 'lucide-react';
export default function App() {
// Facility name - change this to your facility name
const facilityName = "Wuma Frenkendorf";
// Initial demo data
const [clients, setClients] = useState([
{
id: '1',
name: 'Max Mustermann',
roomNumber: '101',
photo: null,
isHome: true,
notHomeReason: '',
uAboExpiryDate: '2025-06-15',
entries: [
{ id: '1', category: 'Gemeinde', description: 'Anmeldung Ferienprogramm', status: 'open', date: '2025-06-01' }
],
appointments: [
{ id: '1', type: 'Arzttermin', date: '2025-06-10', time: '14:00', description: 'Hausarzt Kontrolle' }
]
},
{
id: '2',
name: 'Anna Schmidt',
roomNumber: '102',
photo: null,
isHome: false,
notHomeReason: 'Schule',
uAboExpiryDate: '2025-06-08',
entries: [],
appointments: []
}
]);
const [selectedClient, setSelectedClient] = useState(null);
const [showAddClient, setShowAddClient] = useState(false);
const [editingClient, setEditingClient] = useState(null);
const [darkMode, setDarkMode] = useState(false);
// Effect to apply dark mode class to document
useEffect(() => {
if (darkMode) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
}, [darkMode]);
// Add new client
const addClient = (clientData) => {
console.log("Adding client:", clientData);
const newClient = {
...clientData,
id: Date.now().toString(),
isHome: true,
notHomeReason: '',
entries: [],
appointments: []
};
setClients(prevClients => [...prevClients, newClient]);
setShowAddClient(false);
};
// Update client
const updateClient = (clientId, updates) => {
console.log("Updating client:", clientId, updates);
setClients(prevClients =>
prevClients.map(c => c.id === clientId ? { ...c, ...updates } : c)
);
if (selectedClient?.id === clientId) {
setSelectedClient(prev => ({ ...prev, ...updates }));
}
};
// Delete client
const deleteClient = (clientId) => {
if (window.confirm('Möchten Sie diesen Klienten wirklich löschen?')) {
setClients(prevClients => prevClients.filter(c => c.id !== clientId));
if (selectedClient?.id === clientId) {
setSelectedClient(null);
}
}
};
return (
{/* Header */}
{/* Main Content */}
{!selectedClient ? (
// Client List View
Klienten Übersicht
{clients.map(client => (
setSelectedClient(client)}
onEdit={() => setEditingClient(client)}
onDelete={() => deleteClient(client.id)}
/>
))}
) : (
// Client Detail View
)}
{/* Footer */}
{/* Modals */}
{showAddClient && (
setShowAddClient(false)}
/>
)}
{editingClient && (
{
updateClient(editingClient.id, data);
setEditingClient(null);
}}
onClose={() => setEditingClient(null)}
/>
)}
);
}
// Client Card Component
function ClientCard({ client, onSelect, onEdit, onDelete }) {
const daysUntilExpiry = client.uAboExpiryDate
? Math.ceil((new Date(client.uAboExpiryDate) - new Date()) / (1000 * 60 * 60 * 24))
: null;
return (
{client.photo ? (

) : (
)}
{client.name}
Zimmer {client.roomNumber}
{client.isHome ? 'Zu Hause' : 'Abwesend'}
{daysUntilExpiry !== null && daysUntilExpiry <= 7 && (
U-Abo {daysUntilExpiry < 0 ? 'abgelaufen' : `läuft in ${daysUntilExpiry} Tagen ab`}
)}
);
}
// Client Detail Component
function ClientDetail({ client, onUpdateClient }) {
return (
{/* Client Header */}
{client.photo ? (

) : (
)}
{client.name}
Zimmer {client.roomNumber}
);
}
// Presence Section
function PresenceSection({ client, onUpdate }) {
const [notHomeReason, setNotHomeReason] = useState('');
const [customReason, setCustomReason] = useState('');
const reasons = ['Spazieren', 'Schule', 'Arzt', 'Wochenende weg', 'Andere'];
const togglePresence = () => {
if (client.isHome) {
onUpdate(client.id, { isHome: false });
} else {
onUpdate(client.id, { isHome: true, notHomeReason: '' });
setNotHomeReason('');
setCustomReason('');
}
};
const updateReason = (reason) => {
setNotHomeReason(reason);
if (reason !== 'Andere') {
onUpdate(client.id, { notHomeReason: reason });
}
};
const saveCustomReason = () => {
if (customReason.trim()) {
onUpdate(client.id, { notHomeReason: customReason });
}
};
return (
Anwesenheit
{!client.isHome && (
{notHomeReason === 'Andere' && (
setCustomReason(e.target.value)}
placeholder="Grund eingeben..."
className="flex-1 p-2 border rounded-lg dark:bg-gray-700 dark:border-gray-600 dark:text-white"
/>
)}
{client.notHomeReason && (
Grund: {client.notHomeReason}
)}
)}
);
}
// U-Abo Section
function UAboSection({ client, onUpdate }) {
const [editing, setEditing] = useState(false);
const [date, setDate] = useState(client.uAboExpiryDate || '');
const daysUntilExpiry = date
? Math.ceil((new Date(date) - new Date()) / (1000 * 60 * 60 * 24))
: null;
const saveDate = () => {
onUpdate(client.id, { uAboExpiryDate: date });
setEditing(false);
};
return (
U-Abo Status
{!editing ? (
{daysUntilExpiry !== null ? (
{daysUntilExpiry < 0
? 'U-Abo ist abgelaufen!'
: daysUntilExpiry === 0
? 'U-Abo läuft heute ab!'
: `U-Abo gültig noch ${daysUntilExpiry} Tage`}
Ablaufdatum: {new Date(date).toLocaleDateString('de-DE')}
) : (
Kein Ablaufdatum eingetragen
)}
) : (
)}
);
}
// Entries Section
function EntriesSection({ client, onUpdate }) {
const [showAdd, setShowAdd] = useState(false);
const [newEntry, setNewEntry] = useState({
category: '',
customCategory: '',
description: '',
status: 'open'
});
const categories = ['Gemeinde', 'Beistand(in)', 'Convalere', 'Schule', 'Gesundheit', 'Andere'];
const addEntry = () => {
if (!newEntry.category || !newEntry.description) return;
const entry = {
id: Date.now().toString(),
category: newEntry.category === 'Andere' ? newEntry.customCategory : newEntry.category,
description: newEntry.description,
status: 'open',
date: new Date().toISOString().split('T')[0]
};
onUpdate(client.id, { entries: [...client.entries, entry] });
setNewEntry({ category: '', customCategory: '', description: '', status: 'open' });
setShowAdd(false);
};
const toggleStatus = (entryId) => {
const updated = client.entries.map(e =>
e.id === entryId
? { ...e, status: e.status === 'open' ? 'finished' : 'open' }
: e
);
onUpdate(client.id, { entries: updated });
};
const deleteEntry = (entryId) => {
const updated = client.entries.filter(e => e.id !== entryId);
onUpdate(client.id, { entries: updated });
};
return (
Einträge
{showAdd && (
)}
{client.entries.map(entry => (
{entry.category}
{entry.status === 'open' ? 'Offen' : 'Erledigt'}
{entry.description}
{new Date(entry.date).toLocaleDateString('de-DE')}
))}
{client.entries.length === 0 && (
Keine Einträge vorhanden
)}
);
}
// Appointments Section
function AppointmentsSection({ client, onUpdate }) {
const [showAdd, setShowAdd] = useState(false);
const [newAppointment, setNewAppointment] = useState({
type: '',
customType: '',
date: '',
time: '',
description: ''
});
const types = ['Arzttermin', 'Gesprächstermin Schule', 'Gesprächstermin Wohngruppe', 'Gesprächstermin Beistand', 'Andere'];
const addAppointment = () => {
if (!newAppointment.type || !newAppointment.date) return;
const appointment = {
id: Date.now().toString(),
type: newAppointment.type === 'Andere' ? newAppointment.customType : newAppointment.type,
date: newAppointment.date,
time: newAppointment.time,
description: newAppointment.description
};
const updated = [...client.appointments, appointment].sort((a, b) =>
new Date(a.date) - new Date(b.date)
);
onUpdate(client.id, { appointments: updated });
setNewAppointment({ type: '', customType: '', date: '', time: '', description: '' });
setShowAdd(false);
};
const deleteAppointment = (appointmentId) => {
const updated = client.appointments.filter(a => a.id !== appointmentId);
onUpdate(client.id, { appointments: updated });
};
const isPast = (date) => new Date(date) < new Date().setHours(0, 0, 0, 0);
return (
Termine
{showAdd && (
)}
{client.appointments.map(appointment => (
{appointment.type}
{isPast(appointment.date) && (
Vergangen
)}
{new Date(appointment.date).toLocaleDateString('de-DE')}
{appointment.time && ` um ${appointment.time} Uhr`}
{appointment.description && (
{appointment.description}
)}
))}
{client.appointments.length === 0 && (
Keine Termine vorhanden
)}
);
}
// Client Modal Component
function ClientModal({ client, onSave, onClose }) {
const [formData, setFormData] = useState({
name: client?.name || '',
roomNumber: client?.roomNumber || '',
photo: client?.photo || null,
uAboExpiryDate: client?.uAboExpiryDate || ''
});
const handleSubmit = () => {
if (!formData.name || !formData.roomNumber) {
alert('Name und Zimmernummer sind erforderlich!');
return;
}
console.log("Submitting form data:", formData);
onSave(formData);
};
const handlePhotoChange = (e) => {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onloadend = () => {
setFormData({ ...formData, photo: reader.result });
};
reader.readAsDataURL(file);
}
};
return (
{client ? 'Klient bearbeiten' : 'Neuer Klient'}
);
}