# Panel webowy ŻyrarBOT Frontend napisany w **Vue 3 + TypeScript**, budowany przez **Vite**. Panel jest **samodzielną aplikacją we własnym kontenerze**. Backend wystawia wyłącznie API i steruje botem - nie serwuje żadnych plików statycznych. ## 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 przejmuje wtedy rolę nginxa i przekierowuje REST oraz WebSocket. 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 `Dockerfile` buduje panel w etapie `node:22-alpine`, a wynik serwuje `nginx:1.27-alpine`. Konfiguracja z `nginx.conf` przekazuje `/api` i `/ws` do usługi `discord-bot`, dzięki czemu przeglądarka widzi jedno źródło i nie potrzeba CORS-u. ```bash docker compose up --build # panel na :80, API na :8000 ``` Aby panel łączył się z backendem pod innym adresem, wystarczy podmienić `set $backend` w `nginx.conf` - obraz nie wymaga przebudowania frontendu. ## 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 ├── SettingsModal.vue ustawienia bota i kanałów logów ├── 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.