Skip to content

diwad-code/dyzury2

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

121 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Dyżury 2 - dokumentacja aplikacji

Aktualna instancja online działa pod adresem: https://www.itgohome.com/dyzury-git1/.

To lekka aplikacja webowa do planowania dyżurów, rejestrowania nadgodzin, obsługi zastępstw i budowania zbiorczych podsumowań czasu dyżuru. Projekt został przygotowany jako prosty system do wdrożenia na zwykłym hostingu PHP/MySQL, bez frameworków, builda frontendowego i dodatkowych zależności serwerowych.

1. Cel aplikacji

Aplikacja zastępuje pracę na arkuszach i rozproszonych zestawieniach. W praktyce obsługuje cztery główne obszary:

  • plan dyżurów w widoku kalendarza,
  • ewidencję nadgodzin i zgłoszeń,
  • ewidencję zastępstw między pracownikami,
  • podsumowanie godzin dyżuru netto.

System jest zoptymalizowany pod prostą obsługę:

  • wybór pracownika z listy,
  • szybkie przypisanie dyżuru do dnia i slotu,
  • szybkie wyczyszczenie całego dnia,
  • eksport danych do plików otwieranych w Excelu,
  • awaryjny fallback diagnostyczny i demonstracyjny.

2. Stack technologiczny

Frontend

  • index.html
  • czysty HTML, CSS i JavaScript
  • brak frameworka SPA, brak npm, brak bundlera

Backend

  • api.php
  • PHP 7.4+ / 8.x
  • PDO
  • JSON API

Baza danych

  • MySQL / MariaDB
  • schemat w sql\schema.sql

Integracje zewnętrzne

  • Nager.Date API do pobierania świąt w Polsce

3. Architektura rozwiązania

Architektura jest świadomie prosta:

  1. index.html ładuje interfejs, utrzymuje stan aplikacji i komunikuje się z api.php.
  2. api.php przyjmuje żądania GET, POST, DELETE, wykonuje operacje na bazie i zwraca czysty JSON.
  3. Baza przechowuje pracowników, dyżury, nadgodziny i zastępstwa.
  4. Frontend sam renderuje kalendarz, listy, tabele podsumowań i eksporty XLS.

Najważniejsza cecha wdrożeniowa: projekt nie wymaga procesu budowania. W praktyce oznacza to, że do uruchomienia wystarczą pliki statyczne, PHP i działająca baza MySQL.

4. Najważniejsze funkcje biznesowe

4.1 Planowanie dyżurów

Aplikacja pokazuje miesiąc w formie kalendarza. Dla każdego dnia:

  • rozpoznaje, czy dzień jest roboczy, weekendowy lub świąteczny,
  • pokazuje już przypisane sloty,
  • pokazuje wolne sloty możliwe do obsadzenia,
  • pozwala przypisać pojedynczy slot albo cały dzień,
  • pozwala usunąć pojedynczy dyżur lub wyczyścić cały dzień.

4.2 Nadgodziny

Każdy wpis nadgodzin zawiera:

  • pracownika,
  • datę i godzinę rozpoczęcia,
  • datę i godzinę zakończenia,
  • liczbę zgłoszeń,
  • opis czynności.

Wpisy można:

  • dodawać,
  • edytować,
  • usuwać,
  • filtrować per pracownik,
  • oglądać w widoku miesięcznym lub kwartalnym,
  • eksportować do XLS.

4.3 Zastępstwa

Moduł zastępstw zapisuje przekazanie fragmentu dyżuru od jednej osoby do drugiej. Każdy wpis ma:

  • datę,
  • godzinę od,
  • godzinę do,
  • osobę przekazującą,
  • osobę przejmującą.

Zastępstwa wpływają na podsumowanie godzin dyżuru: czas jest odejmowany osobie oddającej i dodawany osobie przejmującej.

4.4 Podsumowania

Podsumowanie wylicza dla pracownika:

  • sumę godzin wynikających z przypisanych zmian,
  • sumę nadgodzin,
  • dyżur netto: dyżur - nadgodziny,
  • łączną liczbę zgłoszeń.

Widoki podsumowania:

  • miesiąc,
  • kwartał,
  • rok.

5. Reguły biznesowe

5.1 Sloty dyżurów

System korzysta z trzech slotów:

Slot Zakres Minuty Godziny dziesiętne
night 00:00-07:30 450 7.50
day 07:30-15:05 455 7.58
evening 15:05-23:59 534 8.92

5.2 Dostępność slotów

  • w dni robocze dostępne są tylko: night, evening
  • w weekendy i święta dostępne są: night, day, evening

Święta są pobierane z https://date.nager.at/api/v3/PublicHolidays/{rok}/PL.

Jeżeli pobranie świąt się nie powiedzie, aplikacja działa dalej, ale bez zewnętrznej listy świąt.

5.3 Unikalność zmian

W bazie działa ograniczenie:

  • jeden slot może wystąpić tylko raz dla danego dnia

Realizowane jest to przez:

  • unikalny klucz (shift_date, slot) w tabeli shifts,
  • kontrolę po stronie API, która zwraca 409 Slot already assigned, jeżeli slot jest już zajęty.

5.4 Zaokrąglanie nadgodzin

Nadgodziny są zaokrąglane zawsze w górę do rozpoczętego bloku 30 minut:

  • 1-30 minut = 0.5 h
  • 31-60 minut = 1.0 h
  • 61-90 minut = 1.5 h

Logika w backendzie:

$roundedHalfHours = ceil($minutes / 30) / 2.0;

5.5 Zastępstwa w podsumowaniu

Podsumowanie nie traktuje zastępstwa jako osobnego typu dyżuru. Zamiast tego:

  • odejmuje czas od from_employee_id,
  • dodaje ten sam czas do to_employee_id.

Dzięki temu raport odzwierciedla rzeczywiście wykonany dyżur.

5.6 Ograniczenia przypisań po stronie backendu

Backend blokuje przypisania, które naruszają aktualny model danych:

  • nie można przypisać do dyżuru pracownika nieaktywnego (employees.active = 0),
  • nie można zapisać zastępstwa z osobą oddającą lub przejmującą, która jest nieaktywna,
  • osoba oddająca w zastępstwie musi mieć w tym dniu przypisany slot dyżurowy pokrywający cały zakres start_time - end_time.

Ograniczenie modelu: w obecnym schemacie nie ma tabel/pól opisujących kompetencje lub uprawnienia per typ zmiany, więc backend nie może walidować bardziej szczegółowych kwalifikacji niż status aktywności i faktyczne przypisanie do slotu.

6. Struktura projektu

Pliki główne

  • index.html - cały frontend aplikacji
  • api.php - backend REST/JSON
  • lib/audit.php - prosty zapis audytu zmian CRUD
  • config.sample.php - wzór konfiguracji bazy
  • sql\schema.sql - pełny schemat bazy

Pliki pomocnicze i diagnostyczne

  • test-api.php - test połączenia z bazą i podstawowej odpowiedzi API
  • test-json.php - test czystości odpowiedzi JSON
  • test-insert.php - test zapisu do bazy
  • check-schema.php - diagnostyka schematu i kolumn
  • test-audit-log.php - test zapisu wpisów audytowych (actor/action/before/after)

Dokumenty naprawcze

  • HOSTINGER-DEBUG.md
  • FIX-JSON-ERROR.md
  • FIX-MISSING-COLUMNS.md
  • FIX-ACCESS-DENIED.md
  • DEBUG-HTML-RESPONSE.md
  • QUICK-MIGRATION.md
  • QUICK-FIX.md

Materiały referencyjne

  • 1-kalendarz.docx
  • 2-prace.exls.xlsx
  • DYZURY_2025.xlsx
  • snapshots\

7. Model danych

7.1 Tabela employees

Przechowuje słownik pracowników.

Kolumna Typ Opis
id INT klucz główny
name VARCHAR(255) imię i nazwisko, unikalne
phone VARCHAR(50) numer telefonu
color VARCHAR(20) kolor używany w UI
avatar TEXT URL avatara
active TINYINT(1) aktywność pracownika
created_at TIMESTAMP data utworzenia

Uwagi:

  • pracownik nieaktywny pozostaje w danych historycznych,
  • pracownik nieaktywny nie jest domyślnie pokazywany w listach wyboru nowych wpisów.

7.2 Tabela shifts

Przechowuje przypisane dyżury.

Kolumna Typ Opis
id INT klucz główny
shift_date DATE data dyżuru
slot ENUM night, day, evening
employee_id INT FK do employees.id
note TEXT notatka do wpisu
created_at TIMESTAMP data utworzenia
updated_at TIMESTAMP data modyfikacji

Dodatkowo:

  • unikalny klucz: (shift_date, slot)
  • usunięcie pracownika usuwa jego dyżury przez ON DELETE CASCADE

7.3 Tabela overtime_entries

Przechowuje wpisy nadgodzin.

Kolumna Typ Opis
id INT klucz główny
employee_id INT FK do employees.id
started_at DATETIME początek
ended_at DATETIME koniec
rounded_hours DECIMAL(5,2) wynik po zaokrągleniu
call_count INT liczba zgłoszeń
description TEXT opis czynności
created_at TIMESTAMP data utworzenia

7.4 Tabela substitutions

Przechowuje zastępstwa.

Kolumna Typ Opis
id INT klucz główny
sub_date DATE data zastępstwa
start_time TIME początek
end_time TIME koniec
from_employee_id INT osoba oddająca
to_employee_id INT osoba przejmująca
created_at TIMESTAMP data utworzenia

8. Interfejs użytkownika i przepływy

8.1 Widok główny

Główny ekran składa się z kilku paneli:

  • nawigacja po miesiącach,
  • kalendarz dyżurów,
  • formularz i lista nadgodzin,
  • formularz i lista zastępstw,
  • podsumowanie zbiorcze,
  • panel administracyjny pracowników,
  • przyciski eksportu.

Panele są zwijane i rozwijane po kliknięciu nagłówka.

8.2 Planowanie dyżurów w kalendarzu

Frontend:

  • wyświetla przypisanych pracowników w formie badge z nazwą,
  • oznacza dni wolne,
  • pokazuje dostępne sloty,
  • pozwala przypisać zmianę jednym kliknięciem,
  • pozwala przypisać cały dzień wybranemu pracownikowi,
  • pokazuje przy zmianie informację o zastępstwie.

Uwaga implementacyjna: słownik pracowników przechowuje color i avatar, ale aktualne odpowiedzi API dla shifts i overtime nie zwracają tych pól. W efekcie w części widoków interfejs operuje dziś głównie na nazwie pracownika, a nie na pełnych metadanych wizualnych.

8.3 Nadgodziny

Lista nadgodzin:

  • grupuje wpisy per pracownik,
  • sortuje wpisy chronologicznie,
  • umożliwia edycję i usuwanie,
  • pozwala filtrować listę po pracowniku.

Widoki nadgodzin:

  • miesiąc,
  • kwartał.

8.4 Zastępstwa

Lista zastępstw:

  • sortuje wpisy po dacie i godzinie,
  • pozwala edytować wpis,
  • pozwala usuwać wpis,
  • waliduje, że osoba oddająca i przyjmująca nie mogą być tą samą osobą,
  • waliduje dodatni przedział czasu.

8.5 Administracja pracownikami

Frontend wspiera:

  • dodanie nowego pracownika,
  • edycję danych pracownika,
  • archiwizację,
  • przywrócenie pracownika.

Archiwizacja nie usuwa historycznych danych z raportów.

8.6 Podsumowania

Podsumowanie wspiera trzy zakresy:

  • miesiąc,
  • kwartał,
  • rok.

Dla zakresów kwartalnych i rocznych frontend dociąga dodatkowe miesiące przez API, a następnie przelicza zbiorcze dane po stronie klienta.

8.7 Eksporty

Dostępne są dwa eksporty:

  • dyzury-YYYY-MM.xls
  • nadgodziny-YYYY-MM.xls

Technicznie są to pliki HTML zapisane z nagłówkiem/BOM UTF-8 i rozszerzeniem .xls, tak aby otwierały się poprawnie w Excelu.

Eksport dyżurów zawiera

  • datę,
  • dzień tygodnia,
  • zmianę,
  • liczbę godzin w formacie hh:mm,
  • pracownika,
  • notatkę,
  • informację o zastępstwach dopisaną do notatki.

Eksport nadgodzin zawiera

  • pracownika,
  • datę,
  • zakres godzin,
  • czas realizacji,
  • opis czynności.

9. API

API działa pod adresem:

  • produkcja: https://www.itgohome.com/dyzury-git1/api.php
  • lokalnie: api.php

Nagłówki i zachowanie ogólne

Backend ustawia:

  • Content-Type: application/json
  • Access-Control-Allow-Origin: *
  • Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS
  • Access-Control-Allow-Headers: Content-Type

Ważna cecha implementacyjna:

  • skrypt czyści output buffer i wyłącza wyświetlanie błędów PHP, żeby nie psuć JSON-a.

Format błędów walidacyjnych

W obszarze zapisów shifts i substitutions backend zwraca spójny format:

{
  "error": "Czytelny komunikat błędu",
  "error_type": "validation_error",
  "field": "nazwa_pola"
}

Uwagi:

  • error pozostaje kompatybilne wstecz (frontend już je odczytuje),
  • error_type pozwala frontendowi łatwo rozpoznać błąd walidacyjny,
  • field wskazuje pole (lub listę pól rozdzieloną przecinkami), którego dotyczy walidacja.

9.1 resource=employees

GET

Zwraca listę pracowników:

[
  {
    "id": 1,
    "name": "Jan Kowalski",
    "phone": "+48 600 000 000",
    "color": "#4c6fff",
    "avatar": null,
    "active": 1
  }
]

POST

Dodanie nowego pracownika albo aktualizacja istniejącego.

Przykładowe body:

{
  "name": "Jan Kowalski",
  "phone": "+48 600 000 000",
  "color": "#4c6fff",
  "avatar": null,
  "active": 1
}

Jeżeli przekazany jest id, wykonywana jest aktualizacja.

9.2 resource=shifts

GET

Pobiera zmiany dla miesiąca:

  • parametr: month=YYYY-MM

Zwracane pola:

  • id
  • shift_date
  • slot
  • employee_id
  • employee_name
  • note

POST

Dodaje dyżur.

Body:

{
  "shift_date": "2026-02-08",
  "slot": "night",
  "employee_id": 1,
  "note": null
}

Odpowiedzi:

  • 200 { "status": "saved" }
  • 400 { "error": "...", "error_type": "validation_error", "field": "..." } np. błędny shift_date, employee_id, slot, note
  • 404 { "error": "...", "error_type": "validation_error", "field": "employee_id" } gdy wskazany pracownik nie istnieje
  • 409 { "error": "Slot already assigned", "error_type": "validation_error", "field": "shift_date,slot" }

DELETE

Usuwa zmianę po id.

9.3 resource=overtime

GET

Pobiera wpisy nadgodzin dla miesiąca:

  • parametr: month=YYYY-MM

Zwracane pola:

  • id
  • employee_id
  • employee_name
  • started_at
  • ended_at
  • rounded_hours
  • call_count
  • description

POST

Dodaje albo aktualizuje wpis nadgodzin.

Body:

{
  "employee_id": 1,
  "started_at": "2026-02-03 18:30",
  "ended_at": "2026-02-03 19:15",
  "call_count": 2,
  "description": "Awaria serwera"
}

Jeżeli przekazany jest id, wykonywana jest aktualizacja.

Backend sam:

  • normalizuje daty,
  • liczy czas,
  • oblicza rounded_hours.

DELETE

Usuwa wpis po id.

9.4 resource=substitutions

GET

Pobiera zastępstwa dla miesiąca:

  • parametr: month=YYYY-MM

POST

Dodaje albo aktualizuje zastępstwo.

Body:

{
  "sub_date": "2026-02-08",
  "start_time": "08:00",
  "end_time": "12:00",
  "from_employee_id": 1,
  "to_employee_id": 2
}

Jeżeli przekazany jest id, wykonywana jest aktualizacja.

Walidacje backendowe i frontendowe:

  • obie osoby muszą być wybrane,
  • osoby nie mogą być identyczne,
  • zakres godzin musi być dodatni,
  • sub_date musi mieć format YYYY-MM-DD,
  • start_time i end_time muszą mieć format HH:MM albo HH:MM:SS,
  • wskazani pracownicy muszą istnieć,
  • przy aktualizacji przekazane id musi wskazywać istniejące zastępstwo,
  • zastępstwo musi nachodzić na dyżur osoby przekazującej,
  • zastępstwo nie może nachodzić na dyżur osoby przejmującej,
  • zastępstwo nie może nachodzić na inne zastępstwo tej samej osoby.
  • wskazani pracownicy muszą być aktywni (employees.active = 1),
  • osoba oddająca musi mieć przypisany slot pokrywający cały zakres zastępstwa.

Błędy walidacyjne dla POST i DELETE mają spójny format:

  • 400/404 { "error": "...", "error_type": "validation_error", "field": "..." }

DELETE

Usuwa wpis po id.

9.5 resource=summary

GET

Pobiera podsumowanie miesięczne.

  • parametr: month=YYYY-MM

Zwracane pola:

  • employee_id
  • employee_name
  • shift_hours
  • overtime_hours
  • net_oncall
  • calls

W widokach kwartalnych i rocznych frontend nie ma osobnego endpointu zbiorczego. Zamiast tego dociąga miesiące i liczy agregację lokalnie.

9.6 resource=reports

GET

Dedykowany interfejs raportowy (niezależny od UI operacyjnego).

Obsługiwane filtry:

  • month=YYYY-MM (domyślnie bieżący miesiąc, jeśli brak zakresu)
  • start_date=YYYY-MM-DD
  • end_date=YYYY-MM-DD
  • employee_id=<int>

Jeśli podane są start_date i end_date, mają priorytet nad month.

Zwracane dane:

  • filters:
    • start_date
    • end_date
    • employee_id
  • by_employee (agregacje per osoba):
    • employee_id
    • employee_name
    • shift_count
    • shift_hours
    • overtime_hours
    • net_oncall
    • calls
    • substitutions_out_hours
    • substitutions_in_hours
    • substitutions_balance_hours
  • totals (agregacje zbiorcze):
    • employees
    • shift_count
    • shift_hours
    • overtime_hours
    • net_oncall
  • calls
  • substitutions_out_hours
  • substitutions_in_hours
  • substitutions_balance_hours

9.7 resource=history

GET

Pobiera historię zmian dla dyżurów i zastępstw (maksymalnie 200 ostatnich wpisów).

Parametry (opcjonalne):

  • entity_type=shift|substitution
  • entity_id=<id obiektu>
  • day=YYYY-MM-DD (filtrowanie po dacie obiektu: shift_date / sub_date)

Przykłady:

  • historia dla konkretnego obiektu: api.php?resource=history&entity_type=shift&entity_id=123
  • historia dla dnia: api.php?resource=history&day=2026-02-08

Zwracane pola:

  • id
  • entity_type
  • entity_id
  • action (create, update, delete)
  • entity_date
  • actor
  • before_state
  • after_state
  • created_at

10. Konfiguracja i wdrożenie

10.1 Wymagania

  • hosting z PHP
  • dostęp do MySQL
  • możliwość wgrania plików przez FTP lub panel hostingowy

Nie są wymagane:

  • Composer
  • Node.js
  • proces budowania

10.2 Konfiguracja bazy

Skopiuj:

  • config.sample.php -> config.php

Uzupełnij:

return [
  'dsn' => 'mysql:host=localhost;dbname=TWOJA_NAZWA_BAZY;charset=utf8mb4',
  'user' => 'TWOJ_USER',
  'password' => 'TWOJE_HASLO',
];

Ważne dla Hostinger:

  • używaj host=localhost
  • nie dopisuj portu :3306, jeśli hosting tego nie wymaga

10.3 Tworzenie bazy

Uruchom w bazie:

  • sql\schema.sql

Skrypt:

  • tworzy wszystkie główne tabele (w tym audit_log),
  • zakłada klucze obce,
  • dodaje dane przykładowe przez INSERT IGNORE.

Jeżeli baza już istnieje, a brakuje części kolumn, skorzystaj z:

  • sql\migrate-simple.sql
  • sql\migrate-add-columns.sql
  • FIX-MISSING-COLUMNS.md

10.4 Wgranie plików

Do wdrożenia wystarczą:

  • index.html
  • api.php
  • config.php

Opcjonalnie warto zostawić lokalnie lub tymczasowo wgrać pliki diagnostyczne do debugowania.

10.5 Weryfikacja po wdrożeniu

Minimalna checklista:

  1. Otwórz index.html.
  2. Sprawdź, czy ładuje się lista pracowników.
  3. Dodaj testowy dyżur.
  4. Dodaj testową nadgodzinę.
  5. Sprawdź eksport XLS.
  6. Sprawdź, czy podsumowanie aktualizuje się po zapisach.
  7. Przejdź do zakładki Raporty i sprawdź, czy ekran jest odseparowany od panelu dnia.
  8. Sprawdź filtrowanie raportu po zakresie dat (Od daty / Do daty) oraz po pracowniku.
  9. Sprawdź, czy metryki i tabela raportu aktualizują się po zastosowaniu filtrów.
  10. Sprawdź wydruk harmonogramu:
  • otwórz podgląd wydruku (Ctrl+P / Cmd+P),
  • potwierdź, że widoczne są: miesiąc, dni tygodnia, daty, osoby, zmiany i status dnia,
  • potwierdź, że ukryte są kontrolki operacyjne (nawigacja, eksporty, przyciski akcji, sekcje zwijane),
  • sprawdź czytelność układu zarówno dla bieżącego miesiąca, jak i po przejściu na inny miesiąc.

Scenariusz ręcznej weryfikacji historii zmian

  1. Dodaj nowy dyżur i zapamiętaj jego id (z odpowiedzi API lub po liście zmian).
  2. Edytuj lub usuń zastępstwo.
  3. Otwórz panel Historia zmian w UI.
  4. Sprawdź filtr po dniu (Dzień) i potwierdź, że wpisy dla wskazanej daty są widoczne.
  5. Ustaw filtr typu (Dyżury / Zastępstwa) oraz ID obiektu i kliknij Odśwież.
  6. Zweryfikuj, że lista pokazuje akcję (Utworzenie/Edycja/Usunięcie) oraz stan Przed/Po w czytelnej formie.

11. Tryb demo i fallbacki

Tryb demo nie jest stałym, ręcznie przełączanym trybem pracy. W kodzie działa jako uzbrojony fallback.

Jak działa

  • adres z ?demo=1 pozwala na uruchomienie danych przykładowych,
  • dane przykładowe są używane dopiero wtedy, gdy API nie odpowiada lub zwraca błąd,
  • jeśli API działa poprawnie, aplikacja nadal pracuje online na rzeczywistych danych.

Przykład:

  • https://www.itgohome.com/dyzury-git1/?demo=1

Co dzieje się w fallbacku

  • frontend przechodzi w state.offline = true
  • wyświetla badge Tryb demonstracyjny (brak API)
  • ładuje zestaw przykładowych pracowników, dyżurów i nadgodzin
  • część operacji zapisuje się tylko lokalnie w pamięci sesji przeglądarki

11.1 Ochrona danych roboczych formularzy (test ręczny)

Najważniejsze formularze (Nadgodziny, Zastępstwa) zapisują robocze dane w localStorage.

Checklist:

  1. Otwórz aplikację i wpisz dane w formularzu Nadgodziny lub Zastępstwa.
  2. (Symulacja problemu sieci) w narzędziach deweloperskich przeglądarki ustaw tryb Offline i kliknij zapis.
  3. Sprawdź, że pojawia się komunikat: Brak synchronizacji: ... zapisany lokalnie.
  4. Odśwież stronę.
  5. Sprawdź, że wpisane dane formularza nadal są obecne.
  6. Przywróć sieć i zapisz formularz ponownie.
  7. Po poprawnym zapisie komunikat o braku synchronizacji znika.

12. Diagnostyka i utrzymanie

12.1 Najczęstsze klasy problemów

API zwraca HTML zamiast JSON

Zobacz:

  • DEBUG-HTML-RESPONSE.md
  • FIX-JSON-ERROR.md

Błąd połączenia z bazą

Zobacz:

  • HOSTINGER-DEBUG.md
  • FIX-ACCESS-DENIED.md

Brak kolumn w tabeli employees

Zobacz:

  • FIX-MISSING-COLUMNS.md
  • QUICK-MIGRATION.md

Potrzeba szybkiej checklisty

Zobacz:

  • QUICK-FIX.md

12.2 Pliki testowe

W aktualnym repozytorium dostępne są lekkie skrypty testowe (bez pełnego frameworka test runnera):

  • tests/run.php - automatyczne testy CRUD API (shifts, substitutions)

  • test-summary.php (test logiki podsumowania: godziny, nadgodziny, zastępstwa, przypadki graniczne)

  • lintowanie PHP (php -l api.php, php -l config.sample.php),

  • weryfikacja ręczna przez wywołania API i UI.

13. Bezpieczeństwo i ograniczenia

Obecna wersja jest prosta wdrożeniowo, ale ma też świadome ograniczenia:

  • brak logowania i autoryzacji,
  • API jest dostępne bez warstwy uprawnień,
  • CORS jest ustawiony szeroko na *,
  • brak CSRF protection,
  • automatyczne testy obejmują podstawowy CRUD API dla shifts i substitutions,
  • audit zmian obejmuje CRUD dyżurów i zastępstw (actor/timestamp/action/before/after),
  • brak modelu kompetencji/uprawnień per slot lub typ zmiany (brak danych do pełnej walidacji kwalifikacji).

W praktyce oznacza to, że system najlepiej działa:

  • w środowisku z ograniczonym dostępem,
  • za warstwą organizacyjną lub sieciową,
  • jako narzędzie zespołowe o kontrolowanym użyciu.

14. Zgodność z aktualnym wdrożeniem

Na moment aktualizacji dokumentacji:

  • frontend działa publicznie pod https://www.itgohome.com/dyzury-git1/
  • API odpowiada pod https://www.itgohome.com/dyzury-git1/api.php
  • instancja produkcyjna zwraca dane pracowników przez endpoint employees

README opisuje zarówno lokalny kod projektu, jak i aktualny model wdrożenia.

15. Aktualny stan prac repozytorium

Na moment tej aktualizacji repozytorium ma już przygotowany materiał wejściowy do następnego etapu backendowego:

  • zakończono Issue #3 — pełną inwentaryzację punktów zapisu dyżurów i zastępstw,
  • dodano trwały plik AGENT-STATUS.txt, który utrzymuje stan między sesjami,
  • wskazano wspólne miejsce pod centralną walidację: wejście do api.php po sparsowaniu JSON i przed wykonaniem SQL dla shifts oraz substitutions.

Najważniejsze ustalenia z zakończonej analizy:

  • frontend zapisuje dyżury w sześciu miejscach (assignFullDay, assignSlot, assignShift, quickAssignAvailable, clearDay, removeShift),
  • frontend zapisuje zastępstwa w dwóch miejscach (submitSubstitution, deleteSubstitution),
  • backend ma już częściową walidację konfliktu slotów i brakujących pól, ale nadal brakuje centralnej walidacji reguł biznesowych,
  • największe luki dotyczą walidacji formatu dat i godzin, listy dozwolonych slotów, dodatnich identyfikatorów, istnienia pracowników oraz spójnego przygotowania błędów.

Do bieżącego śledzenia stanu prac i kolejnych kroków służy AGENT-STATUS.txt.

15.1 Inwentaryzacja testów i luki pokrycia (Issue #8)

Aktualny stan pokrycia testowego:

  • brak testów automatycznych backendu,
  • brak testów integracyjnych API (shifts, substitutions, summary),
  • brak testów logiki obliczeń podsumowań i wpływu zastępstw,
  • brak testów regresyjnych walidacji kolizji.

Najwyższe priorytety testowe:

  1. API dyżurów (resource=shifts)
    CRUD + walidacje wejścia + konflikt unikalnego slotu (409).
  2. API zastępstw (resource=substitutions)
    CRUD + walidacja zakresów czasu + walidacja pracowników + przypadki aktualizacji.
  3. API podsumowań (resource=summary)
    Poprawność agregacji shift_hours, overtime_hours, net_oncall, calls oraz wpływu zastępstw.
  4. Testy walidacji kolizji i reguł domenowych
    scenariusze graniczne (te same sloty, nakładające się zakresy, błędne daty/godziny, brakujące pola).

16. Załączniki i materiały referencyjne

Do repozytorium dołączono pliki z dotychczasowego procesu pracy:

  • 1-kalendarz.docx
  • 2-prace.exls.xlsx
  • DYZURY_2025.xlsx

Mogą służyć jako:

  • materiał porównawczy,
  • wzorzec eksportów,
  • punkt odniesienia przy dalszym rozwoju aplikacji.

17. Snapshot interfejsu

Podgląd aplikacji

18. Rozwój w przyszłości

Najbardziej naturalne kierunki rozwoju:

  • dokończenie Issue #4 przez wydzielenie wspólnej warstwy walidacji dla zapisów dyżurów i zastępstw,
  • logowanie użytkowników i role,
  • historia zmian,
  • eksport PDF lub wydruku,
  • walidacja kolizji i ograniczeń po stronie backendu,
  • osobny moduł raportów,
  • lepszy tryb offline,
  • testy automatyczne dla API i logiki podsumowań.

19. Mapa architektury (EPIC-0)

Poniżej mapa modułów i punktów odpowiedzialności dla dalszych etapów prac.

19.1 Główne moduły frontendowe

Frontend jest utrzymywany w index.html:

  • konfiguracja i stan aplikacji: API_BASE, shiftSlots, state,
  • komunikacja HTTP i obsługa błędów API: fetchJson,
  • ładowanie danych: loadEmployees, loadShifts, loadOvertime, loadSubstitutions, loadSummary, loadSummaryForView,
  • logika dyżurów (kalendarz): assignFullDay, assignSlot, assignShift, quickAssignAvailable, clearDay, removeShift,
  • logika zastępstw: submitSubstitution, deleteSubstitution, applySubstitutionsToSummary,
  • logika podsumowań: loadSummary, computeLocalSummary, computeSummaryFromData,
  • eksport/raportowanie w obecnej wersji: exportShiftsXls, exportOvertimeXls,
  • offline/fallback demo: useSampleData, state.offline, setErrorBadge.

19.2 Główne moduły backendowe

Backend działa jako monolit w api.php:

  • warstwa transportu i kontraktu błędów JSON: respond, errorResponse,
  • walidacja wejścia i reguł domenowych: validateShiftWriteInput, validateSubstitutionWriteInput, validateEmployeeId, validateShiftDeleteInput, validateSubstitutionDeleteInput,
  • operacje CRUD API:
    • resource=employees,
    • resource=shifts,
    • resource=overtime,
    • resource=substitutions,
    • resource=summary,
  • agregacja podsumowań i wpływ zastępstw: sekcja resource=summary + timeDiffHours.

19.3 Miejsca odpowiedzialne za kluczowe obszary

  • dyżury: frontend (assign*, clearDay, removeShift) + backend (resource=shifts),
  • zastępstwa: frontend (submitSubstitution, deleteSubstitution) + backend (resource=substitutions),
  • podsumowania: backend (resource=summary) oraz frontend (loadSummaryForView, computeSummaryFromData dla kwartału/roku),
  • zapis danych: wszystkie POST/DELETE w api.php i wywołania fetchJson(...resource=...) w index.html,
  • walidacje: backendowe funkcje validate* w api.php (kluczowe miejsce centralizacji reguł),
  • raportowanie/eksport: frontendowe exportShiftsXls, exportOvertimeXls (XLS jako HTML),
  • offline: state.offline, useSampleData, lokalne fallbacki addLocalShift i obsługa błędów w fetchJson.

19.4 Gdzie najlepiej wdrażać kolejne wymagania

  • backend validation: rozszerzać centralne funkcje validate* w api.php i wywoływać je przed SQL,
  • historia zmian (audit log): backend api.php przy operacjach POST/DELETE (shifts, overtime, substitutions, employees) + nowa tabela SQL i endpoint odczytu historii,
  • raporty: osobny endpoint backendowy (np. nowe resource=reports) i osobny panel w index.html zamiast rozbudowywania istniejących eksportów,
  • eksport PDF/print: frontend (index.html) przez dedykowany widok do druku + window.print() jako pierwszy krok; PDF generować po stronie przeglądarki lub serwera w kolejnym etapie,
  • ulepszenia offline: najpierw trwały cache i kolejka operacji po stronie frontend (np. localStorage/IndexedDB), następnie synchronizacja po odzyskaniu połączenia.

19.5 Zależności i uruchamianie lint/build/test

  • frontend: brak npm/bundlera/frameworka,
  • backend: PHP + PDO + MySQL/MariaDB,
  • baza: sql/schema.sql,
  • zewnętrzne API świąt: Nager.Date.

Aktualny sposób uruchamiania:

  • lint backendu: find . -maxdepth 2 -type f -name '*.php' -print0 | xargs -0 -n1 php -l,
  • build: brak procesu build (projekt uruchamiany bez bundlowania),
  • testy automatyczne: brak stałego mechanizmu testów w repo; bieżąca walidacja opiera się na diagnostyce API i ręcznej weryfikacji przepływów UI.

19.6 Rekomendowana kolejność prac

  1. domknąć i rozszerzać walidację backendową (jeden punkt wejścia reguł),
  2. dodać testy automatyczne API i logiki podsumowań,
  3. dodać historię zmian (audit log) dla wszystkich operacji zapisu,
  4. wydzielić moduł raportowania i zakresy raportów,
  5. wdrożyć print/PDF na stabilnym modelu danych raportowych,
  6. rozbudować offline (cache + synchronizacja konfliktów).

19.7 Ryzyka techniczne

  • monolityczny index.html i api.php zwiększają ryzyko regresji przy równoległych zmianach,
  • część agregacji podsumowań jest liczona po stronie klienta (kwartał/rok), co utrudnia spójność przy zmianach reguł,
  • brak pełnych testów automatycznych utrudnia bezpieczne tempo wdrożeń,
  • fallback demo/offline może maskować błędy API, jeśli nie będzie jasno raportowany,
  • eksport XLS oparty na HTML nie pokrywa wymagań jakościowych dla PDF/print bez dodatkowego etapu projektowego.

20. [AUDIT] Projekt techniczny modelu historii zmian (dyżury i zastępstwa)

Poniżej opis docelowego, prostego modelu audytu zmian przygotowany pod wdrożenie etapami (bez implementacji w tej zmianie).

19.1 Cel i zakres

Celem jest rejestrowanie wiarygodnej historii zmian dla kluczowych operacji:

  • dyżury (shifts): utworzenie, usunięcie,
  • zastępstwa (substitutions): utworzenie, aktualizacja, usunięcie.

Każde zdarzenie audytowe musi zawierać:

  • actor — kto wykonał zmianę,
  • event_at (timestamp) — kiedy zmiana została zapisana przez backend,
  • operation_type — typ operacji,
  • state_before — stan rekordu przed zmianą,
  • state_after — stan rekordu po zmianie.

Definicja czasu zdarzenia: event_at oznacza czas wygenerowany przy INSERT rekordu audytu wewnątrz transakcji DB, a nie moment odebrania żądania HTTP. Przy rollbacku transakcji rekord audytu również nie zostaje utrwalony.

19.2 Proponowany model danych

Nowa tabela: audit_events.

Kolumna Typ (propozycja) Opis
id BIGINT AUTO_INCREMENT klucz główny zdarzenia
entity_type VARCHAR(32) np. shift, substitution
entity_id INT identyfikator rekordu biznesowego
operation_type VARCHAR(32) np. create, update, delete
actor VARCHAR(255) identyfikator wykonawcy operacji
event_at TIMESTAMP(3) (MySQL/MariaDB) czas zdarzenia po stronie backendu (UTC)
state_before JSON/LONGTEXT snapshot przed zmianą
state_after JSON/LONGTEXT snapshot po zmianie
context JSON/LONGTEXT NULL opcjonalnie: request_id, ip, user_agent

Indeksy minimalne:

  • INDEX idx_audit_entity (entity_type, entity_id, event_at),
  • INDEX idx_audit_event_at (event_at),
  • INDEX idx_audit_actor (actor, event_at).

19.3 Zakres danych snapshotów (state_before / state_after)

Snapshot powinien przechowywać tylko pola istotne audytowo (bez danych pochodnych z joinów):

  • dla shift: id, shift_date, slot, employee_id, note,
  • dla substitution: id, sub_date, start_time, end_time, from_employee_id, to_employee_id.

Uwaga: w aktualnym modelu substitutions nie mają pola note, więc snapshot obejmuje komplet realnie zapisywanych kolumn biznesowych tej encji.

Zasady:

  • create: state_before = null, state_after = nowy rekord,
  • update: oba snapshoty obecne,
  • delete: state_before = usuwany rekord, state_after = null.

19.4 Źródło actor w obecnej architekturze

Aktualnie aplikacja nie ma logowania użytkowników, więc actor musi być dostarczany etapowo:

  1. etap minimalny: wartość techniczna (anonymous lub system) + opcjonalnie IP/User-Agent w context,
  2. etap docelowy: jawny identyfikator użytkownika (np. nagłówek X-Actor z warstwy proxy/SSO),
  3. po wdrożeniu auth: actor mapowany do rzeczywistego konta.

To pozwala uruchomić audyt od razu, a później zwiększać wiarygodność identyfikacji.

Wymóg bezpieczeństwa: jeśli używany jest nagłówek X-Actor, backend musi ufać wyłącznie nagłówkowi nadpisanemu przez zaufaną warstwę pośrednią (proxy/SSO) i nie może akceptować tej wartości bezpośrednio od klienta publicznego. Praktycznie oznacza to co najmniej jedną technikę odróżnienia ruchu zaufanego: preferowane mTLS między proxy a backendem albo podpisany nagłówek przekazywany wyłącznie w sieci wewnętrznej; lista dozwolonych adresów IP proxy (allowlist) może pełnić wyłącznie kontrolę uzupełniającą.

19.5 Gdzie zapisywać zdarzenia (wpływ na architekturę)

Miejsce zapisu: backend api.php, dokładnie w gałęziach write dla resource=shifts i resource=substitutions.

Wymaganie spójności:

  • zapis biznesowy i wpis audytowy powinny być wykonane w jednej transakcji DB,
  • dla update/delete trzeba odczytać stan „przed” tuż przed modyfikacją.

Minimalny wpływ na obecny kod:

  • dodanie jednej funkcji pomocniczej writeAuditEvent(...),
  • punktowe wywołania po udanym SQL (lub w transakcji),
  • brak zmian kontraktu istniejących endpointów dla frontendu.

19.6 Plan wdrożenia etapami

Etap A (MVP, niski risk):

  • dodać tabelę audit_events,
  • logować tylko substitutions (create/update/delete),
  • actor techniczny, snapshoty pełne dla zastępstw.

Etap B:

  • rozszerzyć logowanie na shifts (create/delete),
  • ujednolicić słownik operation_type i entity_type,
  • dodać request_id w context dla łatwiejszego śledzenia.

Etap C:

  • dodać endpoint tylko do odczytu historii (np. filtrowanie po typie encji, zakresie dat, actorze),
  • dodać podstawowy widok historii w UI (bez edycji).

Etap D (po auth):

  • podmienić actor techniczny na tożsamość użytkownika,
  • dodać politykę retencji/archiwizacji dla dużych wolumenów.

19.7 Mapowanie na kryteria akceptacji

  • „model obejmuje kluczowe operacje”: tak — shifts i substitutions CRUD w zakresie używanym przez aplikację,
  • „wiadomo gdzie zapisywać zdarzenia”: tak — write-pathy w api.php + jedna tabela audit_events w tej samej bazie,
  • „rozwiązanie możliwe do wdrożenia etapami”: tak — etapy A→D z rosnącą dojrzałością i bez dużego refaktoru.

21. Strategia eksportu harmonogramu (Print/PDF)

19.1 Porównanie wariantów

Wariant Koszt wdrożenia Ryzyko Spójność z obecną architekturą Utrzymanie
Print CSS (browser print) niski niski/średni (różnice między przeglądarkami) bardzo wysoka (frontend już renderuje widok i nie wymaga procesu buildu) łatwe
PDF po stronie frontend średni średni/wysoki (jakość paginacji, biblioteki JS, wydajność na dużych widokach) średnia (nowe zależności, większa złożoność w index.html) średnie/trudniejsze
PDF po stronie backend wysoki średni (silnik PDF, infrastruktura serwerowa, większy zakres zmian API) średnia/niższa (obecny backend to proste API JSON bez warstwy raportowej) średnie (stabilny wynik, ale większy koszt operacyjny)

19.2 Rekomendacja

MVP: Print CSS + akcja „Drukuj” dla widoku harmonogramu miesięcznego.

To jest najbezpieczniejszy i najmniej inwazyjny wariant względem obecnej architektury (index.html + api.php, bez procesu buildu). Pozwala szybko dostarczyć funkcję biznesową bez zmiany logiki backendu i bez dokładania ciężkiej biblioteki PDF.

Wariant docelowy: PDF po stronie backend (dedykowany endpoint raportowy).

W dłuższym horyzoncie da to najbardziej powtarzalny, kontrolowany rezultat (ten sam plik niezależnie od przeglądarki), łatwiejszy do archiwizacji i wysyłki. Wymaga jednak osobnego etapu architektonicznego i wdrożeniowego.

19.3 Znane ograniczenia i wspierane widoki

Dla MVP (Print CSS) wspierane powinny być:

  • widok harmonogramu miesięcznego (kalendarz) jako zakres obowiązkowy,
  • opcjonalnie podsumowanie miesięczne jako osobny widok do druku dopiero po stabilizacji kalendarza.

Poza zakresem MVP:

  • generowanie „piksel-perfect” PDF,
  • pełna zgodność każdej przeglądarki i każdej drukarki,
  • eksport wszystkich sekcji aplikacji (nadgodziny, administracja, historia) w pierwszym etapie.

Główne ograniczenia Print CSS:

  • różnice paginacji i marginesów między przeglądarkami,
  • zależność od ustawień użytkownika (skala, nagłówki/stopki, orientacja),
  • ograniczona kontrola nad podziałem tabel/kalendarza na strony.

22. Projekt MVP — osobny moduł raportów

Poniżej minimalny zakres funkcjonalny modułu raportów (MVP) jako osobnego obszaru aplikacji.

19.1 Zakres UI (MVP)

  • osobna zakładka/sekcja Raporty (oddzielona od widoku operacyjnego kalendarza),
  • jeden panel filtrów daty z gotowymi zakresami:
    • miesiąc,
    • kwartał,
    • rok,
    • zakres własny (data od, data do),
  • jedna tabela zbiorcza „Obciążenie per osoba” oraz podstawowe kafelki z metrykami.

19.2 Minimalne agregacje (MVP)

W ramach wybranego zakresu dat raport pokazuje:

  1. Liczba dyżurów per osoba (oraz suma globalna),
  2. Liczba godzin dyżuru per osoba (z uwzględnieniem zastępstw),
  3. Liczba zastępstw:
    • oddanych (from_employee_id),
    • przejętych (to_employee_id),
    • łącznie,
  4. Obciążenie per osoba:
    • udział procentowy godzin danej osoby w łącznej puli godzin dyżurowych zakresu,
    • wraz z godzinami absolutnymi.

19.3 Źródła danych i zależności od obecnych struktur

MVP wykorzystuje już istniejące tabele i reguły:

  • shifts — baza liczby dyżurów i godzin dyżurowych (sloty night/day/evening),
  • substitutions — korekta czasu: odjęcie od osoby oddającej i dodanie osobie przejmującej,
  • employees — nazwy i identyfikatory do grupowania,
  • (opcjonalnie w rozszerzeniu) overtime_entries — do wskaźników netto, poza ścisłym MVP.

Zależności logiczne:

  • mapowanie slotów na czas (jak w obecnym podsumowaniu: slotDuration),
  • obliczenie czasu zastępstwa przez różnicę start_time / end_time (jak w obecnym timeDiffHours),
  • grupowanie po employee_id i prezentacja employee_name.

19.4 Co liczyć w backendzie, a co w frontendzie

Backend (MVP, rekomendowane):

  • filtrowanie po zakresie dat,
  • agregacje grupujące po pracowniku (liczniki i sumy godzin),
  • korekta godzin o zastępstwa,
  • zwrot gotowych metryk raportowych w jednym endpoincie raportowym.

Frontend (MVP, rekomendowane):

  • wybór i walidacja zakresu filtrów daty,
  • prezentacja tabeli/kafelków raportu,
  • sortowanie i formatowanie (hh:mm, %),
  • lekkie obliczenia prezentacyjne (np. procent udziału z wartości już zwróconych przez backend).

Taki podział ogranicza duplikowanie logiki biznesowej w UI, ułatwia testowanie agregacji i przygotowuje bazę pod kolejne etapy ([REPORTS] backend i [REPORTS] frontend).

23. [OFFLINE] Minimalny plan synchronizacji odłożonych zmian (Issue #27)

Cel tego etapu to zaplanowanie prostego, bezpiecznego MVP synchronizacji po odzyskaniu połączenia, bez wdrażania pełnej, rozbudowanej replikacji.

19.1 Gdzie przechowywać odłożone zmiany

Minimalny wariant:

  • przechowywać kolejkę zmian po stronie przeglądarki w localStorage,
  • jeden klucz techniczny, np. dyzury2.pendingMutations.v1,
  • każda pozycja kolejki powinna mieć:
    • mutation_id (local UUID),
    • resource (shifts / substitutions / kolejne zasoby),
    • method (POST / DELETE),
    • payload,
    • created_at (timestamp),
    • sync_state (queued / syncing / failed / conflict / done),
    • opcjonalnie base_fingerprint (np. znacznik wersji rekordu: updated_at albo hash kluczowych pól, używany do wykrycia konfliktu).

Uzasadnienie: localStorage jest już dostępne bez dodatkowej infrastruktury, przetrwa odświeżenie strony i jest wystarczające dla podstawowego scenariusza single-user.

19.2 Jak oznaczać stan synchronizacji

Minimalny model statusów:

  • globalny stan aplikacji: online-clean, online-pending, offline-pending,
  • status per zmiana w kolejce: queued, syncing, done, failed, conflict.

Prezentacja w UI (bez chaosu):

  • utrzymać istniejący badge połączenia jako główne źródło informacji,
  • dodać krótki licznik odłożonych zmian (np. Offline: 3 zmiany oczekujące na synchronizację),
  • nie dodawać dużego nowego panelu; ewentualną listę szczegółów pokazywać dopiero po kliknięciu „Szczegóły”.

19.3 Minimalny przepływ synchronizacji

  1. Zapis online nieudany z powodu sieci/API -> zmiana trafia do kolejki queued.
  2. UI pokazuje, że istnieją zmiany oczekujące.
  3. Po odzyskaniu połączenia aplikacja uruchamia pętlę synchronizacji FIFO.
  4. Każdy element:
    • queued -> syncing,
    • sukces API -> done (i usunięcie z kolejki),
    • błąd przejściowy -> failed (z ponawianiem: maks. 3 próby, odstępy 5s -> 15s -> 30s),
    • błąd konfliktu (np. 409) -> conflict (wymaga decyzji użytkownika).
  5. Po opróżnieniu kolejki wraca stan online-clean.

19.4 Ryzyka konfliktów i minimalne zabezpieczenia

Najważniejsze ryzyka:

  • równoległa edycja tego samego dnia/slotu przez innego użytkownika,
  • usunięcie lub zmiana rekordu na serwerze zanim odłożona operacja się zsynchronizuje,
  • duplikacja żądań po odświeżeniu i ponownej próbie.

Minimalne zabezpieczenia:

  • opierać wykrywanie konfliktu na aktualnych odpowiedziach API (409 + jawny komunikat),
  • dodać idempotencję po stronie klienta przez mutation_id i oznaczanie elementu jako done tylko po potwierdzonym sukcesie,
  • nie ukrywać konfliktu: oznaczać conflict i zostawiać użytkownikowi prostą decyzję (ponów / odrzuć / odśwież dane).

19.5 Proponowane rozbicie implementacji (jeśli za duże na jeden task)

  1. Task A (MVP kolejki): model danych kolejki + zapis/odczyt localStorage + licznik oczekujących zmian w badge.
  2. Task B (silnik sync): automatyczny flush po powrocie online + retry błędów przejściowych.
  3. Task C (konflikty): obsługa 409, status conflict, prosty UI decyzji użytkownika.
  4. Task D (utwardzenie): telemetry/diagnostyka i scenariusze regresyjne offline/online.

24. Audyt UI — inwentaryzacja komponentów i niespójności (Issue #11)

19.1 Lista komponentów (aktualny stan)

  • Karty / kontenery
    • section.panel (główne karty sekcji),
    • .day (karta dnia w kalendarzu),
    • .assign (karta przypisanej zmiany),
    • .substitution-row (karta zastępstwa),
    • .admin-card (karta pracownika w administracji).
  • Statusy i znaczniki
    • .badge (np. #modeBadge),
    • .pill (status pomocniczy, np. „Nieaktywny”),
    • .substitution-chip (chip zastępstwa wewnątrz karty zmiany),
    • .slot-pill (dostępne sloty do szybkiego przypisania).
  • Alerty / komunikaty
    • natywne alert() i confirm() w wielu akcjach CRUD,
    • tekstowe stany „muted” (.muted) dla pustych list i podpowiedzi.
  • Formularze
    • formularze: nadgodziny (#overtimeForm) i zastępstwa (#subForm),
    • wejścia administracyjne (dodawanie/edycja pracownika),
    • wiele layoutów formularzy budowanych inline przez style.
  • Sekcje widoków dziennych
    • nagłówek dnia .day-header,
    • lista przypisań (.assign),
    • sekcja „Dostępne” z .slot-pill,
    • akcja całodniowa .full-day-btn.

19.2 Lista duplikacji i niespójności

  • Niespójne „karty” dla podobnych danych
    • karta zmiany (.assign) używa obramowania dashed i kompaktowego układu,
    • karta zastępstwa (.substitution-row) ma pełne obramowanie i inny rytm spacingu,
    • obie reprezentują wpis dzienny, ale mają inny język wizualny.
  • Różnice między kartami zmian i zastępstw (najważniejsze)
    • zmiana: akcja usuwania ukryta i pokazywana na hover (.assign .delete-shift),
    • zastępstwo: akcje zawsze widoczne (Edytuj, Usuń),
    • zmiana: treść oparta o slot i badge pracownika; zastępstwo: data+godziny+strzałka osoba→osoba,
    • brak wspólnego komponentu bazowego „karta wpisu dnia”.
  • Nadmiar wariantów małych znaczników
    • .badge, .pill, .slot-pill, .substitution-chip, .substitution-hours realizują podobną rolę, ale mają różne promienie, paddingi, kontrast i semantykę.
  • Niespójne komunikaty błędów
    • część akcji używa alert('Nie udało się...'), część cichego console.error, część ma bardziej rozbudowane komunikaty; brak jednego komponentu alert/toast.
  • Rozproszona stylizacja formularzy
    • wiele etykiet i kontenerów formularzy ma duplikowane style inline (display:flex; flex-direction:column; gap:4px; font-weight:700;).
  • Mieszanie styli globalnych i inline
    • duża część odstępów i layoutów sekcji jest ustawiana inline, co utrudnia spójne zmiany i utrzymanie.

19.3 Priorytety i plan ujednolicenia (małe kroki)

  1. Priorytet P1: wspólny komponent bazowy karty wpisu dnia
    • zdefiniować wspólną klasę bazową (np. entry-card) dla .assign i .substitution-row,
    • wyrównać obramowanie, radius, spacing i zachowanie akcji.
  2. Priorytet P1: unifikacja statusów/chipów/badge
    • wprowadzić wspólną bazę (np. ui-chip) oraz warianty semantyczne (info, success, warning, danger),
    • stopniowo podpiąć .badge, .pill, .substitution-chip, .substitution-hours.
  3. Priorytet P2: jeden system komunikatów użytkownika
    • zastąpić rozproszone alert()/confirm() lekkim komponentem alert/toast + potwierdzenia modalnego.
  4. Priorytet P2: porządek w formularzach
    • wydzielić powtarzające się style etykiet/pól do klas (form-row, form-field, form-actions),
    • ograniczyć style inline do przypadków wyjątkowych.
  5. Priorytet P3: redukcja inline styles
    • przenieść najczęściej powtarzane ustawienia spacing/layout do klas utility, bez zmiany logiki JS.

Takie uporządkowanie daje najpierw największy efekt wizualny (karty i znaczniki), a dopiero potem porządkuje mechanikę komunikatów i formularzy.

25. Finalna checklista testów smoke i regresji

Poniższa checklista zamyka wdrożenie obejmujące: walidację backendową, API i podsumowania, redesign panelu dnia, historię zmian, raporty, eksport/print oraz offline.

19.1 Testy automatyczne (smoke)

Minimalny zestaw do uruchomienia po wdrożeniu:

  1. Lint backendu (PHP):
    • php -l api.php
    • php -l config.sample.php
  2. Smoke API - odczyt listy pracowników:
    • curl -s "https://<HOST>/api.php?resource=employees"
    • oczekiwane: poprawny JSON (tablica obiektów lub pusta tablica), brak HTML/błędów PHP.
  3. Smoke API - odczyt dyżurów dla miesiąca:
    • curl -s "https://<HOST>/api.php?resource=shifts&month=YYYY-MM"
    • oczekiwane: poprawny JSON, brak błędu 500.
  4. Smoke API - podsumowanie miesięczne:
    • curl -s "https://<HOST>/api.php?resource=summary&month=YYYY-MM"
    • oczekiwane: poprawny JSON z polami agregacji (shift_hours, overtime_hours, net_oncall, calls).
  5. Smoke walidacji backendu (negatywny przypadek):
    • wysłać POST /api.php?resource=shifts z niepoprawnym slot lub shift_date
    • oczekiwane: kod 4xx i JSON z polem error.

19.2 Testy ręczne (checklista regresji)

  1. Panel dnia (redesign):
    • przełączanie miesięcy działa,
    • karta dnia pokazuje zmiany, dostępne sloty i status dnia,
    • przypisanie pojedynczego slotu i pełnego dnia działa,
    • usunięcie pojedynczej zmiany i wyczyszczenie dnia działa.
  2. Walidacja biznesowa backend/frontend:
    • brak możliwości zapisu duplikatu tego samego slotu dnia,
    • błędne dane (np. pusty pracownik, zły format daty) zwracają czytelny błąd i nie psują UI.
  3. API i podsumowania:
    • po dodaniu/edycji/usunięciu wpisów wartości podsumowań aktualizują się poprawnie,
    • bilans netto (dyżur - nadgodziny) jest spójny z danymi wejściowymi.
  4. Historia zmian:
    • widoczna jest lista zmian dla dyżurów/zastępstw,
    • po wykonaniu zapisu/usunięcia pojawia się nowy wpis historii,
    • dane wpisu historii są czytelne (kto/co/kiedy, jeśli dostępne).
  5. Raporty:
    • ekran raportów otwiera się i jest odseparowany od panelu dnia,
    • filtrowanie (jeśli dostępne) działa i odświeża wynik,
    • metryki raportowe są czytelne i zgodne z danymi bazowymi.
  6. Eksport / print:
    • eksport danych do pliku działa i plik da się otworzyć,
    • podgląd wydruku działa i nie zawiera zbędnych elementów UI,
    • wydruk obejmuje właściwy zakres (panel harmonogramu/raportu).
  7. Offline / fallback:
    • przy braku API widoczny jest status trybu offline/demo,
    • aplikacja pozostaje używalna dla odczytu danych demonstracyjnych,
    • po powrocie API aplikacja wraca do trybu online bez odświeżania krytycznych danych.

19.3 Scenariusze krytyczne (go/no-go przed produkcją)

  1. Krytyczna ścieżka planowania dyżuru: dodanie zmiany -> widoczność w kalendarzu -> poprawne podsumowanie.
  2. Krytyczna ścieżka zastępstwa: dodanie zastępstwa -> korekta godzin oddającego/przejmującego -> poprawne agregacje.
  3. Krytyczna ścieżka raportowa: wybranie zakresu -> poprawne metryki -> zgodność z podsumowaniami.
  4. Krytyczna ścieżka audytowa: wykonanie operacji zapisu -> wpis pojawia się w historii zmian.
  5. Krytyczna ścieżka eksportu/print: wygenerowanie eksportu i wydruku bez utraty kluczowych danych.
  6. Krytyczna ścieżka odporności: chwilowy brak API nie blokuje pracy odczytowej i sygnalizuje tryb offline.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors