Przejdź do głównej zawartości

System zgłoszeń problemów (mini)

Stworzysz System zgłoszeń problemów - uproszczoną wersję helpdesku, gdzie użytkownicy mogą zgłaszać problemy techniczne. Każde zgłoszenie ma priorytet i status, który można zmieniać w miarę rozwiązywania problemu.

Czego się nauczysz?

  • Pracy z formularzami wielopolowymi
  • Zarządzania priorytetami i statusami
  • Walidacji danych z predefiniowanych list
  • Filtrowania i sortowania zgłoszeń
  • Tworzenia prostych raportów

W prawdziwej pracy...

Systemy zgłoszeń (ticketowe) są podstawą obsługi klienta w każdej firmie IT. Jira, Zendesk, ServiceNow - wszystkie działają na podobnej zasadzie. Umiejętność projektowania systemów z przepływem pracy (workflow), priorytetami i statusami jest niezbędna dla każdego programisty aplikacji biznesowych.

  1. Formularz zgłoszenia Użytkownik opisuje problem: tytuł, szczegółowy opis i wybiera priorytet (niski, średni, wysoki).

  2. Walidacja danych System sprawdza poprawność wprowadzonych danych - czy tytuł nie jest pusty, czy priorytet jest z dozwolonej listy.

  3. Lista zgłoszeń Wszystkie zgłoszenia są wyświetlane z priorytetami i statusami, posortowane od najnowszego.

  4. Zmiana statusu Administrator może zmieniać status zgłoszenia (otwarte → w realizacji → zamknięte).

Przykładowa struktura pliku JSON:

{
"issues": [
{
"id": 1,
"title": "Nie działa drukarka w pokoju 203",
"description": "Drukarka HP nie reaguje na polecenia drukowania. Świeci się czerwona kontrolka.",
"priority": "high",
"status": "in_progress",
"reporter": "Jan Kowalski",
"created_at": "2026-02-10 09:30:00",
"updated_at": "2026-02-10 11:00:00"
},
{
"id": 2,
"title": "Prośba o instalację programu",
"description": "Potrzebuję Microsoft Excel na stanowisku roboczym.",
"priority": "low",
"status": "open",
"reporter": "Anna Nowak",
"created_at": "2026-02-11 14:20:00",
"updated_at": "2026-02-11 14:20:00"
},
{
"id": 3,
"title": "Brak dostępu do sieci WiFi",
"description": "Nie mogę połączyć się z siecią firmową. Hasło jest poprawne.",
"priority": "high",
"status": "closed",
"reporter": "Piotr Wiśniewski",
"created_at": "2026-02-09 08:15:00",
"updated_at": "2026-02-09 16:30:00"
}
]
}

Wymagane funkcje:

  • Formularz z polami: tytuł, opis, priorytet (select)
  • Walidacja danych w PHP (wymagane pola, priorytet z listy)
  • Lista wszystkich zgłoszeń
  • Zmiana statusu (open → closed)
  • Prosty interfejs CSS (kolorowanie priorytetów)

Przykładowy scenariusz:

Użytkownik wypełnia formularz: tytuł “Nie działa drukarka”, opis problemu, priorytet “wysoki”. Po zapisie widzi zgłoszenie na liście z czerwonym znacznikiem priorytetu. Może kliknąć “Zamknij” gdy problem rozwiązany.

Ocena: 3.0

Walidacja danych wejściowych:

$title = trim($_POST['title'] ?? '');
$description = trim($_POST['description'] ?? '');
$priority = $_POST['priority'] ?? '';
$reporter = trim($_POST['reporter'] ?? '');
if (empty($title)) {
$errors[] = "Tytuł jest wymagany";
}
if (strlen($title) < 5) {
$errors[] = "Tytuł musi mieć minimum 5 znaków";
}
$validPriorities = ['low', 'medium', 'high'];
if (!in_array($priority, $validPriorities)) {
$errors[] = "Wybierz poprawny priorytet";
}

Dodawanie zgłoszenia:

function addIssue(array &$issues, array $data): int {
$newId = empty($issues) ? 1 : max(array_column($issues, 'id')) + 1;
$now = date('Y-m-d H:i:s');
$newIssue = [
'id' => $newId,
'title' => $data['title'],
'description' => $data['description'] ?? '',
'priority' => $data['priority'],
'status' => 'open',
'reporter' => $data['reporter'] ?? 'Anonim',
'created_at' => $now,
'updated_at' => $now,
];
$issues[] = $newIssue;
return $newId;
}

Zmiana statusu:

function changeIssueStatus(array &$issues, int $issueId, string $newStatus): bool {
$validStatuses = ['open', 'in_progress', 'closed'];
if (!in_array($newStatus, $validStatuses)) {
return false;
}
foreach ($issues as &$issue) {
if ($issue['id'] === $issueId) {
$issue['status'] = $newStatus;
$issue['updated_at'] = date('Y-m-d H:i:s');
return true;
}
}
return false;
}
// Workflow: określ dozwolone przejścia
function getNextStatus(string $currentStatus): array {
$transitions = [
'open' => ['in_progress', 'closed'],
'in_progress' => ['closed', 'open'],
'closed' => ['open'],
];
return $transitions[$currentStatus] ?? [];
}

Filtrowanie zgłoszeń:

function filterIssues(array $issues, ?string $status = null, ?string $priority = null): array {
return array_filter($issues, function($issue) use ($status, $priority) {
if ($status !== null && $issue['status'] !== $status) {
return false;
}
if ($priority !== null && $issue['priority'] !== $priority) {
return false;
}
return true;
});
}

Kolorowanie priorytetów i statusów:

function getPriorityInfo(string $priority): array {
$priorities = [
'low' => ['label' => 'Niski', 'color' => '#27ae60', 'icon' => '🟢'],
'medium' => ['label' => 'Średni', 'color' => '#f39c12', 'icon' => '🟡'],
'high' => ['label' => 'Wysoki', 'color' => '#e74c3c', 'icon' => '🔴'],
];
return $priorities[$priority] ?? $priorities['medium'];
}
function getStatusInfo(string $status): array {
$statuses = [
'open' => ['label' => 'Otwarte', 'color' => '#e74c3c', 'icon' => '📬'],
'in_progress' => ['label' => 'W realizacji', 'color' => '#f39c12', 'icon' => '⚙️'],
'closed' => ['label' => 'Zamknięte', 'color' => '#27ae60', 'icon' => ''],
];
return $statuses[$status] ?? $statuses['open'];
}

Raport statystyk (wariant C):

function getIssueStatistics(array $issues): array {
$total = count($issues);
// Liczba według statusu
$byStatus = [
'open' => 0,
'in_progress' => 0,
'closed' => 0,
];
// Liczba według priorytetu
$byPriority = [
'low' => 0,
'medium' => 0,
'high' => 0,
];
// Czas rozwiązania dla zamkniętych
$resolutionTimes = [];
foreach ($issues as $issue) {
$byStatus[$issue['status']]++;
$byPriority[$issue['priority']]++;
if ($issue['status'] === 'closed') {
$created = strtotime($issue['created_at']);
$updated = strtotime($issue['updated_at']);
$resolutionTimes[] = ($updated - $created) / 3600; // w godzinach
}
}
$avgResolution = !empty($resolutionTimes)
? round(array_sum($resolutionTimes) / count($resolutionTimes), 1)
: 0;
return [
'total' => $total,
'by_status' => $byStatus,
'by_priority' => $byPriority,
'avg_resolution_hours' => $avgResolution,
];
}

Wyszukiwanie:

function searchIssues(array $issues, string $query): array {
if (empty($query)) {
return $issues;
}
$queryLower = mb_strtolower($query);
return array_filter($issues, function($issue) use ($queryLower) {
$titleLower = mb_strtolower($issue['title']);
$descLower = mb_strtolower($issue['description'] ?? '');
return strpos($titleLower, $queryLower) !== false
|| strpos($descLower, $queryLower) !== false;
});
}

Wykorzystaj lekcje!

Cotygodniowe spotkania podczas lekcji to idealny moment, by:

  • Pokazać postępy - nawet małe kroki się liczą
  • Wyjaśnić wątpliwości - pytaj, nie zgaduj
  • Skonsultować rozwiązania - feedback pomoże Ci się rozwijać

Pracuj iteracyjnie - lepiej mieć działający wariant A niż niedokończony C!