Przejdź do głównej treści
INF.03-06-26.06-SGCzerwiec 2026 · 47 kroków · ok. 80 min · 40 kryteriów z klucza

Rozwiązanie krok po kroku: Konto pacjenta i recepty (Szablony tekstowe (innerHTML))

To trzeci sposób rozwiązania tego samego arkusza - te same punkty, inna technika generowania bloków recept. Wersja podstawowa i wersja nowoczesna budują każdy element osobno (document.createElement, appendChild). Ta wersja pisze szablon HTML w napisie:

  • funkcja prescriptionHtml() zwraca kod HTML jednego bloku recepty jako szablon tekstowy (napis w odwrotnych apostrofach z wstawkami ${...}),
  • pętla for...of skleja bloki wszystkich recept w jeden napis, a na końcu jedno przypisanie innerHTML wstawia całość do sekcji,
  • dane z tablicy przechodzą przez funkcję escapeHtml() - bez niej nazwa leku ze znakiem < zepsułaby stronę albo wstrzyknęła na nią obcy kod.

Klucz wprost dopuszcza innerHTML w kryteriach R.5.5 - R.5.7. Taki zapis wygląda jak docelowy HTML, więc łatwo go porównać z ilustracją 5 - tak samo działają szablony w PHP i w bibliotekach typu React. Baza, grafika, HTML i CSS są takie jak w wersji nowoczesnej (siatka CSS), różni się etap JavaScript.

Skrypt został sprawdzony w prawdziwej przeglądarce: cztery bloki z listami o 3, 2, 1 i 3 lekach, pięć bloków po dopisaniu recepty i nazwa leku ze znacznikiem wyświetlona jako tekst.

Jak liczą się punkty. Klucz ma 40 kryteriów (R.1.1 - R.5.9), każde za 1 punkt. Próg zdania to 75%, czyli 30 punktów. Przy każdym kroku jest napisane, które kryteria spełnia.

  1. Etap 1: Baza danych

    Kroki 1-7 · po tym etapie masz 6 z 40 kryteriów (pkt)

    Krok 1: Baza danych recepty

    ok. 2 min
    Polecenie z arkusza

    Utwórz bazę danych o nazwie recepty, z zestawem polskich znaków (np. utf8_polish_ci)

    Archiwum na pulpicie nazywa się pliki7.7z, choć to zadanie 06 - tak podaje arkusz. Hasło Rec3ptyPacj3nt@. W phpMyAdmin Nowa → recepty, porównywanie utf8_polish_ci:

    CREATE DATABASE recepty CHARACTER SET utf8 COLLATE utf8_polish_ci;
    
  2. Krok 2: Import tabel z pliku recepty.sql

    ok. 2 min
    Polecenie z arkusza

    Do utworzonej bazy zaimportuj tabele z pliku recepty.sql

    Baza recepty → Import → recepty.sql. Cztery tabele z ilustracji 1: pacjenci, leki, typy i recepty - ta ostatnia łączy pacjentów z lekami (relacja m:n).

  3. Krok 3: Zrzut ekranu import.png

    Kryteria:

    R.1.1 Wykonany import tabel do bazy danych recepty - plik import.png

    ok. 2 min
    Polecenie z arkusza

    Wykonaj zrzut ekranu po imporcie. Zapisz zrzut w formacie PNG pod nazwą import. Nie kadruj zrzutu. Powinien on obejmować cały ekran monitora, z widocznym paskiem zadań. Na zrzucie powinny być widoczne elementy wskazujące na poprawnie wykonany import tabel

    Cały ekran z paskiem zadań, zapis jako import.png.

    Typowe błędy

    Wykadrowany zrzut nie jest oceniany.

  4. Krok 4: Zapytanie 1: leki liczone w sztukach

    Kryteria: ,

    R.1.2 W pliku kwerendy.txt zapisane co najmniej jedno zapytanie SQL, wynikające z treści zadania

    R.1.3 Wykonane zapytanie 1 wybierające jedynie nazwy i ilości leków dla których jednostka miary to sztuki (szt.). W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT nazwa, ilosc FROM leki WHERE jednostka = "szt."; oraz na zrzucie jest dokładnie 5 rekordów

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 1: wybierające jedynie nazwy i ilości leków, dla których jednostka miary to sztuki (szt.)

    Wartość w bazie to dokładnie szt. z kropką, więc warunek też. Każda klauzula w osobnej linii. Wynik: pięć leków. Zapytanie do kwerendy.txt, zrzut kw1.png.

    Typowe błędy

    jednostka = 'szt' bez kropki nie znajduje żadnego wiersza.

    kwerendy.txt Tekst nowy plik
    -- Zapytanie 1
    SELECT nazwa, ilosc
    FROM leki
    WHERE jednostka = 'szt.';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 4
  5. Krok 5: Zapytanie 2: imię na „a”, rok po 2000

    Kryteria:

    R.1.4 Wykonane zapytanie 2 wybierające jedynie imię, nazwisko i rok urodzenia dla pacjentów urodzonych po 2000 roku, których imię jest zakończone literą ‘a’. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT imie, nazwisko, rokUr FROM pacjenci WHERE imie LIKE "%a" AND rokUr > 2000; oraz na zrzucie jest dokładnie 1 rekord: Anna Kowalska 2001

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 2: wybierające jedynie imię, nazwisko i rok urodzenia dla pacjentów urodzonych po 2000 roku, których imię jest zakończone literą ‘a’

    LIKE '%a' - % zastępuje dowolny ciąg znaków, więc wzorzec pasuje do imion kończących się na „a”; rokUr > 2000 - po 2000 roku, bez samego 2000. Drugi warunek w osobnej linii z AND z przodu - łatwo go dopisać albo zakomentować. Wynik: Anna Kowalska, 2001. Zrzut kw2.png.

    Typowe błędy

    LIKE 'a%' szuka imion zaczynających się od „a” (Anna, Adam) i gubi Joannę.

    kwerendy.txt Tekst zmienione: 6 linii
    -- Zapytanie 1
    SELECT nazwa, ilosc
    FROM leki
    WHERE jednostka = 'szt.';
    
    -- Zapytanie 2
    SELECT imie, nazwisko, rokUr
    FROM pacjenci
    WHERE imie LIKE '%a'
      AND rokUr > 2000;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 5
  6. Krok 6: Zapytanie 3: liczba leków każdego typu

    Kryteria:

    R.1.5 Wykonane zapytanie 3 wybierające jedynie nazwy typów oraz zliczające liczbę leków danego typu. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT typ, COUNT(*) FROM leki JOIN typy USING(idTypy) GROUP BY leki.idTypy; (lub porównanie kluczy po ON lub WHERE ) oraz na zrzucie są dokładnie 3 rekordy: syrop 3; tabletki 7; tabletki musujące 3

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 3: wybierające jedynie nazwy typów leków oraz zliczające liczbę leków danego typu. Należy posłużyć się relacją i grupowaniem

    • FROM leki AS l JOIN typy AS t ON t.idTypy = l.idTypy - złączenie z warunkiem w ON, krótkie aliasy tabel,
    • GROUP BY t.idTypy, t.typ - jeden wiersz na typ; w grupowaniu stoją wszystkie wypisywane kolumny bez funkcji, więc zapytanie działa też przy ścisłym trybie SQL (ONLY_FULL_GROUP_BY),
    • COUNT(*) AS liczba_lekow - ile leków w grupie, z czytelną nazwą kolumny.

    Wynik: syrop 3, tabletki 7, tabletki musujące 3. Zrzut kw3.png.

    kwerendy.txt Tekst zmienione: 6 linii
    -- Zapytanie 1
    SELECT nazwa, ilosc
    FROM leki
    WHERE jednostka = 'szt.';
    
    -- Zapytanie 2
    SELECT imie, nazwisko, rokUr
    FROM pacjenci
    WHERE imie LIKE '%a'
      AND rokUr > 2000;
    
    -- Zapytanie 3
    SELECT t.typ, COUNT(*) AS liczba_lekow
    FROM leki AS l
    JOIN typy AS t ON t.idTypy = l.idTypy
    GROUP BY t.idTypy, t.typ;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 6
  7. Krok 7: Zapytanie 4: użytkownik Lekarz

    Kryteria:

    R.1.6 Wykonane zapytanie 4 tworzące użytkownika Lekarz na localhost z hasłem Lek@rz. W pliku z kwerendami lub na zrzucie istnieje zapis np.: CREATE USER 'Lekarz'@'localhost' IDENTIFIED BY 'Lek@rz'; oraz na zrzucie jest widoczny komunikat o poprawnie wykonanym zapytaniu, dopuszczalny jest błąd informujący o niewybraniu bazy

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 4: tworzące użytkownika Lekarz na localhost z hasłem Lek@rz

    CREATE USER 'Lekarz'@'localhost' IDENTIFIED BY 'Lek@rz' - konto, host i hasło. Wielkość liter w nazwie ma znaczenie. Samo konto nie ma żadnych uprawnień - nadaje się je osobno poleceniem GRANT, zawsze tylko te, które są potrzebne (zasada najmniejszych uprawnień). Zrzut z komunikatem: kw4.png.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT nazwa, ilosc
    FROM leki
    WHERE jednostka = 'szt.';
    
    -- Zapytanie 2
    SELECT imie, nazwisko, rokUr
    FROM pacjenci
    WHERE imie LIKE '%a'
      AND rokUr > 2000;
    
    -- Zapytanie 3
    SELECT t.typ, COUNT(*) AS liczba_lekow
    FROM leki AS l
    JOIN typy AS t ON t.idTypy = l.idTypy
    GROUP BY t.idTypy, t.typ;
    
    -- Zapytanie 4
    CREATE USER 'Lekarz'@'localhost' IDENTIFIED BY 'Lek@rz';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 7
  8. Etap 2: Grafika i strona HTML

    Kroki 8-28 · po tym etapie masz 18 z 40 kryteriów (pkt)

    Krok 8: Grafika recepta.png: butelka i zakrętka na czarno

    ok. 3 min
    Polecenie z arkusza

    Modyfikacje grafiki recepta.png: Butelka z zakrętką wypełniona kolorem czarnym

    W GIMP-ie Wypełnienie kubełkiem, kolor czarny, klik w białe wnętrze butelki, potem w zakrętkę (osobny zamknięty obszar). Krzyża nie klikaj - jego wnętrze oddziela kontur.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 8
  9. Krok 9: Grafika recepta.png: czerwony krzyż

    Kryteria:

    R.2.2 Butelka i nakrętka w grafice są wypełnione czarnym kolorem, a krzyż jest wypełniony dowolnym odcieniem czerwonego koloru

    ok. 1 min
    Polecenie z arkusza

    Krzyż na butelce wypełniony kolorem czerwonym

    Kolor czerwony (dowolny odcień - klucz to dopuszcza) i klik kubełkiem we wnętrze krzyża.

    Podgląd strony bez zmian - taki jak po kroku 8.

  10. Krok 10: Grafika recepta.png: przezroczyste tło

    ok. 2 min
    Polecenie z arkusza

    Białe tło zamienione na tło przezroczyste

    Zaznaczenie rozmyte - klik w białe tło - i Edycja → Wyczyść. Białe wnętrze blistra jest otoczone konturem, więc zostaje.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 10
  11. Krok 11: Grafika recepta.png: 100 × 100 px

    Kryteria:

    R.2.1 Grafika recepta.png ma przezroczyste tło oraz wymiary 100 px na 100 px

    ok. 1 min
    Polecenie z arkusza

    Docelowe wymiary grafiki 100 px na 100 px

    Skaluj obraz na końcu - wypełnianie na dużym obrazie jest dokładniejsze. Eksport do PNG zachowuje przezroczystość.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 11
  12. Krok 12: Strony index.html i skierowania.html w budowie

    ok. 2 min
    Polecenie z arkusza

    Witryna składa się ze stron index.html, recepty.html, skierowania.html. W plikach index.html i skierowania.html należy napisać „Strona w trakcie budowy”

    Dwie strony z jednym akapitem w szkielecie HTML5 - odnośniki z bloku nawigacyjnego mają dokąd prowadzić.

    index.html HTML nowy plik
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Strona główna</title>
    </head>
    <body>
        <p>Strona w trakcie budowy</p>
    </body>
    </html>
    skierowania.html HTML nowy plik
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Skierowania</title>
    </head>
    <body>
        <p>Strona w trakcie budowy</p>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  13. Krok 13: Plik recepty.html w HTML5

    ok. 1 min
    Polecenie z arkusza

    Cechy strony recepty.html: Zapisana w języku HTML5

    <!DOCTYPE html> i szkielet strony.

    recepty.html HTML nowy plik
    <!DOCTYPE html>
    <html>
    <head>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (recepty.html)
  14. Krok 14: Język strony

    Kryteria:

    R.2.3 W pliku recepty.html znajduje się deklaracja HTML5 <!DOCTYPE HTML> i deklaracja języka zawartości: polski np. <html lang="pl">

    ok. 1 min
    Polecenie z arkusza

    Zadeklarowany polski język zawartości witryny

    lang="pl" w <html>.

    recepty.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (recepty.html)
  15. Krok 15: Kodowanie polskich znaków

    ok. 1 min
    Polecenie z arkusza

    Jawnie zastosowany właściwy standard kodowania polskich znaków

    <meta charset="UTF-8"> jako pierwszy element <head>.

    recepty.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (recepty.html)
  16. Krok 16: Tytuł strony

    Kryteria:

    R.2.4 W sekcji head znajduje się jawnie podany standard kodowania polskich znaków i tytuł strony "Konto pacjenta"

    ok. 1 min
    Polecenie z arkusza

    Tytuł strony „Konto pacjenta”

    <title> w <head>; obok <meta name="viewport"> dla telefonów - arkusz tego nie wymaga.

    recepty.html HTML zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Konto pacjenta</title>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (recepty.html)
  17. Krok 17: Podpięcie arkusza stylów

    Kryteria:

    R.3.2 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl.css formatowanie CSS pochodzi jedynie z tego arkusza

    ok. 1 min
    Polecenie z arkusza

    Arkusz stylów w pliku o nazwie styl.css prawidłowo połączony z kodem strony

    <link rel="stylesheet" href="styl.css">.

    recepty.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Konto pacjenta</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (recepty.html)
  18. Krok 18: Bloki: nagłówek, nawigacja, cztery sekcje, stopka

    Kryteria:

    R.2.5 W sekcji body zdefiniowany jest podział na bloki za pomocą semantycznych znaczników HTML5: header, nav, main -> section + section + section + section, footer (dopuszcza się stosowanie bloków pomocniczych)

    ok. 2 min
    Polecenie z arkusza

    Podział strony na bloki: nagłówkowy, nawigacyjny, główny i stopka. Blok główny zawiera cztery bloki sekcji. Podział zrealizowany za pomocą semantycznych znaczników języka HTML5 tak, aby po uruchomieniu w przeglądarce układ bloków był zgodny z ilustracją 4

    header, nav, main z czterema section i footer (R.2.5). Sekcje mają identyfikatory z nazw z arkusza. Kolejność w kodzie nie decyduje tu o układzie - ustawi go siatka - więc zostaje kolejność z arkusza.

    recepty.html HTML zmienione: 16 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Konto pacjenta</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
        </header>
        <nav>
        </nav>
        <main>
            <section id="lewa1">
            </section>
            <section id="prawa1">
            </section>
            <section id="prawa2">
            </section>
            <section id="lewa2">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (recepty.html)
  19. Krok 19: Nagłówek strony

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku nagłówkowego: Nagłówek drugiego stopnia o treści: „Strefa pacjenta”

    Drugiego stopnia, czyli <h2>.

    recepty.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Konto pacjenta</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Strefa pacjenta</h2>
        </header>
        <nav>
        </nav>
        <main>
            <section id="lewa1">
            </section>
            <section id="prawa1">
            </section>
            <section id="prawa2">
            </section>
            <section id="lewa2">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (recepty.html)
  20. Krok 20: Odnośnik „Strona główna”

    Kryteria:

    R.3.3 Kliknięcie odnośnika „Strona główna” powoduje przejście do strony index.html

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku nawigacyjnego: Odnośnik do strony index.html o treści „Strona główna”

    Ścieżka względna - strony leżą w jednym folderze.

    recepty.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Konto pacjenta</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Strefa pacjenta</h2>
        </header>
        <nav>
            <a href="index.html">Strona główna</a>
        </nav>
        <main>
            <section id="lewa1">
            </section>
            <section id="prawa1">
            </section>
            <section id="prawa2">
            </section>
            <section id="lewa2">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (recepty.html)
  21. Krok 21: Odnośnik „Recepty”

    Kryteria:

    R.3.4 Kliknięcie odnośnika „Recepty” powoduje przejście do strony recepty.html

    ok. 1 min
    Polecenie z arkusza

    Odnośnik do strony recepty.html o treści „Recepty”

    Odnośnik do bieżącej strony dostaje aria-current="page" - czytnik ekranu powie „bieżąca strona”, a w CSS można go kiedyś wyróżnić. Arkusz tego nie wymaga.

    recepty.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Konto pacjenta</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Strefa pacjenta</h2>
        </header>
        <nav>
            <a href="index.html">Strona główna</a>
            <a href="recepty.html" aria-current="page">Recepty</a>
        </nav>
        <main>
            <section id="lewa1">
            </section>
            <section id="prawa1">
            </section>
            <section id="prawa2">
            </section>
            <section id="lewa2">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (recepty.html)
  22. Krok 22: Odnośnik „Skierowania”

    Kryteria:

    R.3.5 Kliknięcie odnośnika „Skierowania” powoduje przejście do strony skierowania.html

    ok. 1 min
    Polecenie z arkusza

    Odnośnik do strony skierowania.html o treści „Skierowania”

    Trzeci odnośnik; odnośniki są liniowe, więc stoją w jednym wierszu.

    recepty.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Konto pacjenta</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Strefa pacjenta</h2>
        </header>
        <nav>
            <a href="index.html">Strona główna</a>
            <a href="recepty.html" aria-current="page">Recepty</a>
            <a href="skierowania.html">Skierowania</a>
        </nav>
        <main>
            <section id="lewa1">
            </section>
            <section id="prawa1">
            </section>
            <section id="prawa2">
            </section>
            <section id="lewa2">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (recepty.html)
  23. Krok 23: Sekcja lewa1: obraz i nagłówek

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku sekcji lewa1: Obraz pacjent.png z tekstem alternatywnym „dane pacjenta”. Nagłówek trzeciego stopnia o treści „Dane pacjenta”

    Obraz z archiwum ma już 100 × 100 px; <h3> stanie obok niego po dodaniu opływania.

    recepty.html HTML zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Konto pacjenta</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Strefa pacjenta</h2>
        </header>
        <nav>
            <a href="index.html">Strona główna</a>
            <a href="recepty.html" aria-current="page">Recepty</a>
            <a href="skierowania.html">Skierowania</a>
        </nav>
        <main>
            <section id="lewa1">
                <img src="pacjent.png" alt="dane pacjenta">
                <h3>Dane pacjenta</h3>
            </section>
            <section id="prawa1">
            </section>
            <section id="prawa2">
            </section>
            <section id="lewa2">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (recepty.html)
  24. Krok 24: Sekcja lewa1: imię i nazwisko

    ok. 1 min
    Polecenie z arkusza

    Paragraf o treści „Agnieszka”. Paragraf o treści „Nowak”

    Dwa akapity, jak w arkuszu.

    recepty.html HTML zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Konto pacjenta</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Strefa pacjenta</h2>
        </header>
        <nav>
            <a href="index.html">Strona główna</a>
            <a href="recepty.html" aria-current="page">Recepty</a>
            <a href="skierowania.html">Skierowania</a>
        </nav>
        <main>
            <section id="lewa1">
                <img src="pacjent.png" alt="dane pacjenta">
                <h3>Dane pacjenta</h3>
                <p>Agnieszka</p>
                <p>Nowak</p>
            </section>
            <section id="prawa1">
            </section>
            <section id="prawa2">
            </section>
            <section id="lewa2">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (recepty.html)
  25. Krok 25: Sekcja prawa1: obraz i nagłówek

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku sekcji prawa1: Obraz recepta.png z tekstem alternatywnym „dane recept”. Nagłówek trzeciego stopnia o treści „Dane recept”

    Przerobiona grafika i <h3>. Sekcja prawa2 zostaje pusta - wypełni ją skrypt.

    recepty.html HTML zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Konto pacjenta</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Strefa pacjenta</h2>
        </header>
        <nav>
            <a href="index.html">Strona główna</a>
            <a href="recepty.html" aria-current="page">Recepty</a>
            <a href="skierowania.html">Skierowania</a>
        </nav>
        <main>
            <section id="lewa1">
                <img src="pacjent.png" alt="dane pacjenta">
                <h3>Dane pacjenta</h3>
                <p>Agnieszka</p>
                <p>Nowak</p>
            </section>
            <section id="prawa1">
                <img src="recepta.png" alt="dane recept">
                <h3>Dane recept</h3>
            </section>
            <section id="prawa2">
            </section>
            <section id="lewa2">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (recepty.html)
  26. Krok 26: Sekcja lewa2: obraz i nagłówek

    Kryteria:

    R.2.7 W blokach sekcji znajdują się obrazy z tekstami alternatywnymi: lewa1: pacjent.png, alt = "dane pacjenta" lewa2: lekarz.png , alt = "dane lekarza" prawa1: recepta.png , alt = "dane recept"

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku sekcji lewa2: Obraz lekarz.png z tekstem alternatywnym „dane lekarza”. Nagłówek trzeciego stopnia o treści „Dane lekarza”

    Z tym krokiem są wszystkie trzy obrazy z klucza.

    recepty.html HTML zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Konto pacjenta</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Strefa pacjenta</h2>
        </header>
        <nav>
            <a href="index.html">Strona główna</a>
            <a href="recepty.html" aria-current="page">Recepty</a>
            <a href="skierowania.html">Skierowania</a>
        </nav>
        <main>
            <section id="lewa1">
                <img src="pacjent.png" alt="dane pacjenta">
                <h3>Dane pacjenta</h3>
                <p>Agnieszka</p>
                <p>Nowak</p>
            </section>
            <section id="prawa1">
                <img src="recepta.png" alt="dane recept">
                <h3>Dane recept</h3>
            </section>
            <section id="prawa2">
            </section>
            <section id="lewa2">
                <img src="lekarz.png" alt="dane lekarza">
                <h3>Dane lekarza</h3>
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (recepty.html)
  27. Krok 27: Sekcja lewa2: lekarz i numer PWZ

    ok. 1 min
    Polecenie z arkusza

    Paragraf o treści „lek. Marian Kowal”. Paragraf o treści „numer PWZ: 4387203”

    PWZ to numer prawa wykonywania zawodu.

    recepty.html HTML zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Konto pacjenta</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Strefa pacjenta</h2>
        </header>
        <nav>
            <a href="index.html">Strona główna</a>
            <a href="recepty.html" aria-current="page">Recepty</a>
            <a href="skierowania.html">Skierowania</a>
        </nav>
        <main>
            <section id="lewa1">
                <img src="pacjent.png" alt="dane pacjenta">
                <h3>Dane pacjenta</h3>
                <p>Agnieszka</p>
                <p>Nowak</p>
            </section>
            <section id="prawa1">
                <img src="recepta.png" alt="dane recept">
                <h3>Dane recept</h3>
            </section>
            <section id="prawa2">
            </section>
            <section id="lewa2">
                <img src="lekarz.png" alt="dane lekarza">
                <h3>Dane lekarza</h3>
                <p>lek. Marian Kowal</p>
                <p>numer PWZ: 4387203</p>
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (recepty.html)
  28. Krok 28: Stopka z numerem zdającego w em

    Kryteria: ,

    R.2.6 W bloku nagłówkowym znajduje się <h2>: "Strefa pacjenta", w kolejnych blokach sekcji <h3>: "Dane pacjenta", "Dane recept", "Dane lekarza", w blokach sekcji lewa1 i lewa2 po dwa <p>, w stopce <p> z numerem zdającego

    R.2.10 Numer zdającego jest zapisany w znaczniku <em>

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku stopki: Paragraf o treści „Autor strony: ”, dalej wstawiony numer zdającego. Numer zdającego zapisany za pomocą znacznika semantycznego oznaczającego tekst uwypuklony, formatowany domyślnie jako pochylony

    Tekst uwypuklony to <em>. Na egzaminie wpisujesz w nim swój numer zdającego (PESEL) - tutaj stoi imię i nazwisko autora rozwiązania.

    recepty.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Konto pacjenta</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Strefa pacjenta</h2>
        </header>
        <nav>
            <a href="index.html">Strona główna</a>
            <a href="recepty.html" aria-current="page">Recepty</a>
            <a href="skierowania.html">Skierowania</a>
        </nav>
        <main>
            <section id="lewa1">
                <img src="pacjent.png" alt="dane pacjenta">
                <h3>Dane pacjenta</h3>
                <p>Agnieszka</p>
                <p>Nowak</p>
            </section>
            <section id="prawa1">
                <img src="recepta.png" alt="dane recept">
                <h3>Dane recept</h3>
            </section>
            <section id="prawa2">
            </section>
            <section id="lewa2">
                <img src="lekarz.png" alt="dane lekarza">
                <h3>Dane lekarza</h3>
                <p>lek. Marian Kowal</p>
                <p>numer PWZ: 4387203</p>
            </section>
        </main>
        <footer>
            <p>Autor strony: <em>Bartosz Bryniarski</em></p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (recepty.html)
  29. Etap 3: Styl CSS

    Kroki 29-39 · po tym etapie masz 29 z 40 kryteriów (pkt)

    Krok 29: Zmienne z kolorami i krój czcionki

    Kryteria:

    R.4.1 domyślne formatowanie selektorów (*): krój czcionki "Trebuchet MS" - jako pierwszy, sans-serif - jako ostatni

    ok. 2 min
    Polecenie z arkusza

    Domyślnie, dla wszystkich selektorów: krój czcionki Trebuchet MS, w przypadku braku sans-serif

    Dwa brązy z arkusza trafiają do zmiennych CSS w :root - jasny występuje dwa razy (nawigacja i blok recepty pod kursorem). Potem * z krojem i rodziną zapasową sans-serif na końcu (R.4.1).

    styl.css CSS nowy plik
    :root {
        --brown: #B17948;
        --light-brown: #D9A97E;
    }
    
    * {
        font-family: "Trebuchet MS", sans-serif;
    }
    Podgląd strony po tym kroku (recepty.html)
  30. Krok 30: Nagłówek i stopka

    ok. 1 min
    Polecenie z arkusza

    Dla bloków nagłówkowego i stopki: kolor tła #B17948, biały kolor tekstu, marginesy wewnętrzne 5 px, wyrównanie tekstu do środka

    Kolor ze zmiennej var(--brown).

    styl.css CSS zmienione: 8 linii
    :root {
        --brown: #B17948;
        --light-brown: #D9A97E;
    }
    
    * {
        font-family: "Trebuchet MS", sans-serif;
    }
    
    header,
    footer {
        background-color: var(--brown);
        color: white;
        padding: 5px;
        text-align: center;
    }
    Podgląd strony po tym kroku (recepty.html)
  31. Krok 31: Blok nawigacyjny

    Kryteria:

    R.4.2 kolor tła: blok nagłówkowy, stopka - #B17948, blok nawigacyjny - #D9A97E

    ok. 1 min
    Polecenie z arkusza

    Dla bloku nawigacyjnego: kolor tła #D9A97E, kolor czcionki biały, wyrównanie tekstu do środka

    Odnośniki zostają na razie niebieskie: przeglądarka nadaje a własny kolor, który nie dziedziczy się po rodzicu - zmieni go reguła dla a.

    styl.css CSS zmienione: 6 linii
    :root {
        --brown: #B17948;
        --light-brown: #D9A97E;
    }
    
    * {
        font-family: "Trebuchet MS", sans-serif;
    }
    
    header,
    footer {
        background-color: var(--brown);
        color: white;
        padding: 5px;
        text-align: center;
    }
    
    nav {
        background-color: var(--light-brown);
        color: white;
        text-align: center;
    }
    Podgląd strony po tym kroku (recepty.html)
  32. Krok 32: Siatka czterech sekcji zgodna z ilustracją 4

    Kryteria:

    R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z ilustracją 4 w arkuszu egzaminacyjnym (prawidłowo zastosowane właściwości CSS decydujące o układzie bloków na stronie, np. float i clear albo display flex albo grid albo position; żaden blok nie zachodzi na inne blok - sprawdzić w inspektorze)

    ok. 4 min
    Polecenie z arkusza

    Podział zrealizowany za pomocą semantycznych znaczników języka HTML5 tak, aby po uruchomieniu w przeglądarce układ bloków był zgodny z ilustracją 4

    Blok główny to siatka z dwiema kolumnami 40% i 60% - szerokości lewych i prawych sekcji z arkusza (klucz R.4.4 dopuszcza grid-template-columns). grid-template-areas rysuje ilustrację 4 słowami: lewa1 obok prawa1, lewa1 sięga niżej, pod nią lewa2, a prawa2 zajmuje prawą kolumnę od drugiego wiersza.

    Wiersze wynikają z wysokości z arkusza: pierwszy ma 120 px (wysokość prawa1), drugi 80 px (tyle lewa1 ma więcej: 200 - 120), trzeci auto - dopasuje się do reszty prawa2. Dzięki temu lewa2 zaczyna się dokładnie pod lewa1, a prawa2 pod prawa1, bez pustych pasów. Stopka stoi pod siatką bez clear (R.3.1).

    Typowe błędy

    Bez grid-template-rows (same wiersze auto) przeglądarka rozdziela wysokość prawa2 między dwa wiersze i lewa2 odsuwa się od lewa1 - układ odbiega od ilustracji 4.

    styl.css CSS zmienione: 26 linii
    :root {
        --brown: #B17948;
        --light-brown: #D9A97E;
    }
    
    * {
        font-family: "Trebuchet MS", sans-serif;
    }
    
    header,
    footer {
        background-color: var(--brown);
        color: white;
        padding: 5px;
        text-align: center;
    }
    
    nav {
        background-color: var(--light-brown);
        color: white;
        text-align: center;
    }
    
    main {
        display: grid;
        grid-template-columns: 40% 60%;
        grid-template-rows: 120px 80px auto;
        grid-template-areas:
            "lewa1 prawa1"
            "lewa1 prawa2"
            "lewa2 prawa2";
    }
    
    #lewa1 {
        grid-area: lewa1;
    }
    
    #prawa1 {
        grid-area: prawa1;
    }
    
    #prawa2 {
        grid-area: prawa2;
    }
    
    #lewa2 {
        grid-area: lewa2;
    }
    Podgląd strony po tym kroku (recepty.html)
  33. Krok 33: Sekcje lewa1, lewa2 i prawa1: wysokości

    ok. 1 min
    Polecenie z arkusza

    Dla bloków sekcji lewa1 i lewa2: szerokość 40%, wysokość 200 px. Dla bloku sekcji prawa1: szerokość 60%, wysokość 120 px

    Szerokości dają kolumny siatki; wysokości stoją przy blokach, jak w arkuszu.

    styl.css CSS zmienione: 9 linii
    :root {
        --brown: #B17948;
        --light-brown: #D9A97E;
    }
    
    * {
        font-family: "Trebuchet MS", sans-serif;
    }
    
    header,
    footer {
        background-color: var(--brown);
        color: white;
        padding: 5px;
        text-align: center;
    }
    
    nav {
        background-color: var(--light-brown);
        color: white;
        text-align: center;
    }
    
    main {
        display: grid;
        grid-template-columns: 40% 60%;
        grid-template-rows: 120px 80px auto;
        grid-template-areas:
            "lewa1 prawa1"
            "lewa1 prawa2"
            "lewa2 prawa2";
    }
    
    #lewa1 {
        grid-area: lewa1;
    }
    
    #prawa1 {
        grid-area: prawa1;
    }
    
    #prawa2 {
        grid-area: prawa2;
    }
    
    #lewa2 {
        grid-area: lewa2;
    }
    
    #lewa1,
    #lewa2 {
        height: 200px;
    }
    
    #prawa1 {
        height: 120px;
    }
    Podgląd strony po tym kroku (recepty.html)
  34. Krok 34: Sekcja prawa2: paski zawsze widoczne

    Kryteria:

    R.4.4 wysokość bloków sekcji: lewa1 i lewa2 - 200px, prawa1 - 120px, prawa2 - 400px szerokość bloków sekcji: obie lewe - 40%, obie prawe - 60% (width lub grid-template-columns lub flex )

    ok. 1 min
    Polecenie z arkusza

    Dla bloku sekcji prawa2: szerokość 60%, wysokość 400 px, paski przewijania zawsze widoczne

    Dopisane do reguły #prawa2: overflow: scroll - paski są także przy pustej sekcji, jak na ilustracji 2. To zamyka kryterium wymiarów sekcji.

    styl.css CSS zmienione: 2 linie
    :root {
        --brown: #B17948;
        --light-brown: #D9A97E;
    }
    
    * {
        font-family: "Trebuchet MS", sans-serif;
    }
    
    header,
    footer {
        background-color: var(--brown);
        color: white;
        padding: 5px;
        text-align: center;
    }
    
    nav {
        background-color: var(--light-brown);
        color: white;
        text-align: center;
    }
    
    main {
        display: grid;
        grid-template-columns: 40% 60%;
        grid-template-rows: 120px 80px auto;
        grid-template-areas:
            "lewa1 prawa1"
            "lewa1 prawa2"
            "lewa2 prawa2";
    }
    
    #lewa1 {
        grid-area: lewa1;
    }
    
    #prawa1 {
        grid-area: prawa1;
    }
    
    #prawa2 {
        grid-area: prawa2;
        height: 400px;
        overflow: scroll;
    }
    
    #lewa2 {
        grid-area: lewa2;
    }
    
    #lewa1,
    #lewa2 {
        height: 200px;
    }
    
    #prawa1 {
        height: 120px;
    }
    Podgląd strony po tym kroku (recepty.html)
  35. Krok 35: Obrazy opływane z prawej

    Kryteria:

    R.4.8 styl obrazu: opływanie float: left; styl bloku sekcji prawa2: paski przewijania (overflow) - scroll

    ok. 1 min
    Polecenie z arkusza

    Dla selektora obrazu: opływanie po jego prawej stronie, marginesy zewnętrzne 20 px

    Tekst opływa obraz z prawej, czyli obraz pływa w lewo: float: left. Tu zostaje float - klucz R.4.8 podaje go wprost, a opływanie tekstem to jego właściwe zadanie (siatka służy do układu bloków, nie do oblewania obrazu tekstem).

    styl.css CSS zmienione: 5 linii
    :root {
        --brown: #B17948;
        --light-brown: #D9A97E;
    }
    
    * {
        font-family: "Trebuchet MS", sans-serif;
    }
    
    header,
    footer {
        background-color: var(--brown);
        color: white;
        padding: 5px;
        text-align: center;
    }
    
    nav {
        background-color: var(--light-brown);
        color: white;
        text-align: center;
    }
    
    main {
        display: grid;
        grid-template-columns: 40% 60%;
        grid-template-rows: 120px 80px auto;
        grid-template-areas:
            "lewa1 prawa1"
            "lewa1 prawa2"
            "lewa2 prawa2";
    }
    
    #lewa1 {
        grid-area: lewa1;
    }
    
    #prawa1 {
        grid-area: prawa1;
    }
    
    #prawa2 {
        grid-area: prawa2;
        height: 400px;
        overflow: scroll;
    }
    
    #lewa2 {
        grid-area: lewa2;
    }
    
    #lewa1,
    #lewa2 {
        height: 200px;
    }
    
    #prawa1 {
        height: 120px;
    }
    
    img {
        float: left;
        margin: 20px;
    }
    Podgląd strony po tym kroku (recepty.html)
  36. Krok 36: Nagłówek czwartego stopnia

    Kryteria:

    R.4.5 wyrównanie tekstu: blok nagłówkowy, stopka, nawigacyjny - do środka, nagłówek czwartego stopnia - do prawej strony

    ok. 1 min
    Polecenie z arkusza

    Dla selektora nagłówka czwartego stopnia: wyrównanie tekstu do prawej strony, kolor czcionki czerwony, rozmiar czcionki 120%

    W <h4> skrypt wypisze kod recepty.

    styl.css CSS zmienione: 6 linii
    :root {
        --brown: #B17948;
        --light-brown: #D9A97E;
    }
    
    * {
        font-family: "Trebuchet MS", sans-serif;
    }
    
    header,
    footer {
        background-color: var(--brown);
        color: white;
        padding: 5px;
        text-align: center;
    }
    
    nav {
        background-color: var(--light-brown);
        color: white;
        text-align: center;
    }
    
    main {
        display: grid;
        grid-template-columns: 40% 60%;
        grid-template-rows: 120px 80px auto;
        grid-template-areas:
            "lewa1 prawa1"
            "lewa1 prawa2"
            "lewa2 prawa2";
    }
    
    #lewa1 {
        grid-area: lewa1;
    }
    
    #prawa1 {
        grid-area: prawa1;
    }
    
    #prawa2 {
        grid-area: prawa2;
        height: 400px;
        overflow: scroll;
    }
    
    #lewa2 {
        grid-area: lewa2;
    }
    
    #lewa1,
    #lewa2 {
        height: 200px;
    }
    
    #prawa1 {
        height: 120px;
    }
    
    img {
        float: left;
        margin: 20px;
    }
    
    h4 {
        text-align: right;
        color: red;
        font-size: 120%;
    }
    Podgląd strony po tym kroku (recepty.html)
  37. Krok 37: Odnośniki

    Kryteria: , ,

    R.4.3 kolor czcionki: blok nagłówkowy, stopka, nawigacyjny, selektor a - biały oraz selektor h4 - czerwony (dowolny odcień )

    R.4.6 marginesy wewnętrzne (padding ): blok nagłówkowy, stopka - 5px marginesy zewnętrzne (margin ) selektor img - 20px, odnośnik - 30px

    R.4.7 rozmiar czcionki: nagłówek czwartego stopnia - 120%, odnośnik - 150%

    ok. 1 min
    Polecenie z arkusza

    Dla selektora odnośnika: biały kolor czcionki, rozmiar czcionki 150%, marginesy zewnętrzne 30 px

    Reguła a zmienia kolor odnośników na biały; marginesy rozsuwają je w poziomie. Domyka kryteria kolorów, marginesów i rozmiarów czcionki.

    styl.css CSS zmienione: 6 linii
    :root {
        --brown: #B17948;
        --light-brown: #D9A97E;
    }
    
    * {
        font-family: "Trebuchet MS", sans-serif;
    }
    
    header,
    footer {
        background-color: var(--brown);
        color: white;
        padding: 5px;
        text-align: center;
    }
    
    nav {
        background-color: var(--light-brown);
        color: white;
        text-align: center;
    }
    
    main {
        display: grid;
        grid-template-columns: 40% 60%;
        grid-template-rows: 120px 80px auto;
        grid-template-areas:
            "lewa1 prawa1"
            "lewa1 prawa2"
            "lewa2 prawa2";
    }
    
    #lewa1 {
        grid-area: lewa1;
    }
    
    #prawa1 {
        grid-area: prawa1;
    }
    
    #prawa2 {
        grid-area: prawa2;
        height: 400px;
        overflow: scroll;
    }
    
    #lewa2 {
        grid-area: lewa2;
    }
    
    #lewa1,
    #lewa2 {
        height: 200px;
    }
    
    #prawa1 {
        height: 120px;
    }
    
    img {
        float: left;
        margin: 20px;
    }
    
    h4 {
        text-align: right;
        color: red;
        font-size: 120%;
    }
    
    a {
        color: white;
        font-size: 150%;
        margin: 30px;
    }
    Podgląd strony po tym kroku (recepty.html)
  38. Krok 38: Klasa recepty

    Kryteria:

    R.4.9 styl klasy .recepty : kolor tła PeachPuff, marginesy wewnętrzne (padding ) - 20px, zewnętrzne (margin ) - 40px, zaokrąglenie rogów (border-radius) - 20px

    ok. 1 min
    Polecenie z arkusza

    Dla klasy recepty: kolor tła PeachPuff, marginesy wewnętrzne 20 px, zewnętrzne 40 px, zaokrąglenie rogów 20 px

    Styl bloków, które wygeneruje skrypt.

    styl.css CSS zmienione: 7 linii
    :root {
        --brown: #B17948;
        --light-brown: #D9A97E;
    }
    
    * {
        font-family: "Trebuchet MS", sans-serif;
    }
    
    header,
    footer {
        background-color: var(--brown);
        color: white;
        padding: 5px;
        text-align: center;
    }
    
    nav {
        background-color: var(--light-brown);
        color: white;
        text-align: center;
    }
    
    main {
        display: grid;
        grid-template-columns: 40% 60%;
        grid-template-rows: 120px 80px auto;
        grid-template-areas:
            "lewa1 prawa1"
            "lewa1 prawa2"
            "lewa2 prawa2";
    }
    
    #lewa1 {
        grid-area: lewa1;
    }
    
    #prawa1 {
        grid-area: prawa1;
    }
    
    #prawa2 {
        grid-area: prawa2;
        height: 400px;
        overflow: scroll;
    }
    
    #lewa2 {
        grid-area: lewa2;
    }
    
    #lewa1,
    #lewa2 {
        height: 200px;
    }
    
    #prawa1 {
        height: 120px;
    }
    
    img {
        float: left;
        margin: 20px;
    }
    
    h4 {
        text-align: right;
        color: red;
        font-size: 120%;
    }
    
    a {
        color: white;
        font-size: 150%;
        margin: 30px;
    }
    
    .recepty {
        background-color: PeachPuff;
        padding: 20px;
        margin: 40px;
        border-radius: 20px;
    }
    Podgląd strony po tym kroku (recepty.html)
  39. Krok 39: Blok recepty pod kursorem

    Kryteria:

    R.4.10 gdy kursor znajdzie się na elemencie z przypisaną klasą .recepty, kolor tła zmienia się na #D9A97E

    ok. 1 min
    Polecenie z arkusza

    Gdy kursor znajdzie się na elemencie z przypisaną klasą recepty, kolor tła zmienia się na #D9A97E

    Pseudoklasa :hover, kolor ze zmiennej - ten sam brąz co nawigacja.

    styl.css CSS zmienione: 4 linie
    :root {
        --brown: #B17948;
        --light-brown: #D9A97E;
    }
    
    * {
        font-family: "Trebuchet MS", sans-serif;
    }
    
    header,
    footer {
        background-color: var(--brown);
        color: white;
        padding: 5px;
        text-align: center;
    }
    
    nav {
        background-color: var(--light-brown);
        color: white;
        text-align: center;
    }
    
    main {
        display: grid;
        grid-template-columns: 40% 60%;
        grid-template-rows: 120px 80px auto;
        grid-template-areas:
            "lewa1 prawa1"
            "lewa1 prawa2"
            "lewa2 prawa2";
    }
    
    #lewa1 {
        grid-area: lewa1;
    }
    
    #prawa1 {
        grid-area: prawa1;
    }
    
    #prawa2 {
        grid-area: prawa2;
        height: 400px;
        overflow: scroll;
    }
    
    #lewa2 {
        grid-area: lewa2;
    }
    
    #lewa1,
    #lewa2 {
        height: 200px;
    }
    
    #prawa1 {
        height: 120px;
    }
    
    img {
        float: left;
        margin: 20px;
    }
    
    h4 {
        text-align: right;
        color: red;
        font-size: 120%;
    }
    
    a {
        color: white;
        font-size: 150%;
        margin: 30px;
    }
    
    .recepty {
        background-color: PeachPuff;
        padding: 20px;
        margin: 40px;
        border-radius: 20px;
    }
    
    .recepty:hover {
        background-color: var(--light-brown);
    }
    Podgląd strony po tym kroku (recepty.html)
  40. Etap 4: JavaScript

    Kroki 40-45 · po tym etapie masz 40 z 40 kryteriów (pkt)

    Krok 40: Plik skrypt.js z danymi z dane.json

    Kryteria: , ,

    R.5.1 Skrypt w języku JavaScript zawiera przynajmniej jedną poprawną składniowo instrukcję wynikającą z treści zadania

    R.5.2 Zastosowana przynajmniej jedna zmienna oraz nazewnictwo jest w języku polskim lub angielskim i odzwierciedla cel zastosowania

    R.5.3 Dane do skryptu są pobrane ze struktury, której wzór znajduje się w pliku dane.json . Struktura jest kompletna. Wymagane przynajmniej jedno odwołanie do elementu tablicy recepty

    ok. 2 min
    Polecenie z arkusza

    Strukturę danych należy skopiować z pliku dane.json

    Skrypt trafia do osobnego pliku skrypt.js, podpiętego w <head> z atrybutem defer: przeglądarka pobiera go równolegle i wykonuje po wczytaniu całego HTML-u, więc sekcja prawa2 już istnieje.

    Na początek kopia całej zawartości dane.json. To nie jest czysty JSON, tylko instrukcja JavaScriptu - zmienna z obiektem. Jedna zmiana: var na const - nazwa pacjenci nie zostanie przypisana od nowa (zawartość tablicy nadal można zmieniać). Struktura jest kompletna, jak wymaga R.5.3.

    Typowe błędy

    Pominięcie części struktury (np. tylko tablica recepty) kosztuje R.5.3 - klucz wymaga, by była kompletna.

    recepty.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Konto pacjenta</title>
        <link rel="stylesheet" href="styl.css">
        <script src="skrypt.js" defer></script>
    </head>
    <body>
        <header>
            <h2>Strefa pacjenta</h2>
        </header>
        <nav>
            <a href="index.html">Strona główna</a>
            <a href="recepty.html" aria-current="page">Recepty</a>
            <a href="skierowania.html">Skierowania</a>
        </nav>
        <main>
            <section id="lewa1">
                <img src="pacjent.png" alt="dane pacjenta">
                <h3>Dane pacjenta</h3>
                <p>Agnieszka</p>
                <p>Nowak</p>
            </section>
            <section id="prawa1">
                <img src="recepta.png" alt="dane recept">
                <h3>Dane recept</h3>
            </section>
            <section id="prawa2">
            </section>
            <section id="lewa2">
                <img src="lekarz.png" alt="dane lekarza">
                <h3>Dane lekarza</h3>
                <p>lek. Marian Kowal</p>
                <p>numer PWZ: 4387203</p>
            </section>
        </main>
        <footer>
            <p>Autor strony: <em>Bartosz Bryniarski</em></p>
        </footer>
    </body>
    </html>
    skrypt.js JavaScript nowy plik
    const pacjenci = {
        "id": "1",
        "imie": "Agnieszka",
        "nazwisko": "Nowak",
        "wystawca": "lek. Marian Kowal",
        "numer": "4387203",
        "recepty": [
            {"id": "0",  "data": "8.03.2025", "kod": "1220", "lek1": "Witamina C", "lek2": "Potas", "lek3": "Syrop prawoślazowy"},    
            {"id": "1",  "data": "23.04.2025", "kod": "4634", "lek1": "APAP", "lek2": "Witamina B", "lek3": ""},    
            {"id": "2",  "data": "13.05.2025", "kod": "2913", "lek1": "Melatonina", "lek2": "", "lek3": ""},    
            {"id": "3",  "data": "30.10.2025", "kod": "1105", "lek1": "Witamina C", "lek2": "Calcium", "lek3": "Sinupret"}
        ]
    };
    Podgląd strony po tym kroku (recepty.html)
  41. Krok 41: Pętla: szablon bloku z klasą recepty dla każdej recepty

    Kryteria: , ,

    R.5.4 Program wykorzystuje pętlę działającą na wszystkich elementach tablicy recepty. Skrypt napisano uniwersalnie dla dowolnej liczby elementów w tablicy

    R.5.5 Skrypt tworzy elementy bloków (np. div ) z atrybutem class = recepty w bloku sekcji prawej np. blok = document.createElement("div"); blok.setAttribute("class", "recepty"); ( lub blok.className = "recepty"; lub blok.classList.add("recepty");) prawy = document.getElementById("prawy2"); prawy.appendChild(blok);

    R.5.8 Na stronie jest wyświetlanych za pomocą pętli tyle bloków, ile jest elementów w tablicy recepty . Każdy blok ma przypisaną klasę recepty

    ok. 4 min
    Polecenie z arkusza

    Struktura jest uproszczona, dane innych pacjentów nie będą dodawane, ale może ulec zmianie tablica recepty. W tym mogą zostać dopisane nowe elementy do tablicy, co należy uwzględnić w skrypcie. Generowanych jest tyle bloków ile jest elementów tablicy recepty. Każdy blok ma przypisaną klasę recepty

    Funkcja prescriptionHtml(prescription) zwraca kod HTML jednego bloku jako szablon tekstowy - napis w odwrotnych apostrofach, który może mieć wiele linii i wstawki ${...}. Na razie sam pusty <div class="recepty">.

    Pętla for...of przechodzi po wszystkich receptach (po dopisaniu recepty - o jeden obieg więcej) i dokleja kolejne bloki do zmiennej html. Dopiero po pętli jedno przypisanie innerHTML wstawia całość do sekcji prawa2. Klucz dopuszcza innerHTML w R.5.5 - R.5.7; przypisanie raz zamiast innerHTML += w pętli jest szybsze, bo przeglądarka analizuje HTML jeden raz, a nie przy każdym obiegu od nowa. W podglądzie cztery puste brzoskwiniowe bloki.

    skrypt.js JavaScript zmienione: 12 linii
    const pacjenci = {
        "id": "1",
        "imie": "Agnieszka",
        "nazwisko": "Nowak",
        "wystawca": "lek. Marian Kowal",
        "numer": "4387203",
        "recepty": [
            {"id": "0",  "data": "8.03.2025", "kod": "1220", "lek1": "Witamina C", "lek2": "Potas", "lek3": "Syrop prawoślazowy"},    
            {"id": "1",  "data": "23.04.2025", "kod": "4634", "lek1": "APAP", "lek2": "Witamina B", "lek3": ""},    
            {"id": "2",  "data": "13.05.2025", "kod": "2913", "lek1": "Melatonina", "lek2": "", "lek3": ""},    
            {"id": "3",  "data": "30.10.2025", "kod": "1105", "lek1": "Witamina C", "lek2": "Calcium", "lek3": "Sinupret"}
        ]
    };
    
    function prescriptionHtml(prescription) {
        return `
            <div class="recepty">
            </div>`;
    }
    
    let html = '';
    for (const prescription of pacjenci.recepty) {
        html += prescriptionHtml(prescription);
    }
    document.querySelector('#prawa2').innerHTML = html;
    Podgląd strony po tym kroku (recepty.html)
  42. Krok 42: Akapit z datą wystawienia i funkcja escapeHtml

    Kryteria:

    R.5.6 Skrypt tworzy przynajmniej jeden element <p> lub <h4> w utworzonym bloku np. data = document.createElement("p"); ... blok.appendChild(data); (gdzie blok to uchwyt z przykładu w R.5.5)

    ok. 4 min
    Polecenie z arkusza

    Wewnątrz jednego bloku generowane są: Paragraf o treści „Data wystawienia: ”, dalej wstawiona wartość z tablicy

    W szablonie akapit z wstawką ${...}. Każda wartość z danych przechodzi przez escapeHtml(): zamienia &, <, > i cudzysłowy na encje. To konieczne przy innerHTML - napis jest czytany jako kod HTML, więc lek o nazwie <img src=x onerror=alert(1)> uruchomiłby obcy skrypt (atak XSS), a w nazwie „Witamina <C>” fragment w nawiasach zniknąłby jako nieznany znacznik. Zamiana & musi być pierwsza, inaczej popsułaby encje dopisane przez kolejne zamiany.

    Typowe błędy

    Szablon bez escapeHtml działa na danych z arkusza, ale pierwszy nietypowy znak w danych psuje stronę - przy innerHTML escapowanie to część poprawnego kodu, nie dodatek.

    skrypt.js JavaScript zmienione: 10 linii
    const pacjenci = {
        "id": "1",
        "imie": "Agnieszka",
        "nazwisko": "Nowak",
        "wystawca": "lek. Marian Kowal",
        "numer": "4387203",
        "recepty": [
            {"id": "0",  "data": "8.03.2025", "kod": "1220", "lek1": "Witamina C", "lek2": "Potas", "lek3": "Syrop prawoślazowy"},    
            {"id": "1",  "data": "23.04.2025", "kod": "4634", "lek1": "APAP", "lek2": "Witamina B", "lek3": ""},    
            {"id": "2",  "data": "13.05.2025", "kod": "2913", "lek1": "Melatonina", "lek2": "", "lek3": ""},    
            {"id": "3",  "data": "30.10.2025", "kod": "1105", "lek1": "Witamina C", "lek2": "Calcium", "lek3": "Sinupret"}
        ]
    };
    
    function escapeHtml(text) {
        return text
            .replaceAll('&', '&amp;')
            .replaceAll('<', '&lt;')
            .replaceAll('>', '&gt;')
            .replaceAll('"', '&quot;')
            .replaceAll("'", '&#39;');
    }
    
    function prescriptionHtml(prescription) {
        return `
            <div class="recepty">
                <p>Data wystawienia: ${escapeHtml(prescription.data)}</p>
            </div>`;
    }
    
    let html = '';
    for (const prescription of pacjenci.recepty) {
        html += prescriptionHtml(prescription);
    }
    document.querySelector('#prawa2').innerHTML = html;
    Podgląd strony po tym kroku (recepty.html)
  43. Krok 43: Lista numerowana z pierwszym lekiem

    Kryteria:

    R.2.9 Na stronie znajduje się przynajmniej jedna lista numerowana z przynajmniej jednym elementem (znaczniki <ol>, <li>; w HTML lub skrypcie)

    ok. 2 min
    Polecenie z arkusza

    Lista numerowana (uporządkowana) z nazwami leków pobranymi z tablicy. Pod jednym indeksem tablicy recepty mogą być maksymalnie trzy leki, zapisane w polach lek1, lek2, lek3. Pierwszy lek zawsze jest wpisany.

    Elementy listy powstają w zmiennej medicines przed szablonem bloku - pierwszy lek zawsze. Szablon wstawia je między <ol> i </ol>.

    skrypt.js JavaScript zmienione: 3 linie
    const pacjenci = {
        "id": "1",
        "imie": "Agnieszka",
        "nazwisko": "Nowak",
        "wystawca": "lek. Marian Kowal",
        "numer": "4387203",
        "recepty": [
            {"id": "0",  "data": "8.03.2025", "kod": "1220", "lek1": "Witamina C", "lek2": "Potas", "lek3": "Syrop prawoślazowy"},    
            {"id": "1",  "data": "23.04.2025", "kod": "4634", "lek1": "APAP", "lek2": "Witamina B", "lek3": ""},    
            {"id": "2",  "data": "13.05.2025", "kod": "2913", "lek1": "Melatonina", "lek2": "", "lek3": ""},    
            {"id": "3",  "data": "30.10.2025", "kod": "1105", "lek1": "Witamina C", "lek2": "Calcium", "lek3": "Sinupret"}
        ]
    };
    
    function escapeHtml(text) {
        return text
            .replaceAll('&', '&amp;')
            .replaceAll('<', '&lt;')
            .replaceAll('>', '&gt;')
            .replaceAll('"', '&quot;')
            .replaceAll("'", '&#39;');
    }
    
    function prescriptionHtml(prescription) {
        let medicines = `<li>${escapeHtml(prescription.lek1)}</li>`;
    
        return `
            <div class="recepty">
                <p>Data wystawienia: ${escapeHtml(prescription.data)}</p>
                <ol>${medicines}</ol>
            </div>`;
    }
    
    let html = '';
    for (const prescription of pacjenci.recepty) {
        html += prescriptionHtml(prescription);
    }
    document.querySelector('#prawa2').innerHTML = html;
    Podgląd strony po tym kroku (recepty.html)
  44. Krok 44: Leki z pętli, puste wpisy pominięte

    Kryteria:

    R.5.7 Skrypt tworzy listę z elementami w utworzonym bloku np. listalekow = document.createElement("ol"); lek1 = document.createElement("li"); listalekow.appendChild(lek1); ... blok.appendChild(listalekow); (gdzie blok to uchwyt z przykładu w R.5.5) oraz tworzy tyle elementów listy ile jest danych w polach lek1, lek2, lek3 np. if(pacjenci.recepty[i].lek2) ...

    ok. 3 min
    Polecenie z arkusza

    Kolejne wpisy mogą być puste. Gdy wpis jest pusty – nie jest uwzględniany w liście. Na ilustracji 5 pokazano wygenerowany drugi i trzeci blok dla indeksów [1] i [2] tablicy recepty. Pod indeksem [1] zdefiniowano tylko dwa leki, pod indeksem [2] zdefiniowano tylko jeden lek – dlatego listy mają kolejno dwa i jeden element

    Pętla po trzech polach leków; <li> dopisuje się tylko dla niepustego wpisu (!==). Listy mają 3, 2, 1 i 3 elementy - jak na ilustracji 5.

    Typowe błędy

    <li> dla pustego leku pokazuje sam numer - klucz wymaga listy n-elementowej (R.5.9).

    skrypt.js JavaScript zmienione: 6 linii
    const pacjenci = {
        "id": "1",
        "imie": "Agnieszka",
        "nazwisko": "Nowak",
        "wystawca": "lek. Marian Kowal",
        "numer": "4387203",
        "recepty": [
            {"id": "0",  "data": "8.03.2025", "kod": "1220", "lek1": "Witamina C", "lek2": "Potas", "lek3": "Syrop prawoślazowy"},    
            {"id": "1",  "data": "23.04.2025", "kod": "4634", "lek1": "APAP", "lek2": "Witamina B", "lek3": ""},    
            {"id": "2",  "data": "13.05.2025", "kod": "2913", "lek1": "Melatonina", "lek2": "", "lek3": ""},    
            {"id": "3",  "data": "30.10.2025", "kod": "1105", "lek1": "Witamina C", "lek2": "Calcium", "lek3": "Sinupret"}
        ]
    };
    
    function escapeHtml(text) {
        return text
            .replaceAll('&', '&amp;')
            .replaceAll('<', '&lt;')
            .replaceAll('>', '&gt;')
            .replaceAll('"', '&quot;')
            .replaceAll("'", '&#39;');
    }
    
    function prescriptionHtml(prescription) {
        let medicines = '';
        for (const medicine of [prescription.lek1, prescription.lek2, prescription.lek3]) {
            if (medicine !== '') {
                medicines += `<li>${escapeHtml(medicine)}</li>`;
            }
        }
    
        return `
            <div class="recepty">
                <p>Data wystawienia: ${escapeHtml(prescription.data)}</p>
                <ol>${medicines}</ol>
            </div>`;
    }
    
    let html = '';
    for (const prescription of pacjenci.recepty) {
        html += prescriptionHtml(prescription);
    }
    document.querySelector('#prawa2').innerHTML = html;
    Podgląd strony po tym kroku (recepty.html)
  45. Krok 45: Nagłówek z kodem recepty

    Kryteria: ,

    R.2.8 W bloku sekcji prawa2 znajduje się przynajmniej jeden blok z paragrafem i nagłówkiem <h4> (w HTML lub skrypcie )

    R.5.9 Każdy blok zawiera paragraf z datą, listę n-elementową, gdzie n to liczba wymienionych leków oraz nagłówek <h4>

    ok. 2 min
    Polecenie z arkusza

    Nagłówek czwartego stopnia o treści „Kod: ”, dalej wstawiona wartość kodu z tablicy

    Ostatni element szablonu: <h4> z kodem. Szablon wygląda teraz jak docelowy HTML bloku z ilustracji 5 - akapit, lista, kod - więc łatwo porównać go z wymaganiem wzrokiem. Sprawdzone w przeglądarce z dopisaną piątą receptą, której leki mają w nazwie znaczniki (<b>, <img>): powstaje pięć bloków, a znaczniki wyświetlają się jako tekst - nic się nie wykonuje.

    skrypt.js JavaScript zmienione: 1 linia
    const pacjenci = {
        "id": "1",
        "imie": "Agnieszka",
        "nazwisko": "Nowak",
        "wystawca": "lek. Marian Kowal",
        "numer": "4387203",
        "recepty": [
            {"id": "0",  "data": "8.03.2025", "kod": "1220", "lek1": "Witamina C", "lek2": "Potas", "lek3": "Syrop prawoślazowy"},    
            {"id": "1",  "data": "23.04.2025", "kod": "4634", "lek1": "APAP", "lek2": "Witamina B", "lek3": ""},    
            {"id": "2",  "data": "13.05.2025", "kod": "2913", "lek1": "Melatonina", "lek2": "", "lek3": ""},    
            {"id": "3",  "data": "30.10.2025", "kod": "1105", "lek1": "Witamina C", "lek2": "Calcium", "lek3": "Sinupret"}
        ]
    };
    
    function escapeHtml(text) {
        return text
            .replaceAll('&', '&amp;')
            .replaceAll('<', '&lt;')
            .replaceAll('>', '&gt;')
            .replaceAll('"', '&quot;')
            .replaceAll("'", '&#39;');
    }
    
    function prescriptionHtml(prescription) {
        let medicines = '';
        for (const medicine of [prescription.lek1, prescription.lek2, prescription.lek3]) {
            if (medicine !== '') {
                medicines += `<li>${escapeHtml(medicine)}</li>`;
            }
        }
    
        return `
            <div class="recepty">
                <p>Data wystawienia: ${escapeHtml(prescription.data)}</p>
                <ol>${medicines}</ol>
                <h4>Kod: ${escapeHtml(prescription.kod)}</h4>
            </div>`;
    }
    
    let html = '';
    for (const prescription of pacjenci.recepty) {
        html += prescriptionHtml(prescription);
    }
    document.querySelector('#prawa2').innerHTML = html;
    Podgląd strony po tym kroku (recepty.html)
  46. Etap 5: Porównanie z wersją podstawową

    Krok 46 · po tym etapie masz 40 z 40 kryteriów (pkt)

    Krok 46: Szablony a API DOM - którą drogę wybrać

    ok. 2 min

    Wszystkie trzy wersje dają komplet 40 punktów. Różnią się tym, jak skrypt buduje bloki:

    API DOM (podstawowa, nowoczesna)szablony tekstowe (ta wersja)
    tworzenie elementówcreateElement + appendChild/append dla każdego znacznikajeden napis HTML na blok
    czytelnośćstruktura rozbita na wiele liniiszablon wygląda jak docelowy HTML
    bezpieczeństwotextContent - tekst nigdy nie jest kodemescapeHtml przy każdej wartości - pominięcie jednej to luka
    wstawienieblok po blokujedno innerHTML na końcu

    Kiedy który sposób. Szablony są wygodne przy dużych, stałych fragmentach HTML (karta produktu, wiersz tabeli) - tak samo działają szablony w PHP, a biblioteki typu React czy Vue robią to z automatycznym escapowaniem. API DOM jest bezpieczniejsze domyślnie i lepsze, gdy elementy trzeba później zmieniać lub podpinać do nich zdarzenia. Na egzaminie klucz przyjmuje oba (R.5.5 - R.5.7 dopuszczają innerHTML); pamiętaj tylko, że innerHTML += w pętli przy dużej liczbie bloków jest wolne i kasuje zdarzenia przypięte wcześniej do elementów sekcji.

    Podgląd strony bez zmian - taki jak po kroku 45.

  47. Etap 6: Oddanie pracy

    Krok 47 · po tym etapie masz 40 z 40 kryteriów (pkt)

    Krok 47: Plik przeglądarka.txt i nagranie płyty

    ok. 5 min
    Polecenie z arkusza

    Po zakończeniu pracy utwórz plik tekstowy o nazwie przeglądarka.txt. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowana była poprawność działania witryny. Umieść go w folderze z numerem zdającego. Nagraj płytę z rezultatami pracy.

    W folderze z numerem zdającego: import.png, index.html, kw1.png … kw4.png, kwerendy.txt, lekarz.png, pacjent.png, przeglądarka.txt, recepta.png, recepty.html, skrypt.js, skierowania.html, styl.css. Bez skrypt.js sekcja recept zostanie pusta. Płytę sprawdź po nagraniu.

    przeglądarka.txt Tekst nowy plik
    Google Chrome

    Podgląd strony bez zmian - taki jak po kroku 45.

Podgląd

To jedno z możliwych rozwiązań. Egzaminator ocenia spełnienie kryteriów z klucza odpowiedzi, a nie zgodność z tym kodem - inna, poprawna droga też daje punkty.

Autor rozwiązania: . Licencja CC BY-NC 4.0 - kopiowanie i przeróbki do celów niekomercyjnych, z podaniem autora i źródła (link do tej strony) (zasady wykorzystania). Treść arkusza i klucza oceniania pochodzi z CKE.