Frontend Overview
Ten dokument zbiera kluczowe filary frontendu Vista i sposób organizacji kodu.
Na tej stronie
Tech Stack
Dział zatytułowany „Tech Stack”graph TB subgraph "Frontend Stack" REACT["React 18.3.1<br/>UI Framework"] TS["TypeScript 5.6.3<br/>Type Safety"] TAILWIND["Tailwind CSS 4.1<br/>Styling"] FRAMER["Framer Motion 12.23<br/>Animations"] I18N["i18next 25.4<br/>Internationalization"] end
subgraph "Build & Dev Tools" VITE["Vite 6.3.5<br/>Build Tool"] VITEST["Vitest 3.2.4<br/>Testing"] STORYBOOK["Storybook 9.1<br/>Component Dev"] end
REACT --> VITE TS --> VITESTKluczowe liczby
Dział zatytułowany „Kluczowe liczby”| Kategoria | Liczba | Lokalizacja |
|---|---|---|
| React Components | ~330 | src/components/ |
| Custom Hooks | 170 | src/hooks/ |
| Services | 50 | src/services/ |
| Context Providers | 4 | src/contexts/ |
| Languages | 2 | Polski (primary), English |
Architektura aplikacji
Dział zatytułowany „Architektura aplikacji”src/├── components/ # ~330 komponentów UI│ ├── auth/ # Logowanie, biometria│ ├── visits/ # Workflow wizyt (SOAP)│ ├── patients/ # Zarządzanie pacjentami│ ├── calendar/ # Kalendarz i wizyty│ ├── settings/ # Konfiguracja│ ├── ai/ # Komponenty AI│ ├── audio/ # Przetwarzanie audio│ ├── layout/ # Sidebar, navigation│ ├── ui/ # Reusable UI (70+)│ └── ...│├── hooks/ # 58 custom hooks│ ├── audio/ # useRecording, useVAD│ ├── visits/ # useVisit, useSOAP│ └── ...│├── services/ # 50 serwisów│ ├── ai/ # UnifiedAIClient│ ├── patients/ # patientService│ └── ...│├── contexts/ # 4 główne konteksty│ ├── AuthContext.tsx│ ├── ThemeContext.tsx│ ├── SidebarContext.tsx│ └── NotificationContext.tsx│├── types/ # TypeScript definitions├── utils/ # Utility functions├── i18n/ # Translations (PL/EN)└── schemas/ # Zod validation schemasState Management
Dział zatytułowany „State Management”Vista używa React Context API zamiast Redux/Zustand dla prostszego mental model.
Context Providers
Dział zatytułowany „Context Providers”// Hierarchia providerów w App.tsx<AuthProvider> <ThemeProvider> <SidebarProvider> <NotificationProvider> <App /> </NotificationProvider> </SidebarProvider> </ThemeProvider></AuthProvider>| Context | Odpowiedzialność | Plik |
|---|---|---|
| AuthContext | User authentication, sessions, biometric auth | src/contexts/AuthContext.tsx |
| ThemeContext | Light/dark mode, Galaxy theme | src/contexts/ThemeContext.tsx |
| SidebarContext | Navigation state, mobile sidebar | src/contexts/SidebarContext.tsx |
| NotificationContext | Toast notifications, error messaging | src/contexts/NotificationContext.tsx |
Routing & Navigation
Dział zatytułowany „Routing & Navigation”Główne widoki
Dział zatytułowany „Główne widoki”type MenuItem = | 'dashboard' // Main overview | 'new-visit' // Create visit | 'browse-visits' // Visit management | 'calendar' // Appointments | 'analytics' // Reports | 'dictionary' // Medical terms | 'settings'; // ConfigurationNavigation features
Dział zatytułowany „Navigation features”- Deep linking - wsparcie dla appointments/patients
- Keyboard shortcuts -
Ctrl+N(nowa wizyta),Ctrl+F(szukaj) - Mobile-responsive sidebar
- Breadcrumb navigation w zagnieżdżonych widokach
Component Patterns
Dział zatytułowany „Component Patterns”Naming conventions
Dział zatytułowany „Naming conventions”| Typ | Konwencja | Przykład |
|---|---|---|
| Page components | *View.tsx | SettingsView.tsx |
| Form components | *Form.tsx | NewPatientForm.tsx |
| List components | *List.tsx | PatientsList.tsx |
| Editor components | *Editor.tsx | SOAPEditor.tsx |
| Modal components | *Modal.tsx | PasswordResetModal.tsx |
File structure per component
Dział zatytułowany „File structure per component”components/visits/├── NewVisitView.tsx # Main view├── VisitEditor.tsx # Edit form├── SOAPEditor.tsx # SOAP note editing├── AudioRecordingSection.tsx # Recording UI├── TranscriptionViewer.tsx # Transcript display├── AISuggestionsViewer.tsx # AI suggestions└── __tests__/ # Component testsStyling System
Dział zatytułowany „Styling System”Tailwind CSS 4.1
Dział zatytułowany „Tailwind CSS 4.1”// Przykład użycia Tailwind<div className="flex flex-col gap-4 p-6 bg-white dark:bg-gray-900 rounded-xl shadow-lg"> <h2 className="text-xl font-semibold text-gray-900 dark:text-white"> {title} </h2></div>Galaxy Theme (Glassmorphism)
Dział zatytułowany „Galaxy Theme (Glassmorphism)”// Galaxy theme configurationinterface GalaxyConfig { starDensity: number; // 0-100 (default: 15) opacity: number; // 0-1 (default: 0.6) animationSpeed: number; // 0-10 (default: 2) enableBlur: boolean; // Glass effect (default: true) vibrancyMaterial: 'HudWindow' | 'WindowBackground'; // macOS only}Performance Optimizations
Dział zatytułowany „Performance Optimizations”Lazy loading
Dział zatytułowany „Lazy loading”// Code splitting for major viewsconst Dashboard = lazy(() => import('./components/dashboard/Dashboard'));const SettingsView = lazy(() => import('./components/settings/SettingsView'));const CalendarView = lazy(() => import('./components/calendar/CalendarView'));Memoization
Dział zatytułowany „Memoization”// Selective re-rendering with useMemoconst filteredVisits = useMemo(() => { return visits.filter(visit => matchesFilters(visit, filters));}, [visits, filters]);
// Debounced searchconst debouncedSearch = useDebounce(searchQuery, 300);Virtualization
Dział zatytułowany „Virtualization”// For long lists (patients, visits)const VisitsList = React.memo(({ visits, filters }) => { const virtualizedVisits = useVirtualization(visits, { itemHeight: 120, overscan: 5, });
return <VirtualList items={virtualizedVisits} />;});Tauri Integration
Dział zatytułowany „Tauri Integration”IPC Communication
Dział zatytułowany „IPC Communication”// Frontend wywołuje komendy Tauri przez invokeimport { invoke } from '@tauri-apps/api/core';
const createVisit = async (data: CreateVisitRequest) => { const visit = await invoke<Visit>('create_visit', { patientId: data.patientId, userId: data.userId, visitData: data, }); return visit;};Safe Invoke Pattern
Dział zatytułowany „Safe Invoke Pattern”// Wrapper z error handlingexport async function safeInvoke<T>( command: string, args?: Record<string, unknown>): Promise<T> { try { return await invoke<T>(command, args); } catch (error) { console.error(`Command ${command} failed:`, error); throw new Error(getLocalizedErrorMessage(error)); }}Testing
Dział zatytułowany „Testing”Test stack
Dział zatytułowany „Test stack”- Vitest - Unit tests, component tests
- Testing Library - React component testing
- Playwright - E2E tests
Test structure
Dział zatytułowany „Test structure”src/├── __tests__/ # Integration tests├── components/__tests__/ # Component unit tests├── hooks/__tests__/ # Hook testing├── services/__tests__/ # Service logic tests└── e2e/ # Playwright E2E testsExample test
Dział zatytułowany „Example test”describe('SOAPEditor', () => { it('should update SOAP fields', async () => { render(<SOAPEditor visitId="test-id" />);
await userEvent.type( screen.getByLabelText('Podmiotowo'), 'Patient presented with...' );
expect(screen.getByLabelText('Podmiotowo')).toHaveValue( 'Patient presented with...' ); });});Frontend Transformation
Dział zatytułowany „Frontend Transformation”Migracja Streaming Audio
Dział zatytułowany „Migracja Streaming Audio”Streaming audio przechodzi z Tauri invoke na bezpośredni WebSocket do VistaScribe/Libraxis.
Komendy do migracji (engineBridge.ts):
| Stara komenda | Nowe rozwiązanie |
|---|---|
recording_start_session | WebSocket connect |
recording_push_chunk | WebSocket binary frame |
recording_finalize_session | WebSocket close + ‘end’ |
transcription_start_stream | WebSocket to STT endpoint |
transcription_push_chunk | WebSocket audio stream |
Nowy WebSocket client:
interface STTWebSocketConfig { language: string; sampleRate: number; onInterim: (text: string, confidence: number) => void; onFinal: (text: string, words?: Word[]) => void; onError: (error: Error) => void;}
export class STTWebSocketClient { private ws: WebSocket | null = null;
async connect(config: STTWebSocketConfig): Promise<void> { const endpoint = import.meta.env.DEV ? 'ws://127.0.0.1:8237/ws/transcribe' : 'wss://api.libraxis.cloud/stt/v1/stream'; // ... }
async sendAudio(chunk: ArrayBuffer): Promise<void> { // Binary frame }
async close(): Promise<void> { // Send 'end' and close }}Synchronizacja typów z Backend
Dział zatytułowany „Synchronizacja typów z Backend”Po zmianach w backend, synchronizuj typy:
# Sprawdź contractloctree src src-tauri/src -A --preset-tauri --fail-on-missing-handlers
# Aktualizuj typy# src/types/api.ts - dodaj/usuń komendy zgodnie z backendCleanup Frontend
Dział zatytułowany „Cleanup Frontend”Narzędzia:
# Nieużywane exportypnpm knip --reporter json > knip-report.json
# TypeScript checkpnpm tsc --noEmit
# ESLintpnpm eslint src/ --ext .ts,.tsxGhost event listeners do sprawdzenia:
tauri://created- czy używane?vista-devtools:console- czy emitowane?
Potencjalna reorganizacja hooks/
Dział zatytułowany „Potencjalna reorganizacja hooks/”Obecna struktura (płaska, 50+ hooków) może być zgrupowana:
hooks/├── common/ # useDebounce, useClickOutside├── auth/ # useAuth, useBiometricAuth├── patients/ # usePatientSelection├── visits/ # useVisitEditor├── audio/ # (już istnieje)└── workspace/ # (już istnieje)Related
Dział zatytułowany „Related”- Components - Struktura komponentów
- Hooks - Custom hooks
- Styling - Z-Index i Vibrancy