Projekt Café Lóra nebudeme dělat úplně na zelené louce. Budeme vycházet z již připraveného základu, V tomto cvičení se seznámíme s tím, co všechno je pro nás připraveno a jakým způsobem budeme pracovat.
- Základ celé stránky, kterou budete postupně tvořit najdete v repozitáři cafelora. Pomocí Use this template si vytvořte kopii tohoto repozitáře na svém GitHubu a naklonujte si ji do svého počítače.
- Pro všechny projekty používající JSX nebo React platí, že po jejich naklonování nebo aktualizaci z GitHubu je potřeba spustit
npm install
. - Základní strukturu a design cílové stránky v JSX a CSS spolu s veškerými obrázky najdete v připraveném repozitáři. Poděkujte grafikům a kodérům, kteří pro vás tento návrh připravili a vy se už můžete zabývat pouze programováním.
- Seznamte se se zdrojovým kódem, který je pro vás v projektu připraven. Spusťte si web pomocí
npm run dev
. Prohlédněte si JSX a CSS obou stránek a vyzkoušejte si obě stránky zobrazit v prohlížeči. - Na stránkách najdete příklad nápojů a objednávky. Tato data samozřejmě budeme později stahovat z API, nyní jsou zde pouze jako ukázka.
Jako první budeme chtít rozsekat hlavní stránku index.jsx na následující komponenty:
Header
- hlavička stránky,Banner
- uvítací obrázek,Menu
- meníčko s nápoji,Gallery
- obrázek kavárny a texty,Contact
- kontakt a otvírací hodiny,Footer
- patička.
-
Ve složce
src
vytvořte složkucomponents
a v ní postupně vytvořte všechny výše zmíněné komponenty pro hlavní stránku. Rozsekejte JSX i CSS tak, aby každá komponenta měla vlastní styly i obrázky. Globální styly pro celou aplikaci najdete v souboruglobal.css
, ten ponechte beze změny. Styly komponent hlavní stránky najdete v souboruindex.css
. Souborindex.css
je strukturovaný tak, aby styly pro jednotlivé komponenty byly seskupené u sebe, nemusíte tak zoufale lovit styly po celém projektu. V souboruorder.css
jsou styly pro detail objednávky – ty zatím neřešte, detailem se budete zabývat až v druhé části projektu.Chceme dosáhnout toho, aby kód pro obsah hlavní stránky aplikace v
index.jsx
vypadal takto:document.querySelector('#root').innerHTML = render( <div className="page"> <Header /> <main> <Banner /> <Menu /> <Gallery /> <Contact /> </main> <Footer /> </div> );
-
Vyzkoušejte, že máte hotovou stránku, která vypadá stejně jako stránka ze zadání s funkční navigací. Proveďte commit s hezky popisnou zprávou a pushněte do vzdáleného repozitáře.
Jako další úkol rozchodíme zatím nefunkční navigaci a zařídíme, aby se na úzkých displejích navigace zobrazovala po kliknutí na hamburger ikonku.
- Nejdříve do těch komponent, které odpovídají odkazům v navigaci, přidejte attribut
id
. Atribut vložte přímo na<section/>
uvnitř dané komponenty. Tím zajistíte, aby odkazy v navigaci po kliknutí přesunuly uživatele na správnou část stránky. - Zobrazování a skrývání navigačního menu uděláme tak, že budeme prvku
.rollout-nav
přidávat nebo odebírat třídunav-closed
. V hlavnímindex.jsx
(ve složcepages
) vyberte ikonku.nav-btn
a připojte k ní posluchač událosticlick
. Tento posluchač bude přepínat třídunav-closed
na prvku.rollout-nav
. Klikáním na ikonku tak můžeme zobrazovat nebo skrývat navigaci. - Navigaci budeme chtít schovat i po kliknutí na odkaz uvnitř navigace. Připojte tedy další posluchač události přímo na prvek
.rollout-nav
. V posluchači události zařiďte, aby se navigace při kliknutí na libovolnou její položku schovala (tj. prvku.rollout-nav
přidáte třídunav-closed
, obdobně, jako v předchozím kroku při přepínání). - Jakmile je váš kód funkční, proveďte commit se zodpovědně napsanou zprávou a pushněte do vzdáleného repozitáře.
V komponentě Menu
máme příklad tří napojů zatím jako natvrdo vytvořené JSX. Budeme chtít mít každý nápoj v menu jako komponentu. Připravujeme se tím na to, abychom později mohli seznam nápojů zobrazovat stažením dat z API.
Vytvoříme komponentu Drink
, která zatím nebude mít funkční objednávací tlačítko a nebude ještě správně zobrazovat ingredience (layers). Obojí doplníme později.
-
Ve složce
components
vytvořte komponentuDrink
sindex.jsx
astyle.css
. Dostyle.css
přesuňte styly související s komponentou. -
V
index.jsx
vytvořte komponentuDrink
podle vzoru nápojů zMenu
. Připravte komponentu, aby očekávala props viz níže. Nebojte se použít destrukturování.<Drink id={0} name="Romano" ordered={false} image="http://localhost:4000/assets/cups/romano.png" layers={[ { color: '#fbdf5b', label: 'citrón', }, { color: '#613916', label: 'espresso', }, ]} />
-
Uvnitř JSX komponenty použijte pouze 2 ze seznamu props:
name
aimage
. První bude sloužit jako název nápoje, druhá jako adresa obrázku (atributsrc
). Ostatní props můžete zatím nechat nepoužité. -
Nyní máte komponentu připravenou. Vraťte se do komponenty
Menu
, smažte ukázkové příklady nápojů a místo nich použijte komponentuDrink
. Zatím na stránce klidně zobrazte pouze jeden nápoj, ať se moc nenadřete. PředejteDrink
props podle příkladu výše, nebo si vymyslete vlastní data, ať můžete otestovat, že komponenta funguje. (Nevadí že předáte všechny props, i když komponenta zatím používá jenomname
aimage
). -
Po předání props by komponenta měla minimálně správně zobrazovat vámi zadané jméno přes
name
a případně i obrázek, pokud jste např. použily adresu obrázku, který máte uložený u sebe na počítači. Adresa obrázku v příkladu nahoře využívá lokální API, které zatím nemáme zprovozněné, takže se vám tento obrázek zobrazovat nebude. -
Tlačítko objednání zatím pouze zobrazte, funkčnost mu přidáme později.
-
V této fázi si commitněte kód s užitečně napsanou commit zprávou a pushněte do vzdáleného repozitáře.
Abychom mohli vytvářet seznam ingrediencí podle dat, každá ingredience nápoje musí být také komponenta. Budeme postupovat obdobně jako u komponenty Drink
.
-
Ve složce
components
vytvořte komponentuLayer
. Podívejte se doDrink
na ukázkové JSX jednotlivých layers (ingrediencí) a podle něj vytvořte strukturu komponenty, která bude vracet JSX pro jednu ingredienci.Layer
bude očekávat props v následujícím tvaru, které na patřičných místech v JSX rovnou použijte.<Layer color="#feeeca" label="mléčná pěna" />
-
Do komponenty také přesuňte styly s ní související.
-
Hotovou komponentu použijte v komponentě
Drink
a nahraďte tak předchozí ukázkové příklady layers.Layer
předejte data pomocí props a otestujte, že váš projekt funguje. Commitněte kód s výborně napsanou commit zprávou a pushněte do vzdáleného repozitáře.
V tomto cvičení konečně zobrazíme celou nabídku nápojů, které si stáhneme z API.
- Nejdříve si naklonujte repozitář cafelora-api, kde najdete připravená data pro
apidroid
. Otevřete si repozitář v novém okně VS Code a spusťtenpx apidroid@latest
(pozor na přidanou část@latest
– to zajistí, aby se použila nejnovější verzeapidroid
, která je pro API Café Lóra potřeba). - Prohlédněte si data, která vrací endpoint
/api/drinks
. - Upravte hlavní stránku tak, aby stahovala seznam nápojů z API, zatím stačí do proměnné, kterou vypíšete do konzole.
- Komponentu
Menu
upravte tak, aby přijímala prop s názvemdrinks
. Skrz ni komponentě předejte stažený seznam nápojů a zobrazte uvnitř prvkudrinks-list
za využití komponentyDrink
. - Díky datům z API můžeme komponentě
Drink
předat reálná data a zprovoznit tak obrázky a ingredience. Adresu obrázku z API předáte přes propimage
. Nezapomeňte, že z API vám přijde pouze relativní cesta souboru, např./assets/cups/romano.png
, které musí předcházet url adresa, kde běží váš backend server, např.http://localhost:4000
. Pomocí interpolace řetězců složte správně URL adresu obrázku a použijte uvnitřsrc
. - Ingredience zobrazíte za využití prop
layers
a komponentyLayer
, která už také získá opravdová data. - Stránka by nyní měla zobrazovat všechny nápoje s obrázky i ingrediencemi. Commitněte se srozumitelnou zprávou a pushněte do vzdáleného repozitáře.
-
Nejdříve si všimněte, že data pro jeden nápoj obsahují vlastnost
ordered
, která udává, zda je nápoj zrovna objednaný či nikoliv. Toto je zároveň prop v komponentěDrink
. Upravte tuto komponentu tak, aby v závislosti na hodnotě této prop zobrazila na tlačíku text Objednat nebo Zrušit. -
Na objednávací tlačítko také přidejte třídu
.order-btn--ordered
v případě, že nápoj je objednaný. -
Prop
id
předejte atributudata-id
, který vložte na<form>
. -
V hlavním souboru
index.jsx
pověste pomocíquerySelectorAll
posluchač události na každý objednávací formulář v nápojích. Zatím při kliknutí na tlačítko vypište do konzoleid
nápoje, abyste si ověřili, že váš posluchač události pracuje se správným prvkem pole. Kid
se dostanete pomocí vlastnostidataset.id
. -
Samotné objednání nápoje provedete pomocí
PATCH
požadavku na API endpoint/api/drinks/:id
.:id
zde představuje dynamickou část URL, kam vložíteid
formuláře. Požadavek bude mít v těle JSON pole s objektem, tělo požadavku tedy bude vypadat takto:[{ op: 'replace', path: '/ordered', value: true }];
Proveďte tento požadavek pomocí
fetch
a zkontrolujte, že se vám v konzoli vypíše odpověď od API. Jakmile je váš kód funkční, proveďte refresh stránky, aby se vám zobrazila aktuální data. -
Vyzkoušejte si na stránce, že objednávání nápojů funguje.
-
Bonus: Pokud vám toto cvičení přišlo jako pohodička, zkuste si zprovoznit zrušení objednávky. Stačí upravit vlastnost
value
v body požadavku, aby místotrue
posílala opak předchozího stavu nápoje. Přístup kordered
stavu nápoje máte díky datům z předchozího GET requestu. Budete muset v poli se všemi nápoji najít nápoj, který odpovídáid
použitého formuláře. -
Commitněte váš kód se zodpovědně napsanou commit zprávou a pushněte do vzdáleného repozitáře.
Oživíme kostru stránky pro detail objednávky pomocí už existujících komponent. Komponenty pro jednotlivé položky objednávky vytvoříme v dalším cvičení.
- Ve složce
src/pages
najdete soubororder.html
i s JavaScriptemorder.jsx
a stylyorder.css
. - Na stránce použijte komponenty
Header
aFooter
. KomponentuHeader
bude potřeba upravit, protože na stránce s objednávkou se hlavička zobrazuje bez hlavního menu. Do komponentyHeader
tedy přidejte prop s názvemshowMenu
. Pokud budeshowMenu
mít hodnotutrue
, komponentaHeader
zobrazí celé menu, jako doposud. Pokud budefalse
, zobrazí hlavičku pouze s odkazem na hlavní stránku, jak je navrženo v zadání projektu v souboruorder.jsx
. - Vyzkoušejte, že váš web funguje a že se lze přesouvat mezi oběma stránkami.
- Proveďte commit a push vašich změn.
-
Ve složce
src/components
vytvořte komponentuOrder
pro zobrazení obsahu objednávky. Tato komponenta bude mít jedinou propitems
, která bude očekávat pole objednaných nápojů. Toto pole bude obsahovat objekty s následující strukturou:{ id: 7, name: 'Romano', image: 'http://localhost:4000/assets/cups/romano.png', }
-
Vytvořte také komponentu
OrderItem
s propsname
aimage
představující jednu položku objednávky. -
Na stránce se detailem objednávky získáte jednotlivé položky z objednávky tak, že pošlete GET požadavek na API endpoint
/api/drinks?filter=ordered:eq:true&select=id,name,image
Tato URL adresa obsahuje speciální parametry, které ze seznamu nápojů vyfiltrují pouze ty, které jsou objednané a vrátí pouze jejich
id
,name
aimage
. Pozor, že pokud nemáte zatím žádný nápoj objednaný, API endpoint vrátí prázdné pole. -
Pokud je objedávka prázdná, zobrazte příslušnou zprávu.
-
Vyzkoušejte, že stránka s detailem objednávky správně zobrazuje obsah objednávky. Zkuste na hlavní stránce změnit objednané nápoje a zkontrolujte, že se na stránce s detailem objednávky správně aktualizuje obsah.
-
Proveďte commit a push vašich změn.
Máte hotovo! Web Café Lóra ožil pod vašima rukama.