Fiktivní webový projekt semestrálního kurzu React 1 JARO 2024, na kterém si procvičíme, co vše jsme se v Reactu naučili.
V praxi často začnete pracovat na projektu, na kterém už pracoval někdo před vámi. V tomto cvičení tomu nebude jinak a také začneme s projektem, který již obsahuje nějaký kód.
Nejprve si prohlédněte dopředu připravený design webu LeviExpress, ze kterého budeme vycházet. V připraveném designu najdete kromě úvodní stránky taky stránku s detailem jízdenky. Jde o statické stránky, které nemají žádnou funkčnost. Obsahují pouze HTML a CSS. Zdrojové kódy najdete v leviexpress-design (tento repositář si klonovat nemusíte, slouží hlavně pro inspiraci). Odsud můžete vzít všechny potřebné styly, HTML a obrázky pro váš projekt.
Vytvořte si repozitář ze šablony leviexpress-starter. V tomto repozitáři najdete již rozpracovaný základ aplikace.
Svůj repozitář si naklonujte do počítače a otevřete ve VS Code.
Nainstalujte všechny závislosti pomocí npm install
a spusťte projekt pomocí npm run dev
.
Prohlédněte si strukturu projektu a projděte si kód připravených komponent.
Hned na začátku rozběháme routování, abychom ho pak nemuseli složitě roubovat do již rozpracovaného projektu. Knihovna react-router
už je v naklonovaném projektu nainstalovaná, můžete ji rovnou začít používat.
Naše aplikace bude mít dvě hlavní stránky: Home a Reservation. Obě obsahují stejnou hlavičku i patičku. Stránka Home bude pod routou /
, stránka s detaily rezervace bude mít adresu /reservation
.
App
již máte připravenou strukturu s hlavičkou a patičkou stránky. Dále máte již hotovou kostru komponenty Home
. Sestavte router tak, aby komponenty Header
a Footer
byly na stránce zobrazeny vždy. Mezi ně vložte prvek RouterProvider
z React Routeru a předejte do něho konfigurační objekt, ve kterém budete mít vytvořené dvě routy: /
a /reservation
. V první routě zobrazte komponentu Home
, ve druhé zatím necháme jen nadpis h2
s textem "Detail jízdenky". Vyzkoušejte, že vaše stránka správně zobrazuje obě stránky. Odkazy (Link
) na stránku nedávejte – uživatel přijde vždy na hlavní stránku /
. Na stránku /reservation
se dostane až po kliknutí na tlačítko pro objednání, které zprovozníte až později.Reservation
. Tuto komponentu zobrazte na adrese /reservation
. Zatím může vracet pouze nadpis h2
, abychom viděli, že se na stránce něco děje. Obsah komponenty vytvoříme později./reservation
vyzkoušejte tak, že ji napíšete do adresního řádku prohlížeče).Ve svém projektu již máte vytvořen základy komponenty s názvem JourneyPicker
. Ta je součástí komponenty Home
a zatím vrací pouze statické JSX
JourneyPicker
si připravte funkci handleSubmit(event)
, která se bude volat při odeslání formuláře. Ošetřete, aby prohlížeč sám neodesílal formulář a zatím si ve funkci jen vypište do konzole text 'Odesílám formulář s cestou'
.handleSubmit
na událost submit ve formuláři. Ověřte v prohlížeči, že po kliknutí na Vyhledat spoj se v konzoli objeví výše uvedený text.useState
si v komponentě připravte tři stavy: fromCity
, toCity
a date
. Výchozí hodnotou bude ve všech třech případech prázdný řetězec ''
;<select>
tak, aby select
zobrazoval vybraný stav a změna v select
u se promítla do stavu. Vytvoříte tedy dvoucestný databinding, kdy se např. stav fromCity
bude promítat do value
příslušného select
u, a při události onChange
na select
u se nová hodnota zapíše do stavu fromCity
. Obdobně i pro další dva select
y a stavy toCity
a date
.handleSubmit
tak, aby do konzole vypsala všechny tři stavy. Vyzkoušejte, že výběrem stavu v select
u se změní stav – po kliknutí na tlačítko se do konzole vypíše změněný stav. Tím, že si dočasně změníte výchozí hodnotu v useState('')
na některou z hodnot (atribut value
) v <option>
můžete ověřit, že funguje správně nastavení výchozího stavu select
u.Na konci tohoto cvičení si uživatel bude schopen vybrat startovní a cílové město ze seznamu měst stažených z API. Vytvoříte komponentu CityOptions
, která dostane na vstupu pole se seznamem destinací a vytvoří z něj elementy <option>
do select
ů pro výběr výchozího a cílového města. Seznam měst se bude stahovat v komponentě JourneyPicker
z API endpointu /api/cities. Prohlédněte si strukturu dat, která endpoint vrací.
Přímo v souboru index.jsx
komponenty JourneyPicker
si vytvořte novou komponentu CityOptions
. Přesuňte do ní všechny <option>
ze select
u pro výběr výchozího města. Komponentu CityOptions
použijte v obou select
ech pro výběr města. Zkontrolujte, že v prohlížeči vše funguje stejně.
V komponentě JourneyPicker
si vytvořte pomocí useState
další stav cities
. V tomto stavu bude seznam měst, mezi kterými lze cestovat. Pro otestování nastavte do seznamu dvě města:
[
{ name: 'Praha', code: 'CZ-PRG' },
{ name: 'Brno', code: 'CZ-BRQ' },
];
Komponenta CityOptions
bude v props
přijímat cities
. V něm bude pole – seznam měst, které může uživatel vybrat. Upravte tedy příslušným způsobem hlavičku komponenty CityOptions
a získanou property cities
si vypište do konzole.
Na obou místech, kde máte komponentu CityOptions
použitou, nastavte property/atribut cities
na hodnotu stavu cities
. V prohlížeči se teď při zobrazení stránky vypíše dvakrát do konzole seznam měst – Praha a Brno.
Upravte komponentu CityOptions
tak, aby se na základě seznamu měst v property cities
vypsaly jednotlivé <option>
. Pro text option
se použije název destinace, jako hodnota (atribut value
) a také jako klíč pro React (key
) se použije kód destinace.
Nechceme, aby při zobrazení stránky byla rovnou vybraná první města ze seznamu. Proto před elementy option
vytvořené z pole ještě ručně vložíme jeden option
s textem „Vyberte“. Atribut value
tohoto option
bude prázdný.
Odstraňte z komponenty CityOptions
výpis do konzole a zkontrolujte v prohlížeči, že se v seznamu výchozích i cílových měst zobrazuje Praha a Brno a že stále správně funguje výběr měst.
Do hlavní komponenty JourneyPicker
přidejte useEffect
, který se bude volat při prvním zobrazení komponenty. Přesuňte do něj nastavení stavu cities
– naše dvě testovací města. Výchozí stav pro cities
tedy bude prázdné pole, teprve useEffect
nastaví seznam měst na Prahu a Brno. Ověřte v prohlížeči, že se v select
ech stále zobrazují obě města. Dejte pozor na to, aby se efekt volal opravdu jen při prvním zobrazení komponenty – můžete si to ověřit pomocným výpisem do konzole prohlížeče, který se musí objevit jen jednou – když budete překlikávat na jiná města, výpis už se nebude opakovat.
Upravte useEffect tak, že bude seznam měst získávat z API. Endpoint je na adrese
https://apps.kodim.cz/daweb/leviexpress/api/cities
a vrací seznam měst jako JSON ve formátu, který jsme použili výše. Získaná data použijte místo Prahy a Brna ve stavu cities
. Ověřte v prohlížeči, že se v seznamu měst objeví i další města.
Commitněte změny.
Na konci tohoto cvičení bude uživatel schopen vybrat datum cesty podle dat stažených z API. Budeme postupovat obdobně jako s komponentou CityOptions
. Tentokrát však vytvoříme komponentu DatesOptions
, která vygeneruje elementy option
do výběru termínů cesty. Termíny cest se budou získávat z API endpointu /api/dates. Prohlédněte si strukturu dat, která tento endpoint vrací.
Komponentu DatesOptions
vytvořte opět přímo v souboru s komponentami JourneyPicker
a CityOptions
.
HTML kód s elementy <option>
pro výběr termínu přesuňte ze select
u pro výběr data do komponenty DatesOptions
. V select
u použijte vytvořenou komponentu DatesOptions
. Zkontrolujte v prohlížeči, že se výběr termínů zobrazuje stále stejně.
Podobně jako CityOptions
získává seznam měst v property cities
, bude i DatesOptions
získávat seznam termínů v property dates
. V elementech <option>
(s výjimkou prvního ručně vloženého s textem „Vyberte“) použijte jako value
a key
hodnotu dateBasic
a jako hodnotu dateCs
použijte jako obsah.
Připravte si pomocí useState
další stav dates
. Pro otestování si do něj vložte tato data:
[
{
"dateBasic": "28.05.2021",
"dateCs": "pá 28. květen 2021"
},
{
"dateBasic": "29.05.2021",
"dateCs": "so 29. květen 2021"
}
]
Použijte stav dates
pro naplnění hodnot property dates
tam, kde je použita komponenta DatesOptions
. Ověřte v prohlížeči, že se ve výběru termínů zobrazují dvě uvedená data.
Upravte useEffect
volaný při prvním zobrazení komponenty. Vedle seznamu měst bude z API získávat také seznam termínů. Endpoint je na adrese
https://apps.kodim.cz/daweb/leviexpress/api/dates
a vrací seznam termínů ve formátu, který máme připraven. Změňte výchozí stav dates
na prázdné pole a poté do něj nastavte výsledek volání uvedeného endpointu.
Ověřte v prohlížeči, že se do select
ů načítají data (města a termíny) a že po kliknutí na tlačítko „Vyhledat spoj“ se uživatelem zvolené údaje vypíší do konzole prohlížeče.
Commitněte změny.
V tomto cvičení dokončíte komponentu pro vyhledání spojení. V komponentě už funguje výběr výchozího a cílového města a také data cesty. Nyní napojíte komponentu na API pro vyhledávání spojení.
Pokračujte v komponentě JourneyPicker
. Do tlačítka „Vyhledat spoj“ přidejte atribut disabled
tak, aby tlačítko bylo povolené pouze v případě, že jsou vybrána obě města i datum.
Při kliknutí na tlačítko „Vyhledat spoj“ se volá funkce handleSubmit
, která vypíše údaje zadané uživatelem. Nyní výpis do konzole nahradíte voláním API. Bude se volat následující API endpoint
https://apps.kodim.cz/daweb/leviexpress/api/journey?fromCity=…&toCity=…&date=…
Vytečkovaná místa se nahradí hodnotami vybranými uživatelem, které jsou uložené ve stavech fromCity
, toCity
a date
.
Volání tohoto API vrací JSON s nalezenými spoji. Vypište si výstup do konzole prohlížeče.
Nalezená spojení budeme potřebovat zobrazit v další komponentě na stránce. Potřebujeme je tedy poslat z komponenty JourneyPicker
jejímu rodiči – to uděláme v následujících krocích.
V komponentě Home
si připravte funkci handleJourneyChange
. Funkce handleJourneyChange
bude očekávat jeden parametr – objekt s údaji o nalezeném spojení. Nazvěte jej třeba journey
. Ve funkci zatím vypište tento parametr do konzole. Funkce se zatím nebude nikde volat – volání zajistíme v následujících krocích, kde bude funkce handleJourneyChange
sloužit jako callback předaný do komponenty JourneyPicker
.
V komponentě Home
používáte komponentu JourneyPicker
. Této komponentě předejte property jménem onJourneyChange
, jako hodnotu jí předejte funkci (callback) handleJourneyChange
.
V komponentě JourneyPicker
bude property onJourneyChange
, do které rodič (Home
) vkládá funkci, která se zavolá s údaji nalezeném spoji. Všimněte si, že v hlavičce komponenty JourneyPicker
už je property onJourneyChange
připravená.
Ve funkci handleSubmit
v komponentě JourneyPicker
máte nyní výpis nalezených spojení do konzole prohlížeče. Tento výpis nahraďte voláním funkce uložené v property onJourneyChange
, které jako paramter předáte data získaná z volání API pod klíčem results
.
Vraťte se do komponenty Home
, ze které se volá komponenta JourneyPicker
. V komponentě Home
vytvořte pomocí useState
nový stav journey
, výchozí hodnota bude null
.
Propojte komponentu JourneyPicker
se stavem journey
– když je volán callback handleJourneyChange
s údaji o nalezeném spoji, nastaví se toto spojení do stavu journey
.
Upravte komponentu Home
tak, aby v případě, kdy ve stavu journey
je nějaké spojení, vypsala pod vyhledávací formulář text „Nalezeno spojení s id …“. Místo tří teček bude journeyId
z dat o nalezeném spojení.
Ověřte, že funguje výběr měst a data, že po zadání všech třech údajů můžete kliknout na „Vyhledat spoj“ a že se po kliknutí vyhledá nějaké spojení a vypíše se do stránky jeho id.
Commitněte změny.
V tomto cvičení vytvoříte komponentu pro zobrazení detailu cesty a komponentu pro zobrazení zastávky. Využijí se informace, které vrátilo API pro vyhledání spoje.
JourneyDetail
zatím zkopírujte HTML kód ze zadání – celý element div
s třídami journey-detail
a container
i s jeho obsahem. Vytvořte v komponentě také soubor style.css
, do kterého zkopírujte ze zadání styly pro třídy stops
a journey-detail
. Naimportujte soubor se styly do komponenty.JourneyDetail
v komponentě Home
na místě, kde se nyní vypisuje id nalezeného spoje. Komponenta se bude zobrazovat jenom tehdy, když ve stavu journey
v komponentě Home
je něco jiného, než null
. Ověřte, že po vyhledání spojení se na stránce zobrazí podrobnosti cesty s městy 1 až 4.BusStop
. V komponentě vytvořte také soubor se styly, do kterého ze zadání zkopírujete všechny styly pro třídy začínající bus-stop
.BusStop
vložte ze zadání celý element div
, který má třídu bus-stop
. Je to jeden prvek ze seznamu zastávek.JourneyDetail
smažte HTML kód se seznamem zastávek. Zůstane tam jen kontejner, v něm h2
s textem „Podrobnosti cesty“ a pod ním div
s třídou stops
. Do tohoto divu vložte komponentu BusStop
. Zkontrolujte v prohlížeči, že se zobrazí jedna zastávka.BusStop
bude očekávat tři props – name
, station
a time
. Tam, kde používáte komponentu BusStop
, přidejte komponentě odpovídající atributy a nastavte jim hodnoty „Praha“, „ÚAN Florenc“ a „15:55“. Komponentu BusStop
upravte tak, aby se tyto hodnoty propsaly na správná místa v HTML. Zkontrolujte, že se v prohlížeči zobrazují správné údaje pro jednu zastávku.JourneyDetail
bude v props
očekávat property journey
s údaji o cestě. V property journey
bude objekt, který má v sobě v property stops
seznam zastávek. Property journey
si můžete vypsat do konzole prohlížeče.BusStop
použité v komponentě napište kód, který projde všechny zastávky v journey.stops
a pro každou zastávku vloží jednu komponentu BusStop
, které předá správné údaje. Můžete si pomoci tak, že nejprve upravíte vloženou komponentu BusStop
, ve které máte „Praha“, „ÚAN Florenc“ a „15:55“ tak, aby se místo těchto údajů vložily údaje z první zastávky v journey.stops[0]
a následně kód upravíte tak, aby pomocí funkce map
prošel všechny zastávky v journey.stops
. Jako klíč (key
) pro React můžete použít property code
, která je uvedená v journey.stops
u každé zastávky.Home
do komponenty JourneyDetail
údaje o cestě. Vraťte se do komponenty Home
. Ve stavu journey
tam jsou uloženy údaje o cestě. Nyní už jen stačí tento stav předat do prop journey
komponenty JourneyDetail
.V první fázi projektu bude sedadlo pro cestujícího přidělovat automaticky backend. Jistě jste si všimli, že API endpoint /journey
vrací JSON s vlastností autoSeat
. Tato vlastnost obsahuje automaticky vybrané volné sedadlo. V tomto cvičení jej zobrazíme uživateli na stránce.
SelectedSeat
. Její obsah vyplňte dle vzorové stránky. Všimněte si, že obrázek sedadla je vytvořen pomocí SVG.SelectedSeat
nastavit číslo sedadla skrze prop number
.number
měnit číslo sedadla.Home
máme ve stavu journey
uložen výsledek vyhledané cesty. Stačí tedy vlastnost autoSeat
předat komponentě SelectedSeat
. Dejte však pozor na to, že při načtení stránky je ve stavu journey
hodnota null
. V takovém případě komponentu SelectedSeat
vůbec nezobrazujte.Nyní již máme ve stavu journey
uložené všechny potřebné informace k tomu, abychom mohli provést rezervaci jízdenky. V tomto cvičení potvrdíme rezervaci kliknutím na tlačíko, zpracujeme odpověď ze serveru a přesměrujeme uživatele na detail rezervované jízdenky.
Vložte do komponenty Home
oddíl s tlačítkem „Rezervovat". Stále v komponentě Home
vytvořte funkci handleBuy
a zařiďte, aby byla tato funkce volána při kliknutí na tlačítko „Rezervovat". Ve funkci si zatím můžete vypsat nějakou zprávu do konzole ('Funguju!')
.
Podle dokumentace React Routeru se podívejte, jak lze pomocí hooku useNavigate
přímo v kódu změnit stránku, na které se uživatel nachází. Tedy jak uživatele přesměrovat.
Na začátku komponenty Home
vytvořte proměnnou navigate
s použitím hooku useNavigate()
, nezapomeňte hook naimportovat z react-router-dom
. Za moment tuto proměnnou použijeme.
Nákup jízdenky se ve funkci handleBuy
provede tak, že metodou POST zavoláte API endpoint
https://apps.kodim.cz/daweb/leviexpress/api/reservation
Tělo požadavku bude obsahovat akci create
, vlastnost seat
– číslo sedadla vybrané uživatelem, a vlastnost journeyId
– hodnota journeyId
ze stavu. Příklad:
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
action: 'create',
seat: journey.autoSeat,
journeyId: journey.journeyId,
}),
});
Volání tohoto API vrací JSON s daty, ze kterých nás bude zajímat hodnota reservationId
. Vypište si ji do konzole.
Pomocí funkce navigate
a hodnoty reservationId
přesměrujte uživatele na stránku detailu rezervace. Takové volání bude vypadat následovně:
navigate(`/reservation/${reservationId}`);
Zkontrolujte, že po kliknutí na tlačítko „Rezervovat" se stránka přesměruje například na adresu
http://localhost:8080/reservation/HAQBAQASf7M
kde záhy vytvoříme detail jízdenky!
V předešlé lekci jsme dospěli k vytvoření rezervace a získání reservationId
. K dokončení základní verze projektu tak stačí vytvořit detail pro jednu jízdenku a zobrazit její data.
App
připravte již existující komponentu na správné zpracování detailu jízdenky. Upravte path
v routeru tak, aby dynamicky zpracovávala :id
parametr. Výsledná path bude vypadat takto: path="/reservation/:id"
.Reservation
zkopírujte HTML kód ze zadání. Ze souboru reservation.html
převezměte element div
s třídou reservation
i s jeho obsahem.style.css
, do kterého zkopírujte ze zadání styly pro třídy začínající reservation
. Naimportujte soubor se styly do komponenty.useParams
hook z react-router-dom
. Uvnitř komponenty tento hook zavolejte a získejte z něj parametr id
. Příklad použití.useState
vytvořte nový stav reservation
, výchozí hodnota bude null
.useEffect
volaný při prvním zobrazení komponenty. Bude z API získávat podrobné informace o jedné jízdence. Endpoint je na adrese
https://apps.kodim.cz/daweb/leviexpress/api/reservation?id=…
kde tečky nahradí id
konkrétní jízdenky. Toto id
vezměte z vytvořené proměnné id
z useParams
hooku.setReservation
z useState
hooku nastavte do proměnné reservation
výsledek volání uvedeného endpointu.reservation.html
).reservation
. Nezapomeňte zobrazení dat podmínit tím, že stav reservation
nemá hodnotu null
, jinak bude prohlížeč hlásit chybu, že nelze číst z undefined
.V druhé fázi projektu zprovozníme výběr sedadla uživatelem.
V tomto cvičení vytvoříme komponentu zobrazující plánek autobusu se sedadly. Obsazená sedadla budou zobrazena šedě a nepůjde na ně kliknout. API vrací seznam sedadel po řadách – nemusíte tedy řešit rozmístění sedadel. Zobrazíte jednoduše každou řadu zvlášť a v ní sedadla zleva doprava.
SelectedSeat
. V této verzi projektu už ji nebudeme potřebovat. Sedadlo vybereme z plánku.SeatPicker
a přidejte styly pro třídy seat-picker
a seats
ze zadání projektu. Do komponenty SeatPicker
zkopírujte ze zadání celý div
s třídami seat-picker
a container
. Obsah div
u seats
nechte však prázdný.SeatPicker
do komponenty Home
tam, kde před tím byla komponenta SelectedSeat
. Bude tak umístěna pod JourneyDetail
. Komponentu budeme chtít zobrazit jen v případě, kdy stav journey
neobsahuje null
. Pro vývoj komponenty ale nyní bude rychlejší, když se prozatím bude zobrazovat stále.Seat
představující jedno sedadlo v autobusu. Sedadlo je vytvořeno pomocí SVG, které najdete v zadání projektu. Do komponenty Seat
přidejte všechny styly týkající se jednoho sedadla.Seat
bude mít zatím jednu prop s názvem number
, ve které bude číslo sedadla.SeatPicker
pár sedadel s různými čísly, například 1, 17 a 33. Zatím jen tak pod sebe, abychom si vyzkoušeli, že je vůbec dokážeme správně zobrazit.Nyní zařídíme zobrazování sedadel v řadách. Plánek sedadel bude vypadat tak, že v HTML bude pro každou řadu sedadel jedna komponenta SeatRow
a teprve uvnitř této komponenty budou jednotlivá sedadla – komponenty Seat
.
V projektu vytvořte komponentu SeatRow
, která představuje jednu řadu sedadel. Bude vracet div
s třídou seat-row
, který v dalších krocích naplníme sedadly tak, jak nám přijdou z API. Zatím do komponenty natvrdo vložte pár sedadel jen pro testovací účely. Komponentu SeatRow
pak vložte do div
u seats
v komponentě SeatPicker
.
Komponenta SeatRow
bode očekávat prop s názvem row
, ve které budou data pro jednu řadu sedadel. Pro testovací účely si vytvořte proměnnou testRow
, která bude obsahovat takovýto objekt.
const testRow = [
{
number: 33,
isOccupied: false,
},
{
number: 29,
isOccupied: true,
},
{
number: 25,
isOccupied: false,
},
];
Předejte tuto proměnou komponentě SeatRow
a uvnitř ní pomocí funkce map
zobrazte jednotlivá sedadla. Jako key
prop u jednotlivých sedadel můžete použít samotné číslo sedadla.
Nyní máme vše připraveno pro zobrazení správného plánku sedadel podle dat z API. Pracovat budeme v komponentě SeatPicker
– tam, kde máme testovací řadu sedadel. Když se podíváte do konzole na výpis objektu uloženého ve stavu journey
komponenty Home
, uvidíte, že máte velké štěstí. Ve vlastnosti seats
je pole, které představuje přímo jednotlivé řady v autobusu.
Nyní je tedy potřeba údaje o sedadlech předat z komponenty Home
do komponenty SeatPicker
. Zároveň se bude později hodit i identifikátor spoje. Do komponenty SeatPicker
tedy přidejte dvě props – seats
(vloží se do ní journey.seats
) a journeyId
(sem přijde journey.journeyId
).
Ještě je potřeba upravit komponentu Home
tak, aby komponenta SeatPicker
byla vidět jedině v případě, že je stav journey
jiný než null
– tedy stejně, jako se zobrazuje komponenta JourneyDetail
. Ověřte v prohlížeči, že po vyhledání spoje se zobrazí podrobnosti cesty a také komponenta pro výběr sedadel – zatím s vašimi testovacími sedadly.
Uvnitř komponenty SeatPicker
projděte pole seats
pomocí funkce map
, a pro každý řádek pole vytvořte jednu komponentu SeatRow
. I komponenty SeatRow
potřebují prop key
. Zde bohužel nemáme žádnou rozumnou datovou položku, kterou bychom jako klíč mohli použít. Vzpomeňme si však, že funkce vložená do funkce map
může mít dva parametry, druhý parametr je pořadové číslo (takzvaný index) aktuálního prvku. V tomto případě jej výjimečně můžeme použít jako key
pro SeatRow
.
Pokud jste všechno zařídili správně, měli byste po vyhledání cesty vidět sedadla rozmístěná stejně jako ve vzorovém designu stránky. V tuto chvíli už nám stačí pouze správně zobrazit zabraná sedadla. Zda je sedadlo zabrané udává vlastnost isOccupied
v datech z API. Stačí tedy komponentě Seat
přidat prop isOccupied
a poslat do ní hodnotu obdrženou z API.
Uvnitř komponenty Seat
zařiďte, aby se na element svg
přidala CSS třída seat--occupied
ve chvíli, kdy je sedadlo zabrené.
Pokochejte se krásným plánkem sedadel a commitněte změny.
Když už dokážeme zobrazit plánek autobusu, je na čase zobrazit vybrané sedadlo. Zde bude potřeba hodně komunikace směrem od rodiče k dítěti.
Seat
tak, aby správně zobrazovala vybrané sedadlo. Přidáme jí tedy novou prop isSelected
. Pokud je sedadlo vybrané (prop isSelected
je nastavena na true
), bude mít sedadlo nastavenu vedle seat
také třídu seat--selected
.SeatRow
budeme nyní potřebovat prop rowSelectedSeat
, do které vložíme číslo vybraného sedadla. Na komponentách Seat
uvnitř SeatRow
pak změníme atribut isSelected
. Místo statické hodnoty true
nebo false
nastavujte jeho hodnotu v závislosti na tom, zda číslo sedadla je shodné s číslem v prop rowSelectedSeat
.SeatRow
vzít číslo vybraného sedadla? Získá jej od rodiče SeatPicker
. Do komponenty SeatPicker
tedy přidejte prop s názvem selectedSeat
. Hodnotu v této proppak předejte komponentám
SeatRowjako
rowSelectedSeat`.selectedSeat
komponenty SeatPicker
můžete nastavit libovolné sedadlo jako vybrané.autoSeat
z backendu.Nyní jsme ve stavu, kdy uživatel vidí automaticky vybrané sedadlo přímo na plánku autobusu.
V předchozí verzi projektu jsme sedadlo pro rezervaci získali z hodnoty autoSeat
stavu journey v komponentě Home
. Nyní však sedadlo bude vybírat uživatel. Potřebujeme tedy nový stav v komponentě Home
. Zde si užijeme hodně komunikace od potomka k předkovi.
Home
vytvořte nový stav s názvem userSeat
. Jeho hodnota bude na začátku null
.handleJourneyChange
tak nastavte stav userSeat
na hodnotu autoSeat
, která přišla ze serveru při výběru cesty.userSeat
pošlete do prop selectedSeat
komponenty SeatPicker
.Seat
přidejte prop onSelect
. V této prop bude funkce, kterou Seat
zavolá, když uživatel vybere sedadlo. Jako parametr této funkci předejte číslo sedadla.userSeat
při kliknutí na komponentu Seat
, která je ovšem zanořena v hlubinách komponenty SeatPicker
. Mezi komponentami Seat
a Home
je vztah potomek - pra-prarodič. Komunikace mezi nimi tedy musí probíhat skrze komponenty SeatRow
a SeatPicker
.SeatPicker
i SeatRow
musí mít proto prop onSeatSelected
. Komponenta SeatRow
tuto funkci předá všem svým Seat
jako prop onSelect
. Komponenta SeatPicker
funkci onSeatSelected
předá dolů komponentě SeatRow
skrze stejnojmennou prop. Takto můžeme z prarodiče SeatPicker
propašovat funkci do vnuka Seat
.SeatPicker
skrze prop onSeatSelected
předat funkci setUserSeat
, která nastaví stav v komponentě Home
. Pokud se povedlo vše správně propojit, při kliknutí na sedadlo se změní stav userSeat
v komponentě Home
a plánek zobrazí vybrané sedadlo. Vyzkoušejte v prohlížeči, že vše správně funguje.autoSeat
použít stavu userSeat
.