Dzień 2: Projekt
W Dniu 1 przygotowaliśmy środowisko i uruchomiliśmy pustą aplikację Symfony 8. Zanim napiszemy pierwszą linię kodu funkcjonalnego, musimy dokładnie wiedzieć co budujemy. Dzisiejszy rozdział nie zawiera kodu — to specyfikacja projektu: aktorzy systemu, historie użytkownika (user stories) i makiety kluczowych ekranów. Do tego dokumentu będziemy wracać przez cały kurs.
Jobeet to otwartoźródłowa tablica ogłoszeń o pracę, która robi jedną rzecz, ale robi ją dobrze. Jest prosta w użyciu, łatwa do dostosowania, rozszerzenia i osadzenia na własnej stronie. Obsługuje wiele języków, udostępnia kanały RSS oraz API do integracji programistycznej.
Aktorzy systemu
W Jobeet występują cztery typy użytkowników:
| Aktor | Rola |
|---|---|
| Admin | jest właścicielem serwisu i nim zarządza |
| Użytkownik (kandydat) | odwiedza serwis w poszukiwaniu pracy |
| Wystawiający (poster) | odwiedza serwis, aby dodać ofertę pracy |
| Partner (affiliate) | publikuje oferty Jobeet na własnej stronie przez API |
Jedna aplikacja, nie dwie
W oryginalnym tutorialu (Symfony 1.x) budowano dwie osobne aplikacje: frontend dla użytkowników
oraz backend dla administratorów. W Symfony 8 tego nie robimy — tworzymy jedną aplikację z
wydzieloną, zabezpieczoną sekcją administracyjną (firewall + role, np. /admin).
Zmiana vs Symfony 4.2: rezygnujemy z podziału na aplikacje frontend/backend. Sekcję admina zabezpieczymy natywnym Security Bundle (firewall,
#[IsGranted('ROLE_ADMIN')], Voters) — bez zewnętrznych bundli w stylu FOSUserBundle. Panel admina zbudujemy później jako ręczny CRUD na formularzach Symfony (bez EasyAdmin/Sonata — zgodnie z konwencją tego projektu).
F1: Na stronie głównej użytkownik widzi najnowsze aktywne oferty
Na stronie głównej Jobeet użytkownik widzi listę 10 najnowszych aktywnych ofert pogrupowanych według kategorii. Dla każdej oferty wyświetlamy tylko lokalizację, stanowisko i firmę. Przy każdej kategorii jest link pozwalający wyświetlić wszystkie oferty z tej kategorii. Użytkownik może też wyszukać oferty lub dodać nową.

F2: Użytkownik przegląda wszystkie oferty z danej kategorii
Użytkownik widzi listę wszystkich ofert z kategorii, posortowaną według daty i podzieloną na strony po 20 ofert na stronę (paginacja).

F3: Użytkownik zawęża listę słowami kluczowymi
Użytkownik może wpisać słowa kluczowe, aby zawęzić wyszukiwanie. Słowa kluczowe mogą pochodzić z pól: lokalizacja, stanowisko, kategoria lub firma.
F4: Użytkownik klika ofertę, aby zobaczyć szczegóły
Użytkownik może wybrać ofertę z listy, aby zobaczyć szczegółowe informacje.

F5: Użytkownik dodaje ofertę
Użytkownik może dodać ofertę pracy. Oferta składa się z kilku informacji:
- Firma
- Typ (pełny etat, część etatu lub freelance)
- Logo (opcjonalne)
- URL (opcjonalne)
- Stanowisko
- Lokalizacja
- Kategoria (wybór z listy dostępnych kategorii)
- Opis stanowiska (adresy URL i e-mail są automatycznie zamieniane na linki)
- Jak aplikować (adresy URL i e-mail są automatycznie zamieniane na linki)
- Publiczna (czy oferta może być publikowana także na stronach partnerów)
- E-mail (adres wystawiającego)
Proces ma tylko dwa etapy: najpierw użytkownik wypełnia formularz, a następnie zatwierdza ofertę po obejrzeniu podglądu finalnej strony.
Nie trzeba zakładać konta, aby dodać ofertę. Ofertę można później edytować dzięki specjalnemu adresowi URL chronionemu tokenem, który użytkownik otrzymuje przy tworzeniu oferty.
Każda oferta jest wyświetlana przez 30 dni (wartość konfigurowalna przez admina). Użytkownik może wrócić, aby reaktywować lub przedłużyć ważność oferty o kolejne 30 dni — ale tylko gdy do wygaśnięcia zostało mniej niż 5 dni.

F6: Użytkownik zgłasza się jako partner
Aby korzystać z API Jobeet, użytkownik musi zgłosić się jako partner. Może wybrać podzbiór kategorii, z których chce otrzymywać oferty. Przy zgłoszeniu podaje:
- Nazwę
- Adres URL strony
Konto partnera musi zostać aktywowane przez admina. Po aktywacji partner otrzymuje e-mailem token do korzystania z API.
F7: Partner pobiera aktualną listę aktywnych ofert
Partner pobiera aktualną listę ofert, wywołując API ze swoim tokenem. Może ograniczyć liczbę zwracanych ofert i zawęzić zapytanie do wybranej kategorii.
Zmiana vs Symfony 4.2: oryginał zwracał dane w formatach XML / JSON / YAML, składanych ręcznie (JMSSerializer + FOSRestBundle). W Symfony 8 zbudujemy API zgodnie z konwencją tego projektu — kontroler REST zwracający JSON z DTO i automatyczną dokumentacją OpenAPI (NelmioApiDoc + swagger-php), z uwierzytelnianiem tokenem w nagłówku.
B1: Admin konfiguruje serwis
Admin może edytować kategorie dostępne w serwisie.
B2: Admin zarządza ofertami
Admin może edytować i usuwać dowolną dodaną ofertę.
B3: Admin zarządza partnerami
Admin może tworzyć i edytować partnerów. Odpowiada za aktywację partnera, może go też dezaktywować. Gdy admin aktywuje nowego partnera, system generuje unikalny token do użycia z API.
Podsumowanie
Mamy komplet specyfikacji Jobeet:
- ✅ czterej aktorzy: admin, użytkownik, wystawiający, partner,
- ✅ jedna aplikacja z zabezpieczoną sekcją admina (zamiast dwóch aplikacji),
- ✅ siedem historii frontendu (F1–F7) i trzy backendu (B1–B3),
- ✅ makiety kluczowych ekranów,
- ✅ reguły biznesowe: ważność 30 dni, reaktywacja < 5 dni, edycja przez token, API dla partnerów.
W Dniu 3 przekujemy tę specyfikację w model danych: zdefiniujemy encje Doctrine (Job, Category, Affiliate), relacje między nimi, uruchomimy pierwszą migrację i zasilimy bazę danymi testowymi.