Skip to content

Formularz zgłoszeniowy + panel podglądu

This content is not available in your language yet.

Stworzycie System zgłoszeniowy - aplikację webową do przyjmowania i zarządzania zgłoszeniami od użytkowników. Może to być system zgłaszania usterek w szkole, helpdesk IT, formularz kontaktowy z obsługą lub system ticketowy. Użytkownicy mogą tworzyć zgłoszenia z opisem problemu i priorytetem, a operatorzy przeglądać je i zmieniać statusy.

Czego się nauczycie?

  • Projektowania workflow zgłoszeń (nowe -> w trakcie -> zamknięte)
  • Obsługi priorytetów i statusów
  • Filtrowania i sortowania danych
  • Tworzenia paneli administracyjnych
  • Praca zespołowa - podział zadań, współpraca, integracja kodu

W prawdziwej firmie...

Systemy ticketowe to podstawa obsługi klienta i wsparcia technicznego. Jira, Zendesk, Freshdesk, GitHub Issues - wszystkie działają na podobnej zasadzie. Umiejętność projektowania takich systemów jest bardzo ceniona na rynku pracy.

Umiejętności rynkowe

Nauczycie się zarządzania stanami (state machine) - koncepcji używanej w każdej aplikacji biznesowej. Zrozumiecie, jak projektować interfejsy dla różnych typów użytkowników (zgłaszający vs operator).

  1. Formularz zgłoszenia Użytkownik wypełnia formularz z tematem zgłoszenia, szczegółowym opisem, priorytetem (niski/średni/wysoki) oraz danymi kontaktowymi. System automatycznie nadaje numer zgłoszenia i znacznik czasu.

  2. Walidacja i zapis System sprawdza poprawność danych - czy wszystkie wymagane pola są wypełnione, czy priorytet jest prawidłowy, czy email ma poprawny format. Poprawne zgłoszenia są zapisywane do pliku JSON.

  3. Panel przeglądu zgłoszeń Lista wszystkich zgłoszeń z możliwością filtrowania po priorytecie, statusie lub dacie. Kolorowe oznaczenia priorytetów ułatwiają identyfikację pilnych spraw.

  4. Zarządzanie statusami (B/C) W wyższych wariantach operator może zmieniać status zgłoszenia (NOWE -> W TRAKCIE -> ZAMKNIĘTE), co pozwala śledzić postęp obsługi.

Formularz zgłoszenia

  • Temat zgłoszenia
  • Szczegółowy opis problemu
  • Wybór priorytetu
  • Dane kontaktowe (imię, email)
  • Przycisk “Wyślij zgłoszenie”

Potwierdzenie

  • Komunikat o przyjęciu zgłoszenia
  • Numer zgłoszenia do śledzenia
  • Link do listy zgłoszeń

Lista zgłoszeń

  • Tabela wszystkich zgłoszeń
  • Kolorowe chipy priorytetów
  • Filtry i sortowanie
  • Statusy zgłoszeń (B+)

Panel operatora (B/C)

  • Szczegóły zgłoszenia
  • Zmiana statusu
  • Historia zmian (C)

Przykładowa struktura pliku JSON:

{
"tickets": [
{
"id": 1,
"ticket_number": "TKT-2026-0001",
"subject": "Nie działa projektor w sali 204",
"description": "Od rana projektor nie reaguje na przycisk włączania. Pilot ma nowe baterie. Proszę o pilną naprawę - mam prezentację o 12:00.",
"priority": "high",
"status": "new",
"contact_name": "Anna Kowalska",
"contact_email": "anna.kowalska@szkola.pl",
"created_at": "2026-02-13 08:30:00",
"updated_at": "2026-02-13 08:30:00"
},
{
"id": 2,
"ticket_number": "TKT-2026-0002",
"subject": "Prośba o nową myszka do pracowni",
"description": "Myszka przy stanowisku 5 w pracowni 108 jest uszkodzona - nie działa scroll.",
"priority": "low",
"status": "in_progress",
"contact_name": "Jan Nowak",
"contact_email": "jan.nowak@szkola.pl",
"created_at": "2026-02-13 09:15:00",
"updated_at": "2026-02-13 10:00:00"
}
]
}

Wymagane funkcjonalności:

  • Formularz zgłoszenia: temat, opis, priorytet, dane kontaktowe
  • Walidacja PHP wszystkich pól (wymagane, format email)
  • Minimum 1 walidacja JavaScript (np. minimalna długość opisu)
  • Zapis zgłoszenia do pliku JSON
  • Generowanie numeru zgłoszenia (np. TKT-2026-0001)
  • Lista wszystkich zgłoszeń z odczytem z JSON
  • Wyświetlanie komunikatów o błędach
  • Potwierdzenie przyjęcia zgłoszenia

Struktura plików:

  • Directoryprojekt/
    • index.php (formularz)
    • submit.php (obsługa POST)
    • list.php (lista zgłoszeń)
    • README.md
    • Directorydata/
      • tickets.json
    • Directorycss/
      • style.css
    • Directoryjs/
      • validation.js
Ocena: 3.0
  1. Nauczyciel odkrywa, że projektor w sali nie działa
  2. Otwiera stronę zgłoszeń i wypełnia formularz
  3. Wpisuje temat “Nie działa projektor w sali 204”
  4. Opisuje szczegóły problemu
  5. Wybiera priorytet “Wysoki” (ma prezentację za 2 godziny)
  6. Podaje swoje dane kontaktowe
  7. Klika “Wyślij zgłoszenie”
  8. Widzi potwierdzenie z numerem TKT-2026-0015
  9. Może śledzić status zgłoszenia

Scenariusz 2: Obsługa zgłoszenia przez operatora (wariant C)

Dział zatytułowany „Scenariusz 2: Obsługa zgłoszenia przez operatora (wariant C)”
  1. Operator IT loguje się do panelu
  2. Widzi listę zgłoszeń posortowaną po priorytecie
  3. Klika w pilne zgłoszenie o projektorze
  4. Przegląda szczegóły i lokalizację
  5. Zmienia status na “W trakcie”
  6. Po naprawie zmienia status na “Zamknięte”
  7. System zapisuje historię zmian
  1. Kierownik chcę zobaczyć wszystkie otwarte zgłoszenia
  2. Otwiera listę zgłoszeń
  3. Ustawia filtr na status “Nowe” i “W trakcie”
  4. Sortuje po priorytecie (najpierw wysokie)
  5. Analizuje obciążenie zespołu IT

Generowanie numeru zgłoszenia:

<?php
function generateTicketNumber(array $tickets): string {
$year = date('Y');
$count = count($tickets) + 1;
return sprintf('TKT-%s-%04d', $year, $count);
}
// Użycie:
$ticketNumber = generateTicketNumber($existingTickets);
// Wynik: "TKT-2026-0001"

Walidacja priorytetu:

<?php
function validatePriority(string $priority): bool {
$allowed = ['low', 'medium', 'high'];
return in_array($priority, $allowed, true);
}
function validateStatus(string $status): bool {
$allowed = ['new', 'in_progress', 'done'];
return in_array($status, $allowed, true);
}
// Walidacja wszystkich pól
function validateTicket(array $data): array {
$errors = [];
if (empty($data['subject'])) {
$errors[] = 'Temat jest wymagany';
} elseif (strlen($data['subject']) < 5) {
$errors[] = 'Temat musi mieć minimum 5 znaków';
}
if (empty($data['description'])) {
$errors[] = 'Opis jest wymagany';
} elseif (strlen($data['description']) < 20) {
$errors[] = 'Opis musi mieć minimum 20 znaków';
}
if (!validatePriority($data['priority'] ?? '')) {
$errors[] = 'Nieprawidłowy priorytet';
}
if (!filter_var($data['contact_email'] ?? '', FILTER_VALIDATE_EMAIL)) {
$errors[] = 'Nieprawidłowy adres email';
}
return $errors;
}

Zmiana statusu zgłoszenia (wariant C):

<?php
function updateTicketStatus(int $ticketId, string $newStatus, string $operator): bool {
$data = readJsonFile('data/tickets.json');
foreach ($data['tickets'] as &$ticket) {
if ($ticket['id'] === $ticketId) {
$ticket['status'] = $newStatus;
$ticket['updated_at'] = date('Y-m-d H:i:s');
// Dodaj do historii zmian
if (!isset($ticket['history'])) {
$ticket['history'] = [];
}
$ticket['history'][] = [
'status' => $newStatus,
'changed_by' => $operator,
'changed_at' => date('Y-m-d H:i:s')
];
return writeJsonFile('data/tickets.json', $data);
}
}
return false;
}

CSS dla chipów priorytetów:

.priority-chip {
display: inline-block;
padding: 4px 12px;
border-radius: 12px;
font-size: 0.8em;
font-weight: bold;
text-transform: uppercase;
}
.priority-low {
background-color: #e0f2fe;
color: #0369a1;
}
.priority-medium {
background-color: #fef3c7;
color: #d97706;
}
.priority-high {
background-color: #fee2e2;
color: #dc2626;
}
.status-chip {
display: inline-block;
padding: 4px 12px;
border-radius: 12px;
font-size: 0.8em;
}
.status-new {
background-color: #dbeafe;
color: #1d4ed8;
}
.status-in_progress {
background-color: #fef9c3;
color: #ca8a04;
}
.status-done {
background-color: #dcfce7;
color: #16a34a;
}

JavaScript - walidacja formularza:

document.getElementById('ticketForm').addEventListener('submit', function(e) {
const subject = document.getElementById('subject').value.trim();
const description = document.getElementById('description').value.trim();
if (subject.length < 5) {
e.preventDefault();
alert('Temat musi mieć minimum 5 znaków');
return false;
}
if (description.length < 20) {
e.preventDefault();
alert('Opis musi mieć minimum 20 znaków - opisz problem dokładniej');
return false;
}
});
// Licznik znaków dla opisu
document.getElementById('description').addEventListener('input', function() {
const counter = document.getElementById('charCounter');
counter.textContent = this.value.length + ' / 20 minimum';
counter.style.color = this.value.length >= 20 ? 'green' : 'red';
});

To prawdziwy projekt zespołowy!

Ten projekt to symulacja pracy w firmie IT. System ticketowy to podstawa każdego helpdesku - nauczycie się tworzyć coś, co jest używane w każdej organizacji!

Pracujcie iteracyjnie - lepiej mieć działający wariant A niż niedziałający C!