# Panel webowy ŻyrarBOT Frontend napisany w **Vue 3 + TypeScript**, budowany przez **Vite**. Panel jest budowany jako statyczny frontend i w produkcji serwuje go Pythonowy backend razem z API. ## Praca lokalna ```bash npm install npm run dev # http://localhost:5173, proxy /api i /ws na backend :8000 ``` Backend uruchamiamy równolegle (`python main.py`). Serwer deweloperski Vite przekierowuje REST oraz WebSocket do backendu. Inny adres backendu wskazuje zmienna `VITE_BACKEND_URL`: ```bash VITE_BACKEND_URL=http://192.168.1.10:8000 npm run dev ``` ## Budowanie ```bash npm run build # typecheck + bundle do dist/ npm run smoke # test dymny zbudowanego artefaktu ``` ## Kontener Główny `Dockerfile` buduje panel w etapie `node:22-alpine`, a wynik kopiuje do obrazu Pythona. FastAPI serwuje `/`, `/api` i `/ws` z jednego kontenera. ```bash docker compose up --build # panel i API na :80 ``` ## Struktura ``` src/ ├── main.ts montowanie aplikacji ├── App.vue układ pulpitu i przełączanie okien modalnych ├── api/client.ts typowane wywołania REST - jedyne miejsce z adresami ├── types/status.ts kontrakt danych z /api/status i WebSocketu ├── composables/ │ ├── useBotStatus.ts jedno połączenie WebSocket na aplikację │ ├── useToasts.ts kolejka powiadomień + helper run() │ ├── useTrackProgress.ts płynny pasek postępu między pakietami z serwera │ └── useUploads.ts serwerowa baza plików ├── utils/plural.ts polska odmiana liczebników ├── assets/style.css system stylów (zachowany wygląd sprzed przepisania) └── components/ ├── AppHeader.vue nagłówek ze statusem połączenia ├── VoiceChannelPanel.vue wybór kanału głosowego ├── PlayerPanel.vue odtwarzacz, postęp, głośność, zapętlanie ├── AddTrackPanel.vue dodawanie po linku lub frazie ├── UploadsPanel.vue 10 ostatnio używanych plików + wysyłanie ├── UploadedFileRow.vue wiersz pliku (współdzielony z oknem modalnym) ├── QueuePanel.vue kolejka z przeciąganiem i zmianą kolejności ├── QueueItem.vue pozycja kolejki wraz z limitem odtworzeń ├── HistoryPanel.vue historia z ponownym dodaniem do kolejki ├── ModalShell.vue wspólna ramka okien modalnych ├── UploadsLibraryModal.vue pełna lista plików na serwerze └── ToastHost.vue powiadomienia ``` ## Zasady - **Stan płynie z serwera.** Nie duplikujemy stanu bota lokalnie - komponenty czytają `status` z WebSocketu i wywołują API. Wyjątkiem są pola formularzy podczas edycji oraz suwak głośności w trakcie przeciągania. - **Zero `innerHTML`.** Poprzednia wersja składała wiersze kolejki ze stringów, przez co tytuły utworów trafiały do DOM bez escapowania. Teraz wszystko idzie przez szablony Vue. - **Ikony jako komponenty** (`lucide-vue-next`) zamiast skryptu z CDN.