Przejdź do głównej zawartości

Panel ogłoszeń szkolnych

Stworzysz Panel ogłoszeń szkolnych - aplikację do publikowania i przeglądania ogłoszeń z określoną datą ważności. System automatycznie rozróżnia aktywne i archiwalne ogłoszenia, pozwala na kategoryzację i filtrowanie treści.

Czego się nauczysz?

  • Pracy z datami ważności (valid_to)
  • Automatycznego archiwizowania wygasłych treści
  • Kategoryzacji i filtrowania ogłoszeń
  • Implementacji systemu CMS-like
  • Tworzenia interfejsu administratora

W prawdziwej pracy...

Systemy ogłoszeń i komunikatów są podstawą intranetu każdej organizacji. Od tablic ogłoszeń firmowych, przez systemy powiadomień, po portale informacyjne - umiejętność projektowania systemów z datą ważności i automatyczną archiwizacją jest fundamentem dla każdego programisty aplikacji korporacyjnych.

  1. Formularz dodawania ogłoszenia Użytkownik podaje tytuł, treść, kategorię i datę ważności ogłoszenia.

  2. Walidacja danych System sprawdza poprawność wprowadzonych danych - czy tytuł nie jest pusty, czy data ważności jest w przyszłości.

  3. Lista ogłoszeń Aktywne ogłoszenia (przed datą ważności) są wyświetlane prominentnie, wygasłe trafiają do archiwum.

  4. Podgląd szczegółów Użytkownik może kliknąć na ogłoszenie i zobaczyć pełną treść.

Przykładowa struktura pliku JSON:

{
"announcements": [
{
"id": 1,
"title": "Zebranie rodziców - klasy 1-3",
"content": "Zapraszamy na zebranie rodziców klas 1-3 w dniu 20.02.2026 o godz. 17:00 w auli szkolnej.",
"category": "zebrania",
"priority": "high",
"valid_from": "2026-02-10",
"valid_to": "2026-02-20",
"author": "Dyrekcja",
"created_at": "2026-02-10 08:00:00"
},
{
"id": 2,
"title": "Konkurs recytatorski",
"content": "Zapraszamy do udziału w szkolnym konkursie recytatorskim. Zgłoszenia do 15.02.",
"category": "wydarzenia",
"priority": "normal",
"valid_from": "2026-02-01",
"valid_to": "2026-02-15",
"author": "Biblioteka",
"created_at": "2026-02-01 10:30:00"
},
{
"id": 3,
"title": "Zmiana planu lekcji",
"content": "W dniu 12.02 obowiązuje zmieniony plan lekcji. Szczegóły u wychowawców.",
"category": "organizacja",
"priority": "high",
"valid_from": "2026-02-11",
"valid_to": "2026-02-12",
"author": "Sekretariat",
"created_at": "2026-02-11 07:00:00"
}
]
}
  • Folderpanel-ogłoszeń/
    • index.php (lista aktywnych ogłoszeń)
    • archiwum.php (wygasłe ogłoszenia)
    • dodaj.php (formularz dodawania)
    • ogłoszenie.php (podgląd szczegółów)
    • edytuj.php (edycja - wariant C)
    • usun.php (usuwanie - wariant C)
    • Folderincludes/
      • config.php
      • functions.php
      • auth.php (wariant C)
    • Folderdata/
      • announcements.json
      • categories.json
      • users.json (wariant C)
    • Foldercss/
      • style.css
    • Folderjs/
      • validation.js

Wymagane funkcje:

  • Formularz dodawania: tytuł, treść, kategoria (select), data ważności
  • Walidacja PHP (tytuł wymagany, data ważności >= dziś)
  • Min. 1 walidacja JavaScript
  • Zapis ogłoszeń do pliku JSON
  • Lista ogłoszeń z podglądem pełnej treści
  • Komunikaty błędów i sukcesu

Przykładowy scenariusz:

Użytkownik wchodzi na panel i widzi listę aktywnych ogłoszeń. Klika “Dodaj ogłoszenie”, wpisuje tytuł “Zebranie rodziców”, wybiera kategorię “Zebrania” i ustawia datę ważności na 20.02. Po zapisie ogłoszenie pojawia się na liście.

Ocena: 3.0

Walidacja danych wejściowych:

$title = trim($_POST['title'] ?? '');
$content = trim($_POST['content'] ?? '');
$category = $_POST['category'] ?? '';
$validTo = $_POST['valid_to'] ?? '';
$today = date('Y-m-d');
if (empty($title)) {
$errors[] = "Tytuł jest wymagany";
}
if (strlen($title) > 200) {
$errors[] = "Tytuł może mieć maksymalnie 200 znaków";
}
if (empty($content)) {
$errors[] = "Treść ogłoszenia jest wymagana";
}
$validCategories = ['zebrania', 'wydarzenia', 'organizacja', 'konkursy', 'inne'];
if (!in_array($category, $validCategories)) {
$errors[] = "Wybierz poprawną kategorię";
}
if ($validTo < $today) {
$errors[] = "Data ważności musi być dzisiejsza lub przyszła";
}

Określanie statusu ogłoszenia:

function isAnnouncementActive(array $announcement): bool {
$today = date('Y-m-d');
$validFrom = $announcement['valid_from'] ?? $announcement['created_at'];
$validTo = $announcement['valid_to'];
return $validFrom <= $today && $validTo >= $today;
}
function getAnnouncementStatus(array $announcement): string {
$today = date('Y-m-d');
$validFrom = $announcement['valid_from'] ?? $today;
$validTo = $announcement['valid_to'];
if ($today < $validFrom) {
return 'scheduled'; // Zaplanowane
} elseif ($today > $validTo) {
return 'expired'; // Wygasłe
}
return 'active'; // Aktywne
}

Filtrowanie ogłoszeń:

function getActiveAnnouncements(array $announcements): array {
return array_filter($announcements, fn($a) => isAnnouncementActive($a));
}
function getArchivedAnnouncements(array $announcements): array {
$today = date('Y-m-d');
return array_filter($announcements, fn($a) => $a['valid_to'] < $today);
}
function filterByCategory(array $announcements, string $category): array {
if (empty($category)) {
return $announcements;
}
return array_filter($announcements, fn($a) => $a['category'] === $category);
}

Sortowanie ogłoszeń:

function sortAnnouncements(array $announcements, string $sortBy = 'valid_to', string $order = 'asc'): array {
usort($announcements, function($a, $b) use ($sortBy, $order) {
$result = strcmp($a[$sortBy] ?? '', $b[$sortBy] ?? '');
return $order === 'desc' ? -$result : $result;
});
return $announcements;
}
// Sortuj: najpierw wysokie priorytety, potem po dacie
function sortByPriorityAndDate(array $announcements): array {
usort($announcements, function($a, $b) {
// Najpierw po priorytecie (high przed normal)
$priorityOrder = ['high' => 0, 'normal' => 1];
$priorityA = $priorityOrder[$a['priority'] ?? 'normal'];
$priorityB = $priorityOrder[$b['priority'] ?? 'normal'];
if ($priorityA !== $priorityB) {
return $priorityA - $priorityB;
}
// Potem po dacie ważności (najbliższe najpierw)
return strcmp($a['valid_to'], $b['valid_to']);
});
return $announcements;
}

Dodawanie ogłoszenia:

function addAnnouncement(array &$announcements, array $data): int {
$newId = empty($announcements) ? 1 : max(array_column($announcements, 'id')) + 1;
$newAnnouncement = [
'id' => $newId,
'title' => $data['title'],
'content' => $data['content'],
'category' => $data['category'],
'priority' => $data['priority'] ?? 'normal',
'valid_from' => $data['valid_from'] ?? date('Y-m-d'),
'valid_to' => $data['valid_to'],
'author' => $data['author'] ?? 'Administrator',
'created_at' => date('Y-m-d H:i:s'),
];
$announcements[] = $newAnnouncement;
return $newId;
}

Kategorie z kolorami:

function getCategories(): array {
return [
'zebrania' => ['label' => 'Zebrania', 'icon' => '👥', 'color' => '#3498db'],
'wydarzenia' => ['label' => 'Wydarzenia', 'icon' => '🎉', 'color' => '#9b59b6'],
'organizacja' => ['label' => 'Organizacja', 'icon' => '📋', 'color' => '#e74c3c'],
'konkursy' => ['label' => 'Konkursy', 'icon' => '🏆', 'color' => '#f39c12'],
'inne' => ['label' => 'Inne', 'icon' => '📢', 'color' => '#95a5a6'],
];
}

Obliczanie dni do wygaśnięcia:

function getDaysUntilExpiry(array $announcement): int {
$today = new DateTime();
$validTo = new DateTime($announcement['valid_to']);
$diff = $today->diff($validTo);
return $diff->invert ? -$diff->days : $diff->days;
}
function formatExpiryInfo(int $days): string {
if ($days < 0) {
return 'Wygasło ' . abs($days) . ' dni temu';
} elseif ($days === 0) {
return 'Wygasa dzisiaj!';
} elseif ($days === 1) {
return 'Wygasa jutro';
} else {
return 'Wygasa za ' . $days . ' dni';
}
}

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!