Rezervační formulář

Výběr míst má teď pod souhrnem svůj formulář: textová pole Jméno a E-mail a tlačítko Rezervovat, převedené do JSX (z for se v něm stalo htmlFor a z novalidate noValidate). Oživte ho jako v lekci Formuláře: textová pole jsou řízená, se stavy jmeno a email, a při odeslání formulář zavolá funkci odesli, která začne voláním event.preventDefault().

Kontrola. Potom funkce odesli formulář zkontroluje, jednu věc po druhé, jako ve cvičení Chybové zprávy: prázdné jméno, e-mail bez @, žádné vybrané místo. První problém uloží do stavu chyba, který formulář ukáže, a return funkci ukončí, takže se nic nezarezervuje. Návštěvník problém opraví a klikne na Rezervovat znovu. Stará stránka ukazovala všechny tři zprávy najednou. Tady je zpráva vždy jen jedna, pod tlačítkem, a kód je kratší.

Rezervace. Když je všechno v pořádku, výběr vytvoří vstupenku: objekt s id z Date.now(), představením, místy, jménem a e-mailem. Kam ale patří? Vstupenky potřebuje výběr míst, aby ukázal zarezervovaná místa jako obsazená, a seznam Vaše vstupenky v komponentě Program. Patří tedy do stavu komponenty Program, vstupenky, a výběr je dostane v props spolu s funkcí, která přidá novou, stejně jako formulář pro vlastní slovíčka v závěrečném projektu kurzu Reactu:

onRezervovat({
    id: Date.now(),
    predstaveni: predstaveni,
    mista: vybrana,
    jmeno: jmeno.trim(),
    email: email.trim(),
});

Vstupenka si drží celé představení, aby seznam mohl ukázat jeho den, čas a film. Pak výběr vyprázdní vybrana i obě textová pole. Zarezervovaná místa jsou od té chvíle obsazená: jeObsazene() navíc pomocí some() zjistí, jestli místo nemá některá vstupenka na toto představení, jako to dělal starý skript:

return vstupenky.some(
    (vstupenka) =>
        vstupenka.predstaveni.id === predstaveni.id &&
        vstupenka.mista.includes(misto),
);

Nakonec výběr napíše, která místa jsou zarezervovaná: Rezervováno! Vaše místa: A3, A4. Ten text bude v dalším stavu, potvrzeni. Místa do něj můžete vzít z vybrana, i když setPotvrzeni() zavoláte až po setVybrana([]): jak víte z lekce Stav, nová hodnota přijde až s dalším vykreslením.

Pokyny

  1. V komponentě VyberMist přidejte stavy jmeno, email a chyba, všechny na začátku "", a udělejte z obou textových polí řízená. Formuláři dejte onSubmit={odesli}. Funkce odesli(event) zavolá event.preventDefault() a pak kontroluje: když je jméno prázdné (jmeno.trim() === ""), nastaví chyba na Zadejte své jméno. a skončí. Stejně tak když e-mail nemá @ (Zadejte platnou e-mailovou adresu.) a když není vybrané žádné místo (Vyberte aspoň jedno místo.). Pod tlačítko dejte chybu v <p className="mt-4 text-sm text-red-700">, když nějaká je. Klikněte na Rezervovat s prázdnými textovými poli.

  2. V komponentě Program přidejte stav vstupenky, prázdné pole, a funkci pridejVstupenku(vstupenka), která vstupenku přidá na konec vstupenky aktualizační funkcí: setVstupenky((vstupenky) => [...vstupenky, vstupenka]). Dejte výběru props vstupenky={vstupenky} a onRezervovat={pridejVstupenku}. V komponentě VyberMist obě props převezměte a v odesli, když je všechno v pořádku, nastavte chyba zpátky na "", zavolejte onRezervovat() jako výše a vyprázdněte vybrana i obě textová pole. Ať jeObsazene() kontroluje i vstupenky, jako výše. Zarezervujte místo: zešedne.

  3. Po rezervaci uložte do nového stavu potvrzeni text Rezervováno! Vaše místa: A3, A4, s místy z vybrana.join(", "), a ukažte ho pod formulářem v <p className="mt-4 font-semibold text-green-700">. Do seznamu Vaše vstupenky (jeho sekce s nadpisem je v komponentě Program hotová) dejte pro každou vstupenku li s klíčem, třídami rounded-lg border border-stone-200 bg-white px-4 py-2 a textem Pátek 17:30, Roboti na dovolené: A3, A4, sestaveným ze vstupenka.predstaveni a vstupenka.mista.join(", ").