diff --git a/frontend/README.md b/frontend/README.md new file mode 100644 index 0000000..c0dd3d3 --- /dev/null +++ b/frontend/README.md @@ -0,0 +1,83 @@ +# 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.