INF.03 – FITNESSCLUB – Instrukcja zadania

Instrukcja w stylu arkusza egzaminacyjnego + przykładowe rozwiązania w rozwijanych blokach.

1. Opis zadania FITNESSCLUB

Twoim zadaniem jest przygotowanie mini‑serwisu „FitnessClub”, który składa się z:

  • bazy danych z karnetami i zajęciami,
  • strony PHP prezentującej ofertę karnetów i grafik zajęć,
  • strony HTML z formularzem obliczającym koszt karnetu w JavaScript,
  • wspólnego arkusza stylów CSS nadającego spójny wygląd.

Wszystkie pliki zapisz w jednym folderze o nazwie fitnessclub.

2. Plan pracy krok po kroku

  1. Folder: Na pulpicie utwórz folder fitnessclub.
  2. Serwer: Uruchom serwer lokalny (np. XAMPP), włącz moduły Apache i MySQL.
  3. phpMyAdmin: W przeglądarce otwórz http://localhost/phpmyadmin.
  4. Baza danych: Utwórz bazę fitnessclub i wymagane tabele.
  5. Dane: Wprowadź przykładowe rekordy do tabel.
  6. Kwerendy: Utwórz plik kwerendy_fitness.txt z czterema poleceniami SQL.
  7. Style: Przygotuj arkusz styl_fitness.css.
  8. PHP: Utwórz stronę oferta_fitness.php korzystającą z bazy.
  9. JS: Utwórz stronę kalkulator_karnetu.html z formularzem i skryptem JS.
  10. Test: Skopiuj folder fitnessclub do C:\xampp\htdocs\ i przetestuj obie strony w przeglądarce.

3. Baza danych FITNESSCLUB

3.1. Utworzenie bazy

  1. W phpMyAdmin przejdź do zakładki Bazy danych.
  2. Utwórz bazę danych o nazwie fitnessclub z kodowaniem utf8_general_ci.

3.2. Tabela karnety

  1. W bazie fitnessclub utwórz tabelę karnety.
  2. Zdefiniuj w niej pola:
    • id_karnetu – liczba całkowita, klucz główny, autoinkrementacja.
    • nazwa_karnetu – tekst (co najmniej 60 znaków), wymagane.
    • czas_trwania_mies – liczba całkowita, wymagane (liczba miesięcy).
    • cena_miesieczna – liczba dziesiętna z dwoma miejscami po przecinku, wymagane.
    • dostep_sauna – tekst (np. „TAK” / „NIE”), wymagane.

3.3. Tabela zajecia

  1. W bazie fitnessclub utwórz tabelę zajecia.
  2. Zdefiniuj w niej pola:
    • id_zajec – liczba całkowita, klucz główny, autoinkrementacja.
    • rodzaj_zajec – tekst (co najmniej 60 znaków), wymagane.
    • poziom – tekst (np. „Początkujący”, „Średniozaawansowany”, „Senior”), wymagane.
    • dzien_tygodnia – tekst (np. „Poniedziałek”, „Środa”), wymagane.
    • godzina – typ TIME, wymagane.

3.4. Wprowadzenie danych

  1. Do tabeli karnety wprowadź co najmniej cztery różne karnety (np. Standard, Student, Premium, VIP) z różnym czasem trwania, ceną i informacją o dostępie do sauny.
  2. Do tabeli zajecia wprowadź co najmniej pięć różnych zajęć (np. Joga, Pilates, CrossFit, Zdrowy kręgosłup) z określonym poziomem, dniem tygodnia i godziną.

3.X. Przykładowe rozwiązanie – kod SQL (dla nauczyciela / do weryfikacji)

Przykładowy kod tworzący bazę fitnessclub
CREATE DATABASE IF NOT EXISTS fitnessclub CHARACTER SET utf8 COLLATE utf8_general_ci;
USE fitnessclub;

CREATE TABLE karnety (
    id_karnetu INT AUTO_INCREMENT PRIMARY KEY,
    nazwa_karnetu VARCHAR(60) NOT NULL,
    czas_trwania_mies INT NOT NULL,
    cena_miesieczna DECIMAL(6,2) NOT NULL,
    dostep_sauna VARCHAR(3) NOT NULL
);

CREATE TABLE zajecia (
    id_zajec INT AUTO_INCREMENT PRIMARY KEY,
    rodzaj_zajec VARCHAR(60) NOT NULL,
    poziom VARCHAR(20) NOT NULL,
    dzien_tygodnia VARCHAR(15) NOT NULL,
    godzina TIME NOT NULL
);

INSERT INTO karnety (nazwa_karnetu, czas_trwania_mies, cena_miesieczna, dostep_sauna) VALUES
('Standard', 1, 120.00, 'NIE'),
('Student', 1,  90.00, 'NIE'),
('Premium', 3, 150.00, 'TAK'),
('VIP',     6, 200.00, 'TAK');

INSERT INTO zajecia (rodzaj_zajec, poziom, dzien_tygodnia, godzina) VALUES
('CrossFit',        'Zaawansowany',       'Poniedziałek', '18:00:00'),
('Pilates',         'Początkujący',       'Wtorek',       '17:00:00'),
('Joga',            'Średniozaawansowany','Środa',        '19:00:00'),
('Trening obwodowy','Początkujący',       'Czwartek',     '18:30:00'),
('Zdrowy kręgosłup','Senior',             'Piątek',       '10:00:00');

4. Plik z kwerendami SQL – kwerendy_fitness.txt

4.1. Utworzenie pliku

  1. Otwórz edytor tekstu (Notatnik, Notepad++).
  2. Utwórz nowy plik i zapisz go w folderze fitnessclub jako kwerendy_fitness.txt.

4.2. Zadania dla kwerend

W pliku kwerendy_fitness.txt zapisz cztery kwerendy SQL. Każdą poprzedź komentarzem, np. -- Kw1.

  1. Kw1: Napisz zapytanie wybierające nazwy karnetów, czas trwania w miesiącach i ceny miesięczne z tabeli karnety, posortowane rosnąco po cenie miesięcznej.
  2. Kw2: Napisz zapytanie wybierające rodzaj zajęć, poziom, dzień tygodnia i godzinę z tabeli zajecia tylko dla zajęć odbywających się w środę lub piątek.
  3. Kw3: Napisz zapytanie dodające do tabeli karnety nowy karnet „Senior 60+” na 1 miesiąc, z ceną 80 zł i dostępem do sauny.
  4. Kw4: Napisz zapytanie podnoszące ceny wszystkich karnetów, które mają dostęp do sauny, o 10%.

4.X. Przykładowe rozwiązanie – treść pliku kwerendy_fitness.txt

Przykładowe kwerendy SQL
-- Kw1: nazwy karnetów, czas trwania, cena – rosnąco po cenie
SELECT nazwa_karnetu, czas_trwania_mies, cena_miesieczna
FROM karnety
ORDER BY cena_miesieczna ASC;

-- Kw2: zajęcia tylko w środę lub piątek
SELECT rodzaj_zajec, poziom, dzien_tygodnia, godzina
FROM zajecia
WHERE dzien_tygodnia IN ('Środa', 'Piątek');

-- Kw3: nowy karnet „Senior 60+”
INSERT INTO karnety (nazwa_karnetu, czas_trwania_mies, cena_miesieczna, dostep_sauna)
VALUES ('Senior 60+', 1, 80.00, 'TAK');

-- Kw4: podniesienie ceny karnetów z sauną o 10%
UPDATE karnety
SET cena_miesieczna = cena_miesieczna * 1.10
WHERE dostep_sauna = 'TAK';

5. Arkusz stylów – styl_fitness.css

5.1. Utworzenie pliku stylów

  1. W edytorze tekstu utwórz nowy plik i zapisz go jako styl_fitness.css w folderze fitnessclub.
  2. Ten arkusz stylów wykorzystasz w plikach oferta_fitness.php i kalkulator_karnetu.html.

5.2. Wymagania dotyczące stylu

  • Zastosuj w całej stronie czcionkę Tahoma.
  • Ustaw jasnoszare tło strony i ciemnoszary kolor tekstu.
  • Utwórz główny kontener o maksymalnej szerokości 1100 pikseli, wyśrodkowany, z wewnętrznymi marginesami.
  • Ostyluj nagłówek i stopkę: ciemnoniebieskie tło, biały, wyśrodkowany tekst, górne i dolne marginesy.
  • Ustaw tabele o szerokości 90% strony z obramowaniem 1 px, zlewającym się obramowaniem i odstępami w komórkach.
  • Ustaw nagłówki tabel (<th>) na niebieskim tle, z białym, pogrubionym tekstem.
  • Dla formularza kalkulatora przygotuj kontener z jasnym tłem, obramowaniem i zaokrąglonymi rogami.
  • Pola formularza (input, select) ustaw na szerokość 100%, z wewnętrznym odstępem i zaokrąglonym obramowaniem.
  • Przycisk akcji ostyluj: zielone tło, biały, pogrubiony tekst, zaokrąglone rogi, kursor w formie „rączki”.

5.X. Przykładowe rozwiązanie – treść pliku styl_fitness.css

Przykładowy arkusz stylów
* {
    font-family: Tahoma, sans-serif;
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

body {
    background-color: #f2f2f2;
    color: #343a40;
}

.container {
    max-width: 1100px;
    margin: 0 auto;
    padding: 20px 10px;
}

/* Nagłówek i stopka */
header, footer {
    background: #1e3a5f;
    color: #ffffff;
    text-align: center;
    padding: 16px 0;
    margin: 20px 0;
}

header h1 {
    font-size: 2.2em;
    margin: 0;
}

/* Tabele */
table {
    width: 90%;
    margin: 20px auto;
    border-collapse: collapse;
    border: 1px solid #343a40;
}
td, th {
    border: 1px solid #ccc;
    padding: 10px;
}
th {
    background: #4a7cff;
    color: #ffffff;
    font-weight: bold;
}

/* Formularz i kontrolki */
.form-container {
    max-width: 450px;
    margin: 20px auto;
    padding: 20px;
    background: #e9ecef;
    border-radius: 8px;
    border: 1px solid #ccc;
}

.kontrolka {
    display: block;
    width: 100%;
    margin: 10px 0;
    padding: 8px;
    border-radius: 4px;
    border: 1px solid #ccc;
}

/* Przyciski akcji */
.przycisk-akcja {
    background: #28a745;
    color: #ffffff;
    padding: 10px 20px;
    border-radius: 5px;
    border: none;
    font-weight: bold;
    cursor: pointer;
    margin-top: 15px;
    width: 100%;
}

#wynik_karnetu {
    margin-top: 18px;
    padding: 10px;
    background: #ffffff;
    border: 1px solid #28a745;
    border-radius: 4px;
    font-weight: bold;
}

6. Strona z ofertą – oferta_fitness.php

6.1. Utworzenie pliku

  1. W edytorze utwórz nowy plik i zapisz go w folderze fitnessclub jako oferta_fitness.php.

6.2. Wymagania dla skryptu PHP

  1. Na początku pliku napisz skrypt PHP, który:
    • nawiązuje połączenie z bazą danych fitnessclub (serwer localhost, użytkownik root, bez hasła),
    • wykonuje zapytanie do tabeli karnety, pobierając wszystkie pola,
    • wykonuje zapytanie do tabeli zajecia, pobierając wszystkie pola,
    • zapisuje wyniki w odpowiednich zmiennych.
  2. W części HTML:
    • ustaw nagłówek strony z tytułem „FITNESSCLUB – OFERTA KARNETÓW I ZAJĘĆ”,
    • dołącz arkusz stylów styl_fitness.css,
    • utwórz tabelę „Oferta karnetów” z 5 kolumnami: ID karnetu, nazwa karnetu, czas trwania w miesiącach, cena miesięczna, dostęp do sauny; wiersze wypełnij danymi pobranymi w pętli PHP z tabeli karnety,
    • utwórz tabelę „Grafik zajęć” z 5 kolumnami: ID zajęć, rodzaj zajęć, poziom, dzień tygodnia, godzina; wiersze wypełnij danymi pobranymi w pętli PHP z tabeli zajecia.
  3. Po wyświetleniu danych zamknij połączenie z bazą danych.

6.X. Przykładowe rozwiązanie – treść pliku oferta_fitness.php

Przykładowa strona PHP z ofertą
<?php
$conn = new mysqli("localhost", "root", "", "fitnessclub");
if ($conn->connect_error) {
    die("Błąd połączenia z bazą danych");
}

$sqlKarnety = "SELECT id_karnetu, nazwa_karnetu, czas_trwania_mies, cena_miesieczna, dostep_sauna FROM karnety";
$sqlZajecia = "SELECT id_zajec, rodzaj_zajec, poziom, dzien_tygodnia, godzina FROM zajecia";

$wynikKarnety = $conn->query($sqlKarnety);
$wynikZajecia = $conn->query($sqlZajecia);
?>
<!DOCTYPE html>
<html lang="pl">
<head>
    <meta charset="UTF-8">
    <title>FitnessClub - Oferta</title>
    <link rel="stylesheet" href="styl_fitness.css">
</head>
<body>
<header>
    <h1>FITNESSCLUB – OFERTA KARNETÓW I ZAJĘĆ</h1>
</header>

<main class="container">
    <h2>Oferta karnetów</h2>
    <table>
        <tr>
            <th>ID</th>
            <th>Nazwa karnetu</th>
            <th>Czas trwania (mies.)</th>
            <th>Cena miesięczna (PLN)</th>
            <th>Dostęp do sauny</th>
        </tr>
        <?php
        if ($wynikKarnety && $wynikKarnety->num_rows > 0) {
            while ($row = $wynikKarnety->fetch_assoc()) {
                echo "<tr>";
                echo "<td>{$row['id_karnetu']}</td>";
                echo "<td>{$row['nazwa_karnetu']}</td>";
                echo "<td>{$row['czas_trwania_mies']}</td>";
                echo "<td>{$row['cena_miesieczna']}</td>";
                echo "<td>{$row['dostep_sauna']}</td>";
                echo "</tr>";
            }
        } else {
            echo "<tr><td colspan='5'>Brak karnetów w bazie.</td></tr>";
        }
        ?>
    </table>

    <h2>Grafik zajęć</h2>
    <table>
        <tr>
            <th>ID</th>
            <th>Rodzaj zajęć</th>
            <th>Poziom</th>
            <th>Dzień tygodnia</th>
            <th>Godzina</th>
        </tr>
        <?php
        if ($wynikZajecia && $wynikZajecia->num_rows > 0) {
            while ($row = $wynikZajecia->fetch_assoc()) {
                echo "<tr>";
                echo "<td>{$row['id_zajec']}</td>";
                echo "<td>{$row['rodzaj_zajec']}</td>";
                echo "<td>{$row['poziom']}</td>";
                echo "<td>{$row['dzien_tygodnia']}</td>";
                echo "<td>{$row['godzina']}</td>";
                echo "</tr>";
            }
        } else {
            echo "<tr><td colspan='5'>Brak zajęć w bazie.</td></tr>";
        }
        $conn->close();
        ?>
    </table>
</main>

<footer>
    <p>Przygotował: [NUMER ZDAJĄCEGO]</p>
</footer>
</body>
</html>

7. Kalkulator karnetu – kalkulator_karnetu.html

7.1. Utworzenie pliku

  1. W folderze fitnessclub utwórz plik kalkulator_karnetu.html.

7.2. Wymagania dla strony HTML

  1. Przygotuj dokument HTML5 z ustawionym kodowaniem UTF‑8 i tytułem „FitnessClub – Kalkulator karnetu”.
  2. Dołącz arkusz stylów styl_fitness.css.
  3. W treści strony umieść formularz zawierający:
    • pole tekstowe na imię i nazwisko klienta,
    • listę rozwijaną z wyborem karnetu (każda opcja wyświetla nazwę i cenę miesięczną, a w wartości przechowuje cenę),
    • pole liczbowe do podania liczby miesięcy (minimalna wartość 1),
    • trzy przyciski opcji (radio) dla wyboru zniżki: brak zniżki, student (15%), senior (20%),
    • przycisk uruchamiający obliczenia,
    • element (np. <div>) do wyświetlania wyniku obliczeń.

7.3. Wymagania dla skryptu JavaScript

  1. Umieść w dokumencie skrypt JavaScript z funkcją wywoływaną po kliknięciu przycisku „Oblicz koszt”.
  2. Funkcja powinna:
    • odczytać imię i nazwisko klienta, wybrany karnet, liczbę miesięcy i rodzaj zniżki,
    • sprawdzić, czy imię i nazwisko nie jest puste oraz czy liczba miesięcy jest liczbą większą lub równą 1; w razie błędu wyświetlić komunikat o błędzie w elemencie wyniku,
    • obliczyć koszt bazowy jako iloczyn ceny miesięcznej i liczby miesięcy,
    • obliczyć kwotę zniżki na podstawie wybranego rodzaju zniżki (0%, 15% lub 20%),
    • obliczyć kwotę do zapłaty po uwzględnieniu zniżki,
    • wyświetlić w elemencie wyniku komunikat zawierający imię i nazwisko klienta, nazwę karnetu, liczbę miesięcy, kwotę zniżki oraz kwotę końcową do zapłaty.

7.X. Przykładowe rozwiązanie – treść pliku kalkulator_karnetu.html

Przykładowy kalkulator karnetu (HTML + JS)
<!DOCTYPE html>
<html lang="pl">
<head>
    <meta charset="UTF-8">
    <title>FitnessClub - Kalkulator karnetu</title>
    <link rel="stylesheet" href="styl_fitness.css">
</head>
<body>
<header>
    <h1>FITNESSCLUB – KALKULATOR KARNETU</h1>
</header>

<main class="container">
    <div class="form-container">
        <h2>Oblicz koszt karnetu</h2>

        <label for="klient"><strong>Imię i nazwisko klienta:</strong></label>
        <input type="text" id="klient" class="kontrolka" placeholder="Wpisz imię i nazwisko">

        <label for="karnet"><strong>Wybierz karnet:</strong></label>
        <select id="karnet" class="kontrolka">
            <option value="120" data-nazwa="Standard">Standard (120 PLN / miesiąc)</option>
            <option value="90"  data-nazwa="Student">Student (90 PLN / miesiąc)</option>
            <option value="150" data-nazwa="Premium">Premium (150 PLN / miesiąc)</option>
            <option value="200" data-nazwa="VIP">VIP (200 PLN / miesiąc)</option>
        </select>

        <label for="miesiace"><strong>Liczba miesięcy:</strong></label>
        <input type="number" id="miesiace" class="kontrolka" min="1" value="1">

        <h3>Rodzaj zniżki</h3>
        <label><input type="radio" name="znizka" value="0" checked> Brak zniżki</label><br>
        <label><input type="radio" name="znizka" value="0.15"> Student (15%)</label><br>
        <label><input type="radio" name="znizka" value="0.20"> Senior (20%)</label>

        <button class="przycisk-akcja" onclick="obliczKarnet()">Oblicz koszt</button>

        <div id="wynik_karnetu">
            Tutaj pojawi się wynik obliczeń.
        </div>
    </div>
</main>

<footer>
    <p>Przygotował: [NUMER ZDAJĄCEGO]</p>
</footer>

<script>
function obliczKarnet() {
    const klient = document.getElementById('klient').value.trim();
    const selectKarnet = document.getElementById('karnet');
    const cenaMies = parseFloat(selectKarnet.value);
    const nazwaKarnetu = selectKarnet.options[selectKarnet.selectedIndex].getAttribute('data-nazwa');
    const miesiace = parseInt(document.getElementById('miesiace').value);
    const znizkaElement = document.querySelector('input[name="znizka"]:checked');
    const znizkaProcent = znizkaElement ? parseFloat(znizkaElement.value) : 0;
    const wynikDiv = document.getElementById('wynik_karnetu');

    if (klient === "" || isNaN(miesiace) || miesiace < 1) {
        wynikDiv.innerHTML = "<strong style='color:red;'>BŁĄD: podaj imię i nazwisko klienta oraz liczbę miesięcy (min. 1).</strong>";
        return;
    }

    const kosztBazowy = cenaMies * miesiace;
    const kwotaZnizki = kosztBazowy * znizkaProcent;
    const kosztPoZnizce = kosztBazowy - kwotaZnizki;

    const komunikat = "Klient <strong>" + klient + "</strong>, karnet <strong>" + nazwaKarnetu +
        "</strong> na <strong>" + miesiace + "</strong> mies. " +
        "Cena bazowa: <strong>" + kosztBazowy.toFixed(2) + "</strong> PLN, " +
        "zniżka: <strong>" + kwotaZnizki.toFixed(2) + "</strong> PLN, " +
        "do zapłaty: <strong>" + kosztPoZnizce.toFixed(2) + "</strong> PLN.";

    wynikDiv.innerHTML = komunikat;
}
</script>
</body>
</html>
FitnessClub - Kalkulator karnetu

FITNESSCLUB – KALKULATOR KARNETU

Oblicz koszt karnetu

Rodzaj zniżki



Tutaj pojawi się wynik obliczeń.

Przygotował: [NUMER ZDAJĄCEGO]