Calendar
Na tej stronie
Przegląd komend
Dział zatytułowany „Przegląd komend”Appointments (Wizyty w kalendarzu)
Dział zatytułowany „Appointments (Wizyty w kalendarzu)”| Komenda | Opis | Typ |
|---|---|---|
create_appointment | Tworzy wizytę w kalendarzu | write |
update_appointment | Aktualizuje wizytę | write |
get_appointments | Pobiera wizyty wg filtra | query |
cancel_appointment | Anuluje wizytę | write |
complete_appointment | Oznacza jako zrealizowaną | write |
delete_appointment | Usuwa wizytę | write |
Time Blocks (Blokady czasowe)
Dział zatytułowany „Time Blocks (Blokady czasowe)”| Komenda | Opis | Typ |
|---|---|---|
create_time_block | Tworzy blokadę czasową | write |
update_time_block | Aktualizuje blokadę | write |
get_time_blocks | Pobiera blokady wg filtra | query |
delete_time_block | Usuwa blokadę | write |
Appointment Data Model
Dział zatytułowany „Appointment Data Model”erDiagram APPOINTMENT { string appointment_id PK string patient_id FK string veterinarian_id FK string visit_id FK "Opcjonalnie - po realizacji" string parent_appointment_id FK "Dla serii"
date scheduled_date "YYYY-MM-DD" time scheduled_time "HH:MM" int duration_minutes
string appointment_type "consultation, vaccination, surgery..." string status "scheduled, completed, cancelled, no_show" text notes
boolean is_recurring string recurrence_pattern "weekly, monthly..." date recurrence_end_date
boolean reminder_enabled boolean reminder_email_sent timestamp reminder_email_sent_at
string[] additional_staff_ids "JSON array"
timestamp created_at timestamp updated_at string created_by string updated_by }
PATIENT ||--o{ APPOINTMENT : "has" USER ||--o{ APPOINTMENT : "conducts" VISIT ||--o| APPOINTMENT : "realized as"Appointment Status Flow
Dział zatytułowany „Appointment Status Flow”stateDiagram-v2 [*] --> scheduled: Utworzenie
scheduled --> completed: Realizacja scheduled --> cancelled: Anulowanie scheduled --> no_show: Niestawienie się
completed --> [*] cancelled --> [*] no_show --> scheduled: Przełożenie
note right of scheduled: Można edytować note right of completed: Powiązana z VisitCalendar Architecture
Dział zatytułowany „Calendar Architecture”flowchart TB subgraph CalendarView["CalendarView"] MONTH[📅 Month View] WEEK[📆 Week View] DAY[📋 Day View] end
subgraph Data["Źródła danych"] APPTS[Appointments] BLOCKS[Time Blocks] PATIENTS[Patients] VETS[Veterinarians] end
subgraph Hooks["Hooki"] useAppointmentsList useCalendarData useCalendarState useCalendarMutations end
CalendarView --> Hooks Hooks --> DataAppointments
Dział zatytułowany „Appointments”create_appointment
Dział zatytułowany „create_appointment”Tworzy nową wizytę w kalendarzu:
// Frontend (src/services/appointmentsService.ts)interface CreateAppointmentRequest { patient_id: string; veterinarian_id: string; scheduled_date: string; // 'YYYY-MM-DD' scheduled_time: string; // 'HH:MM' duration_minutes: number; // default: 30 appointment_type: string; // 'consultation', 'vaccination', etc. notes?: string; reminder_enabled?: boolean; // default: true additional_staff_ids?: string[];
// Dla serii is_recurring?: boolean; recurrence_pattern?: 'weekly' | 'biweekly' | 'monthly'; recurrence_end_date?: string;}
const appointment = await appointmentsService.createAppointment( request, userId, sessionId);
// Wewnętrznie:// safeInvoke('create_appointment', withSessionPayload({ args: { request, user_id } }, sessionId))get_appointments
Dział zatytułowany „get_appointments”Pobiera wizyty z filtrami:
interface GetAppointmentsFilter { veterinarian_id?: string; patient_id?: string; start_date?: string; // 'YYYY-MM-DD' end_date?: string; status?: 'scheduled' | 'completed' | 'cancelled' | 'no_show'; user_id?: string; // Dla filtrowania po zalogowanym is_admin?: boolean; // Admin widzi wszystkie}
const appointments = await appointmentsService.getAppointments( filter, sessionId);
// Responseinterface Appointment { appointment_id: string; patient_id: string; veterinarian_id: string; visit_id?: string; scheduled_date: string; scheduled_time: string; duration_minutes: number; appointment_type: string; status: 'scheduled' | 'completed' | 'cancelled' | 'no_show'; notes?: string; is_recurring: boolean; recurrence_pattern?: string; reminder_enabled: boolean;
// Joined fields patient_name?: string; veterinarian_name?: string; owner_phone?: string; additional_staff_names?: string[];}update_appointment
Dział zatytułowany „update_appointment”Aktualizuje wizytę (np. przesunięcie, zmiana lekarza):
interface UpdateAppointmentRequest { appointment_id: string; scheduled_date?: string; scheduled_time?: string; duration_minutes?: number; veterinarian_id?: string; appointment_type?: string; notes?: string; status?: 'scheduled' | 'completed' | 'cancelled' | 'no_show'; additional_staff_ids?: string[];}
await appointmentsService.updateAppointment(request, userId, sessionId);cancel_appointment
Dział zatytułowany „cancel_appointment”Anuluje wizytę:
await appointmentsService.cancelAppointment( appointmentId, userId, sessionId);
// status → 'cancelled'complete_appointment
Dział zatytułowany „complete_appointment”Oznacza wizytę jako zrealizowaną i powiązuje z Visit:
await appointmentsService.completeAppointment( appointmentId, visitId, // Powiązana wizyta medyczna userId, sessionId);
// status → 'completed'// visit_id → visitIddelete_appointment
Dział zatytułowany „delete_appointment”Usuwa wizytę (hard delete):
await appointmentsService.deleteAppointment(appointmentId, sessionId);Time Blocks
Dział zatytułowany „Time Blocks”Blokady czasowe służą do oznaczania niedostępności lekarza (urlop, spotkanie, przerwa):
erDiagram TIME_BLOCK { string time_block_id PK string user_id FK "Lekarz"
string title date start_date date end_date time start_time time end_time string reason
boolean recurring string[] recurring_days "JSON: ['monday', 'wednesday']"
timestamp created_at timestamp updated_at string created_by }
USER ||--o{ TIME_BLOCK : "has"create_time_block
Dział zatytułowany „create_time_block”interface CreateTimeBlockRequest { title: string; start_date: string; // 'YYYY-MM-DD' end_date: string; start_time: string; // 'HH:MM' end_time: string; reason?: string; recurring?: boolean; recurring_days?: ('monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday' | 'sunday')[];}
const timeBlock = await timeBlockService.createTimeBlock( request, userId);get_time_blocks
Dział zatytułowany „get_time_blocks”interface TimeBlockFilter { start_date?: string; end_date?: string; date_range?: { start: string; end: string };}
const timeBlocks = await timeBlockService.getTimeBlocks(filter);
// Cache lokalny (TTL 30s) dla getTimeBlocksForDateupdate_time_block
Dział zatytułowany „update_time_block”interface UpdateTimeBlockRequest { time_block_id: string; title?: string; start_date?: string; end_date?: string; start_time?: string; end_time?: string; reason?: string; recurring?: boolean; recurring_days?: string[];}
await timeBlockService.updateTimeBlock(request, userId);delete_time_block
Dział zatytułowany „delete_time_block”await timeBlockService.deleteTimeBlock(timeBlockId, userId);Conflict Detection
Dział zatytułowany „Conflict Detection”Serwis sprawdza konflikty przed tworzeniem wizyty:
const conflicts = await appointmentsService.checkForConflicts( veterinarianId, date, time, durationMinutes, excludeAppointmentId // Opcjonalne - przy edycji);
// Sprawdza:// 1. Istniejące appointments w tym samym czasie// 2. Time blocks (niedostępność)// Zwraca: Appointment[] - lista konfliktującychisTimeSlotBlocked
Dział zatytułowany „isTimeSlotBlocked”// Sprawdza czy slot jest zablokowanyconst isBlocked = await timeBlockService.isTimeSlotBlocked( veterinarianId, date, startTime, endTime);
// Sync wersja (z cache)const isBlockedSync = timeBlockService.isTimeSlotBlockedSync( veterinarianId, date, startTime, endTime);Calendar Hooks
Dział zatytułowany „Calendar Hooks”useAppointmentsList
Dział zatytułowany „useAppointmentsList”const { appointments, loading, error, refreshAppointments} = useAppointmentsList();
// Automatycznie:// - Filtruje po user_id (lub wszystkie dla admina)// - Mapuje ServiceAppointment → UI Appointment// - Dodaje title = appointment_type + patient_nameuseCalendarData
Dział zatytułowany „useCalendarData”const { patients, // CalendarDataPatient[] veterinarians, // CalendarDataUser[] loading} = useCalendarData();
// Pobiera:// - patientService.getAllPatients()// - userService.getActiveVeterinarians()useCalendarState
Dział zatytułowany „useCalendarState”const { view, // 'month' | 'week' | 'day' currentDate, selectedDay, selectedAppointment,
navigatePrevious, navigateNext, navigateToday, handleViewChange, handleDayClick, handleAppointmentClick,} = useCalendarState({ onDayClick, onAppointmentClick, onViewChange });useCalendarMutations
Dział zatytułowany „useCalendarMutations”const { deleteAppointment, exportCalendar, updateAppointment,} = useCalendarMutations(userId, appointments);Drag & Drop
Dział zatytułowany „Drag & Drop”Kalendarz obsługuje przeciąganie wizyt:
const handleAppointmentMove = async ( appointmentId: string, newDate: Date, newTime: string) => { if (!user) { notify('calendar:userNotAuthenticated'); return; }
const formattedDate = formatSafe(newDate, 'yyyy-MM-dd');
await appointmentsService.updateAppointment( { appointment_id: appointmentId, scheduled_date: formattedDate, scheduled_time: newTime, }, user.user_id );
notify('calendar:appointmentMovedSuccess'); refreshAppointments();};Recurring Appointments
Dział zatytułowany „Recurring Appointments”Tworzenie serii wizyt:
const handleRecurringAppointmentCreate = async ( newAppointments: Partial<Appointment>[]) => { for (const apt of newAppointments) { await appointmentsService.createAppointment( { patient_id: apt.patient_id!, veterinarian_id: apt.veterinarian_id!, scheduled_date: apt.scheduled_date!, scheduled_time: apt.scheduled_time!, duration_minutes: apt.duration_minutes!, appointment_type: apt.appointment_type!, notes: apt.notes, is_recurring: true, recurrence_pattern: apt.recurrence_pattern, reminder_enabled: true, }, user.user_id ); }
notify('calendar:recurringAppointmentsCreatedSuccess'); refreshAppointments();};iCal Export
Dział zatytułowany „iCal Export”Eksport kalendarza do formatu iCal:
await exportService.exportCalendarToICal(appointments);
// Generuje plik .ics z VEVENT dla każdego spotkania:// - DTSTART, DTEND// - SUMMARY (appointment_type + patient_name)// - DESCRIPTION (notes)// - STATUS
// Zapisuje przez Tauri dialog (saveFile)AppointmentScheduler Component
Dział zatytułowany „AppointmentScheduler Component”Dialog do tworzenia wizyt:
<AppointmentScheduler patients={patients} veterinarians={veterinarians} existingAppointments={appointments.map(a => ({ date: a.scheduled_date, duration: a.duration_minutes }))} prefilledDate={schedulerState.date} prefilledTime={schedulerState.time} onSchedule={handleAppointmentCreated} onCancel={() => setSchedulerOpen(false)} onPatientCreated={handlePatientCreated}/>Error Codes
Dział zatytułowany „Error Codes”| Kod | Opis | Rozwiązanie |
|---|---|---|
appointment_not_found | Wizyta nie istnieje | Sprawdź ID |
time_slot_conflict | Konflikt czasowy | Wybierz inny termin |
time_slot_blocked | Lekarz niedostępny | Sprawdź blokady |
patient_not_found | Pacjent nie istnieje | Sprawdź patient_id |
veterinarian_not_found | Lekarz nie istnieje | Sprawdź veterinarian_id |
invalid_date_format | Nieprawidłowy format daty | Użyj YYYY-MM-DD |
invalid_time_format | Nieprawidłowy format czasu | Użyj HH:MM |
no_such_column | Brak migracji DB | Zaktualizuj bazę danych |
Calendar → Visits Flow
Dział zatytułowany „Calendar → Visits Flow”Appointment może być konwertowany na pełną wizytę:
sequenceDiagram participant User participant Calendar as CalendarView participant Hook as useAppointmentForm participant API as appointmentApi participant VisitAPI as visitApi participant DB as SQLite
User->>Calendar: Click appointment Calendar->>Hook: openAppointment(id) Hook->>API: getAppointment(id) API->>DB: SELECT * FROM appointments DB-->>API: Appointment data API-->>Hook: appointment
User->>Calendar: Start Visit Calendar->>VisitAPI: createVisit({patient_id, appointment_id}) VisitAPI->>DB: INSERT INTO visits DB-->>VisitAPI: visit_id
VisitAPI->>API: updateAppointment({visit_id, status: 'in_progress'}) API->>DB: UPDATE appointments SET visit_id = ? DB-->>API: OK
VisitAPI-->>Calendar: Visit created Calendar->>Calendar: Navigate to VisitEditorCalendar Module Stats
Dział zatytułowany „Calendar Module Stats”| Metric | Value |
|---|---|
| Files | ~25 |
| LOC | ~15,000 |
| Tauri Commands | 10 |
| Key Hook | useAppointmentForm |
Calendar Hooks
Dział zatytułowany „Calendar Hooks”| Hook | LOC | Opis |
|---|---|---|
useAppointmentForm | ~400 | CRUD operations, validation |
useAppointmentsList | ~200 | List & filtering |
useTimeBlocks | ~150 | Time block management |
useCalendarDragDrop | ~300 | Drag & drop logic |
Powiązane dokumenty
Dział zatytułowany „Powiązane dokumenty”- Visits Commands - Realizacja wizyt
- Patients Commands - Dane pacjentów
- Settings - Clinic - Godziny pracy kliniki
- Database Schema - Schemat appointments