Patients
Przegląd komend
Dział zatytułowany „Przegląd komend”| Komenda | Opis | Typ |
|---|---|---|
get_all_patients | Pobiera listę wszystkich pacjentów | query |
get_patient | Pobiera pojedynczego pacjenta po ID | query |
create_patient | Tworzy nowego pacjenta | write |
update_patient | Aktualizuje dane pacjenta | write |
delete_patient | Usuwa pacjenta | write |
search_patients | Wyszukuje pacjentów po query | query |
get_patient_visits | Pobiera wizyty pacjenta | query |
export_patients | Eksportuje pacjentów (JSON/CSV) | query |
import_patients | Importuje pacjentów z pliku | write |
Patient Data Model
Dział zatytułowany „Patient Data Model”erDiagram PATIENT { string patient_id PK string name "Imię zwierzęcia" string species "pies, kot, królik..." string breed "Rasa" date date_of_birth string sex "male, female, unknown" float weight_kg string chip_number "Numer chipa" string coat_color "Umaszczenie" boolean is_neutered string owner_id FK string clinic_id FK text special_notes text allergies string status "active, deceased, transferred" timestamp created_at timestamp updated_at }
OWNER { string owner_id PK string name string email string phone string address }
PATIENT }o--|| OWNER : "belongs to"Patients Flow
Dział zatytułowany „Patients Flow”flowchart TB subgraph PatientsView["PatientsView"] LIST[Lista pacjentów] SEARCH[Wyszukiwarka] FILTERS[Filtry] end
subgraph Actions["Akcje"] NEW[➕ Nowy pacjent] EDIT[✏️ Edycja] DELETE[🗑️ Usuń] VIEW[👁️ Szczegóły] end
subgraph Backend["Tauri Backend"] GET[get_all_patients] CREATE[create_patient] UPDATE[update_patient] DEL[delete_patient] SRCH[search_patients] end
LIST --> GET SEARCH --> SRCH NEW --> CREATE EDIT --> UPDATE DELETE --> DEL
CREATE -.->|Event| LIST UPDATE -.->|Event| LIST DEL -.->|Event| LISTKomendy CRUD
Dział zatytułowany „Komendy CRUD”get_all_patients
Dział zatytułowany „get_all_patients”Pobiera listę wszystkich pacjentów z joinowanymi danymi właściciela:
// Frontend (src/services/patientService.ts)const patients = await safeInvoke<Patient[]>( 'get_all_patients', withSessionPayload({}));
// Response zawiera:interface Patient { patient_id: string; name: string; species: string; breed?: string; date_of_birth?: string; sex?: 'male' | 'female' | 'unknown'; weight_kg?: number; chip_number?: string; coat_color?: string; is_neutered?: boolean; special_notes?: string; allergies?: string; status: 'active' | 'deceased' | 'transferred'; created_at: string; updated_at: string;
// Joined fields owner_id?: string; owner_name?: string; owner_phone?: string; owner_email?: string; clinic_id?: string;}get_patient
Dział zatytułowany „get_patient”Pobiera pojedynczego pacjenta z pełnymi danymi:
const patient = await safeInvoke<Patient | null>( 'get_patient', withSessionPayload({ patient_id }));create_patient
Dział zatytułowany „create_patient”Tworzy nowego pacjenta:
sequenceDiagram participant UI as NewPatientView participant Service as patientService participant Tauri as Tauri Backend participant DB as SQLite
UI->>Service: createPatient(data) Service->>Service: validatePatientData(data) Service->>Tauri: create_patient(patient_data)
Tauri->>Tauri: Generate UUID Tauri->>DB: INSERT INTO patients
alt Owner nie istnieje Tauri->>DB: INSERT INTO owners end
DB-->>Tauri: OK Tauri-->>Service: Patient
Tauri--)UI: Event: patient-created
Service-->>UI: Patient UI->>UI: Navigate → Patient Profile// Frontendinterface CreatePatientRequest { name: string; species: string; breed?: string; date_of_birth?: string; sex?: 'male' | 'female' | 'unknown'; weight_kg?: number; chip_number?: string; coat_color?: string; is_neutered?: boolean; special_notes?: string; allergies?: string;
// Owner data (can be new or existing) owner_id?: string; // Existing owner owner_name?: string; // New owner owner_phone?: string; owner_email?: string; owner_address?: string;}
const newPatient = await safeInvoke<Patient>( 'create_patient', withSessionPayload({ patient_data: request }));update_patient
Dział zatytułowany „update_patient”Aktualizuje dane pacjenta:
interface UpdatePatientRequest { patient_id: string; // Required name?: string; species?: string; breed?: string; date_of_birth?: string; sex?: string; weight_kg?: number; chip_number?: string; coat_color?: string; is_neutered?: boolean; special_notes?: string; allergies?: string; status?: 'active' | 'deceased' | 'transferred'; owner_id?: string;}
const updated = await safeInvoke<Patient>( 'update_patient', withSessionPayload({ patient_data: request }));
// Emituje event: patient-updateddelete_patient
Dział zatytułowany „delete_patient”Usuwa pacjenta (soft delete przez zmianę statusu lub hard delete):
// Frontend (src/services/patientService.ts)await safeInvoke( 'delete_patient', withSessionPayload({ patient_id }));
// Emituje event: patient-deletedWyszukiwanie
Dział zatytułowany „Wyszukiwanie”search_patients
Dział zatytułowany „search_patients”Wyszukuje pacjentów po nazwie, gatunku, rasie lub danych właściciela:
// Frontendconst results = await safeInvoke<Patient[]>( 'search_patients', withSessionPayload({ query: 'Burek' }));
// Backend szuka w:// - patients.name// - patients.species// - patients.breed// - patients.chip_number// - owners.name// - owners.phonePowiązane wizyty
Dział zatytułowany „Powiązane wizyty”get_patient_visits
Dział zatytułowany „get_patient_visits”Pobiera wszystkie wizyty pacjenta:
const visits = await safeInvoke<Visit[]>( 'get_patient_visits', withSessionPayload({ patient_id }));Export / Import
Dział zatytułowany „Export / Import”export_patients
Dział zatytułowany „export_patients”Eksportuje wszystkich pacjentów do pliku:
// Frontend (src/components/settings/PrivacySettings.tsx)const data = await safeInvoke<string>( 'export_patients', withSessionPayload({ format: 'json' }) // lub 'csv');
// Następnie zapis do pliku przez Tauri dialogawait saveFile(data, 'patients.json');import_patients
Dział zatytułowany „import_patients”Importuje pacjentów z pliku:
const result = await safeInvoke<ImportResult>( 'import_patients', withSessionPayload({ format: 'json', data: fileContent }));
interface ImportResult { imported: number; skipped: number; errors: string[];}Tauri Events
Dział zatytułowany „Tauri Events”Backend emituje eventy przy zmianach, pozwalając UI na reaktywne odświeżanie:
| Event | Payload | Kiedy |
|---|---|---|
patient-created | { patient_id } | Po utworzeniu pacjenta |
patient-updated | { patient_id } | Po aktualizacji pacjenta |
patient-deleted | { patient_id } | Po usunięciu pacjenta |
// Frontend - nasłuchiwanie eventówimport { listen } from '@tauri-apps/api/event';
useEffect(() => { const unlisten = listen<{ patient_id: string }>('patient-created', (event) => { console.log('New patient:', event.payload.patient_id); refreshPatients(); });
return () => { unlisten.then(fn => fn()); };}, []);Cache i deduplikacja
Dział zatytułowany „Cache i deduplikacja”Frontend używa dedupeGet do cachowania i deduplikacji requestów:
export const patientService = { getAllPatients: async () => { const sessionId = requireSessionId(); const cacheKey = `patients:${sessionId}:all`;
return dedupeGet(cacheKey, async () => { return safeInvoke<Patient[]>( 'get_all_patients', withSessionPayload({}) ); }); },
// Po mutacji - inwalidacja cache createPatient: async (data: CreatePatientRequest) => { const result = await safeInvoke<Patient>( 'create_patient', withSessionPayload({ patient_data: data }) );
invalidateDedupePrefix('patients:'); // Czyści cache return result; }};UI Components
Dział zatytułowany „UI Components”PatientsView
Dział zatytułowany „PatientsView”Główny widok listy pacjentów:
const PatientsView: React.FC = () => { const { patients, loading, error, refresh } = usePatients(); const [searchQuery, setSearchQuery] = useState(''); const [filters, setFilters] = useState<PatientFilters>({});
// Filtrowanie po stronie FE const filteredPatients = useMemo(() => { return patients.filter(p => { if (searchQuery && !matchesSearch(p, searchQuery)) return false; if (filters.species && p.species !== filters.species) return false; if (filters.status && p.status !== filters.status) return false; return true; }); }, [patients, searchQuery, filters]);
return ( <div> <PatientSearchBar value={searchQuery} onChange={setSearchQuery} /> <PatientFilters value={filters} onChange={setFilters} /> <PatientsList patients={filteredPatients} /> </div> );};PatientCard
Dział zatytułowany „PatientCard”Karta pojedynczego pacjenta:
interface PatientCardProps { patient: Patient; onEdit: () => void; onDelete: () => void; onViewDetails: () => void;}Error Codes
Dział zatytułowany „Error Codes”| Kod | Opis | Rozwiązanie |
|---|---|---|
patient_not_found | Pacjent nie istnieje | Sprawdź ID |
duplicate_chip_number | Numer chipa już istnieje | Użyj innego numeru |
invalid_species | Nieznany gatunek | Sprawdź dozwolone wartości |
owner_not_found | Właściciel nie istnieje | Utwórz właściciela |
import_validation_error | Błąd walidacji importu | Sprawdź format pliku |
Powiązane dokumenty
Dział zatytułowany „Powiązane dokumenty”- Visits Commands - Komendy wizyt
- Database Schema - Schemat bazy danych
- Settings - Export/Import - Eksport danych