← All challenges

SAMPLE CHALLENGE · 2025 · 2 / 4

Distribuția avizelor și volumelor

Original 2025 brief, including the API references and rules from that edition. The 2026challenges will be released at the opening ceremony.

Descriere

Obiectivul este dezvoltarea unei aplicații web de tip „insights dashboard” care arată cum evoluează în timp transporturile de lemn: câte avize se emit, ce volume se raportează și ce specii sunt cele mai frecvente. Utilizatorul poate alege un interval de timp, poate filtra după emitent/destinatar și după companii specifice, iar aplicația răspunde cu vizualizări ușor de înțeles.

Datele provin din ZebraHack3.0 Data API, în special din endpoint‑urile:

  • GET /insights/range – intervalul de timp acoperit de setul de date;
  • GET /insights – statistici agregate zilnice, orare și pe specii (daily, hourly, species);
  • GET /companies – pentru ajutor la căutarea companiilor (autocomplete / sugestii).

Dashboard‑ul ar trebui să îi ajute pe cetățeni, jurnaliști sau ONG‑uri să observe modele: zile cu trafic intens, ore „fierbinți”, specii dominante sau companii care apar frecvent în intervalul analizat.

Funcționalități:

  1. Pagină de introducere care explică pe scurt contextul (tăierile de păduri, de ce contează distribuția în timp a transporturilor).
  2. Selecție de interval de timp (data de început și de final) cu posibilitatea de a reveni la intervalul complet disponibil.
  3. Filtre de companii, inclusiv rol (emitent/destinatar) și posibilitatea de a adăuga una sau mai multe companii de interes.
  4. Vizualizare zilnică (volum și număr de avize pe zi).
  5. Vizualizare orară (orele cu cele mai multe avize/volume).
  6. Vizualizare pe specii (volum și avize per specie).
  7. Interfață modernă, adaptabilă și ușor de extins – echipele sunt încurajate să experimenteze cu propriile idei de UI, atâta timp cât păstrează claritatea informațiilor.

[!IMPORTANT]

  • Se va implementa exclusiv partea de front‑end: fișiere statice HTML, CSS și JavaScript + librării front‑end încărcate prin <script src="...">.
  • Nu se folosesc backend propriu, server‑side rendering, bundlers sau transpileri (fără Webpack, Vite, Babel, TypeScript etc.).
  • Pentru date se folosește ZebraHack3.0 Data API:
  • Autentificare: cheia de acces este numele echipei și se trimite ca header X-App-Key la fiecare request.

[!TIP] Librării recomandate (fără bundler, direct din CDN):

  • Pentru vizualizări: Chart.js, ApexCharts, ECharts sau alte librării care pot fi încărcate cu <script src="..."> fără toolchain suplimentar.
  • Pentru UI (opțional): librării ușoare de componente sau icon‑set‑uri (de ex. icon fonts), din nou fără bundler sau transpiler.
  • Nu este obligatoriu să folosiți o librărie de grafice – puteți construi și vizualizări custom (bare, badge‑uri, liste) folosind doar HTML/CSS/JS.

Task 1: Pagina de introducere și context

Creați o pagină de tip landing care explică de ce este important să urmărim distribuția în timp a transporturilor de lemn.

Criterii de acceptare:

  • Pagina conține o secțiune „De ce contează tăierile de păduri?” cu o explicație despre: defrișări, impact asupra biodiversității, riscuri pentru comunități (inundații, alunecări de teren).
  • Este prezentată, pe scurt, legătura cu SUMAL 2.0 și Inspectorul Pădurii, cu linkuri externe:
    • https://mmediu.ro/domenii/paduri/sumal/
    • https://inspectorulpadurii.ro/#/
  • O secțiune „Ce probleme încearcă să rezolve acest dashboard” explică de ce e util să vedem statistici pe zile, ore și specii (de ex.: identificarea perioadelor de vârf sau a speciilor exploatate intens).
  • Pagina conține un buton „Intră în dashboard” care duce spre pagina principală cu filtre și vizualizări.
  • Conținutul este static (doar HTML și CSS), fără apeluri la API.

Task 2: Header-ul aplicației și navigarea

Construiți un header comun și un meniu de navigare simplu între introducere și dashboard.

Criterii de acceptare:

  • Header-ul include:
    • un logo sau o marcă vizuală a aplicației;
    • titlul aplicației, de exemplu „Distribuția avizelor și volumelor”.
  • Meniul de navigare permite accesul la cel puțin paginile: Introducere și Dashboard.
  • Pagina curentă este evidențiată vizual (ex.: accent de culoare, subliniere, badge „activ”).
  • Header-ul este reutilizat pe pagini (prin copy‑paste sau componentă JS simplă).
  • Layout-ul exact (sus, lateral, sticky etc.) este la alegerea echipei.

Task 3: Intervalul de timp (endpoint /insights/range și /insights)

Implementați selecția de interval și integrarea cu API-ul pentru a obține datele aferente.

Criterii de acceptare:

  • Dashboard-ul afișează un mic formular cu două câmpuri de tip date (sau echivalent):
    • data de început (start),
    • data de final (end).
  • La încărcare, aplicația apelează GET /insights/range pentru a afla intervalul complet disponibil și îl folosește pentru:
    • afișarea unei etichete (ex.: „Date disponibile: 01 ian 2023 – 31 dec 2023”),
    • setarea limitelor min/max pentru câmpurile de dată.
  • Utilizatorul poate:
    • aplica un interval personalizat (submit pe formular → apel GET /insights cu start și end),
    • reveni la intervalul complet printr-un buton (ex.: „Interval complet”).
  • Înainte de a trimite request-ul, aplicația validează că data de început nu este după data de final și afișează un mesaj clar dacă intervalul e invalid.
  • Pentru fiecare cerere către GET /insights, se trimit parametrii de timp (start, end) și cheia de autentificare (X-App-Key sau app_key).

Task 4: Vizualizarea activității zilnice (daily)

Construiți o vizualizare care arată volumul și numărul de avize pentru fiecare zi din interval.

Criterii de acceptare:

  • Pentru datele din payload.daily, aplicația afișează pentru fiecare zi cel puțin:
    • date (formatată într-un mod prietenos),
    • weekday (ziua săptămânii în limba română),
    • volume total,
    • avize (număr de avize).
  • Volumul fiecărei zile este reprezentat vizual (ex.: bară, lungime relativă, intensitate de culoare) astfel încât zilele cu volum mare să fie ușor de recunoscut.
  • Dacă intervalul selectat conține foarte multe zile, se poate afișa doar o fereastră recentă (ex.: ultimele N zile) pentru lizibilitate.
  • Când nu există date pentru intervalul curent, se afișează un mesaj explicit (de ex. „Nu există date în intervalul selectat.”).

Task 5: Vizualizarea pe ore (hourly) și pe specii (species)

Adăugați panouri care arată orele cu trafic intens și speciile transportate.

Criterii de acceptare:

  • Pentru payload.hourly, aplicația afișează topul câtorva ore (de ex. primele 10–12) ordonate după volum sau număr de avize, cu:
    • eticheta label (ex.: „09:00”),
    • transports (număr de transporturi),
    • avize și volume (formatat).
  • Orele cu volum mare se evidențiază vizual (ex.: bare mai lungi sau culori mai intense) pentru a indica perioadele de vârf.
  • Pentru payload.species, aplicația afișează o listă sau alt tip de vizualizare în care, pentru fiecare specie, se văd:
    • name,
    • volume total,
    • avize.
  • Se folosesc indicii vizuali (bare, badge-uri, culori) pentru a distinge speciile cu volum mare.
  • Lipsa datelor pentru ore sau specii este comunicată prin mesaje clare, nu prin panouri goale.

Task 6: Filtrarea după companii (endpoint /companies și parametrii role / company)

Permiteți utilizatorului să limiteze vizualizările la una sau mai multe companii.

Criterii de acceptare:

  • Aplicația oferă un control pentru alegerea rolului companiilor: emitent sau destinatar.
  • Utilizatorul poate introduce numele unei companii pentru a o adăuga ca filtru.
  • Pentru a ajuta la completarea numelui:
    • aplicația poate apela GET /companies cu parametrii role și search și poate folosi răspunsul pentru sugestii (autocomplete),
    • sau poate implementa propriul mecanism simplu de sugestii, folosind tot /companies.
  • Lista de companii selectate este afișată clar (ex.: chip-uri/etichete) și poate fi resetată sau editată (eliminare individuală).
  • La schimbarea filtrelor (rol și/sau companii selectate), cererea către GET /insights include parametrii corespunzători:
    • role,
    • unul sau mai mulți parametri company (ex.: ...&company=SC+DEDEMAN+SRL&company=REAL+DOC+FOREST+SRL).
  • Se afișează mesaje pentru stările comune („fără companii selectate”, „compania este deja adăugată” etc.), astfel încât utilizatorul să înțeleagă ce se întâmplă.

Task 7: Design interfață utilizator (UI) și responsive

Asigurați o experiență coerentă și plăcută, fără a limita creativitatea echipei.

Criterii de acceptare:

  • Toate paginile folosesc o paletă de culori coerentă, ideal inspirată din tematica pădurilor sau a datelor (nuanțe de verde, tonuri neutre, accente pentru valori mari).
  • Sunt implementate componente interactive de bază:
    • butoane cu feedback vizual (hover, focus, stare „loading”),
    • carduri sau panouri pentru diferitele secțiuni de insights.
  • Fonturile sunt lizibile și uniforme; se poate folosi un font web‑safe sau Google Fonts încărcat prin <link>.
  • Layout‑ul este responsive:
    • pe ecrane mari, utilizatorul poate vedea ușor, în același timp, filtrarea și cel puțin două dintre vizualizări;
    • pe mobil, elementele se rearanjează astfel încât selecțiile și graficele să fie ușor de parcurs prin scroll vertical, fără gesturi complicate.
  • Elementele interactive sunt suficient de mari și spațiate pentru interacțiuni touch.
  • Sunteți încurajați să experimentați cu animații subtile, iconografie sau stiluri proprii, atât timp cât păstrați claritatea și accesibilitatea informațiilor.