Start on Booking form

Clean up navigation bar
Form CSS
Add warning to run when skipping migrations
This commit is contained in:
Michał 2024-05-10 14:46:53 +01:00
parent 5cce507c8a
commit 3198dec20c
9 changed files with 181 additions and 38 deletions

View file

@ -34,6 +34,8 @@ func run(flags []string) {
fmt.Println("Run `TastyBites status` or use the flag -skipMigrations") fmt.Println("Run `TastyBites status` or use the flag -skipMigrations")
os.Exit(1) os.Exit(1)
} }
} else {
fmt.Println("WARNING: Skipping migrations! This can lead to errors, or even data loss!")
} }
api.Serve(api.Config{ api.Serve(api.Config{

View file

@ -1,17 +1,18 @@
<script> <script>
import Router, { replace, link } from 'svelte-spa-router'; import Router, { replace, link } from 'svelte-spa-router';
import active from 'svelte-spa-router/active' import active from 'svelte-spa-router/active'
import { TwitterLogo, FacebookLogo, InstagramLogo, TiktokLogo } from 'phosphor-svelte'; import { House, BookOpenText, Envelope, CalendarDots, Basket, TwitterLogo, FacebookLogo, InstagramLogo, TiktokLogo } from 'phosphor-svelte';
import Cart, { cartLoaded } from './lib/cart'; import Cart, { cartLoaded } from './lib/cart';
import routes from './routes'; import routes from './routes';
import Logo from '/assets/LogoAlt.svg'; import Logo from '/assets/LogoAlt.svg';
import Spinner from '/spinner.svg';
const links = { const links = {
home: {path: '/', className: 'active'}, home: {path: '/', className: 'active'},
menu: {path: '/menu', className: 'active'}, menu: {path: '/menu', className: 'active'},
about: {path: '/about', className: 'active'},
contact: {path: '/contact', className: 'active'}, contact: {path: '/contact', className: 'active'},
booking: {path: '/booking', className: 'active'},
cart: {path: '/cart', className: 'active'}, cart: {path: '/cart', className: 'active'},
} }
@ -61,43 +62,41 @@
{#if showNavBar } {#if showNavBar }
<nav class:scrolled={scrollY > 0} class:mobile={width < 700}> <nav class:scrolled={scrollY > 0} class:mobile={width < 850}>
{#if !(width < 700)} {#if !(width < 850)}
<ul style="justify-content: flex-end"> <ul style="justify-content: flex-end">
<li use:active={links.home}><a href="/" use:link>Home</a></li> <li use:active={links.home}><a href="/" use:link>Home</a></li>
<li use:active={links.menu}><a href="/menu" use:link>Menu</a></li> <li use:active={links.about}><a href="/about" use:link>About</a></li>
<li use:active={links.contact}><a href="/contact" use:link>Contact</a></li>
</ul> </ul>
<span class="nav-logo"><img src={Logo} alt="TastyBites"></span> <span class="nav-logo"><img src={Logo} alt="TastyBites"></span>
<ul style="justify-content: flex-start"> <ul style="justify-content: flex-start">
<li use:active={links.contact}><a href="/contact" use:link>Contact&nbsp;Us</a></li> <li use:active={links.menu}><a href="/menu" use:link>Menu</a></li>
<li use:active={links.booking}><a href="/booking" use:link>Booking</a></li>
<li use:active={links.cart}> <li use:active={links.cart}>
<a href="/cart" use:link> <a href="/cart" use:link>
Cart&nbsp;&nbsp; Cart&nbsp;&nbsp;
<span class="nav-basket"> <span class="nav-basket">
{#await cartLoaded} {#await cartLoaded then _}{cartItemCount}{/await}
<img src={Spinner} alt="Cart Loading">
{:then _}
{cartItemCount}
{/await}
</span> </span>
</a> </a>
</li> </li>
</ul> </ul>
{:else} {:else}
<ul> <ul>
<li use:active={links.home}><a href="/" use:link>Home</a></li> <li use:active={links.home}><a href="/" use:link><House weight="fill" /></a></li>
<li use:active={links.menu}><a href="/menu" use:link>Menu</a></li> <li use:active={links.contact}><a href="/contact" use:link><Envelope weight="fill" /></a></li>
<li use:active={links.contact}><a href="/contact" use:link>Contact&nbsp;Us</a></li> <li use:active={links.menu}><a href="/menu" use:link><BookOpenText weight="fill" /></a></li>
<li use:active={links.booking}><a href="/booking" use:link><CalendarDots weight="fill" /></a></li>
<li use:active={links.cart}> <li use:active={links.cart}>
<a href="/cart" use:link> <a href="/cart" use:link>
Cart&nbsp;&nbsp; {#await cartLoaded then _}
<span class="nav-basket"> {#if cartItemCount === 0}
{#await cartLoaded} <Basket weight="fill" />
<img src={Spinner} alt="Cart Loading"> {:else}
{:then _} <span class="nav-basket">{cartItemCount}</span>
{cartItemCount} {/if}
{/await} {/await}
</span>
</a> </a>
</li> </li>
</ul> </ul>

View file

@ -1,10 +1,10 @@
<script lang="ts"> <script lang="ts">
import { onMount } from "svelte";
import { link } from 'svelte-spa-router'; import { link } from 'svelte-spa-router';
import { Acorn, Fish, Leaf, Pepper, ArrowUpRight, GrainsSlash } from 'phosphor-svelte'; import { Acorn, Fish, Leaf, Pepper, ArrowUpRight, GrainsSlash } from 'phosphor-svelte';
import { type Item, Labels} from "../lib/types"; import { type Item, Labels} from "../lib/types";
import LoadingImage from '/assets/MenuItemLoadingAlt.svg'; import LoadingImage from '/assets/MenuItemLoadingAlt.svg';
import {onMount} from "svelte";
export let item: Item; export let item: Item;

View file

@ -17,8 +17,7 @@ function createCartStore() {
} }
try { try {
const newData: Record<string, CartItem> = const newData: Record<string, CartItem> = await postVerifyCart(localData);
await postVerifyCart(localData);
cart.set(newData); cart.set(newData);
} catch (error) { } catch (error) {
console.error("Could not load basket:", error); console.error("Could not load basket:", error);

View file

@ -61,21 +61,21 @@ Example
`, `,
labels: [Labels.nut], labels: [Labels.nut],
}, },
{ // {
uuid: "gwagwa", // uuid: "gwagwa",
availability: false, // availability: false,
name: "GwaGwa", // name: "GwaGwa",
price: 69, // price: 69,
labels: [Labels.nut], // labels: [Labels.nut],
images: ["/item_images/dab.jpg"], // images: ["/item_images/dab.jpg"],
}, // },
{ {
uuid: "hogmelon", uuid: "hogmelon",
availability: true, availability: true,
name: "Hogermellon", name: "Hogermellon",
price: 1111, price: 1111,
description: ` description: `
This is a sample description. Gay Balls. This is a sample description.
Contains the following: Contains the following:
- hog - hog
@ -92,7 +92,7 @@ Contains the following:
description: ` description: `
This is a sample description. This is a sample description.
Gay Balls Blue Hog
`, `,
labels: [Labels.nut, Labels.gluten, Labels.spicy], labels: [Labels.nut, Labels.gluten, Labels.spicy],
images: ["/item_images/sonichog.jpg"], images: ["/item_images/sonichog.jpg"],

View file

@ -1 +1,135 @@
<script lang="ts">
import { expandOnTyping } from "../lib/utils";
const specialRequestsMax = 300;
let name = "";
let email = "";
let telephone = "";
let specialRequests = "";
let nameValid = true;
let emailValid = true;
let telephoneValid = true;
let specialRequestsValid = true;
function validateName() {
nameValid = name.length > 1
}
function validateEmail() {
emailValid = email.length > 1
}
function validateTelephone() {
telephoneValid = telephone.length == 11
}
function validateSpecialRequests() {
specialRequestsValid = specialRequests.length < 301
}
function onSubmit(event) {
}
</script>
<h1>Table booking</h1> <h1>Table booking</h1>
<form on:submit|preventDefault={onSubmit}>
<div class="form-element">
<label class="form-label" for="name">Full Name</label>
<input
bind:value={name}
on:blur={validateName}
on:input={validateName}
type="text"
id="name"
name="name"
class="form-input"
/>
{#if !nameValid}
<span class="form-notice error">Enter a name</span>
{/if}
</div>
<div class="spacer half" />
<div class="form-element">
<label class="form-label" for="email">Email</label>
<input
bind:value={email}
on:blur={validateEmail}
on:input={validateEmail}
type="text"
id="email"
name="email"
class="form-input"
/>
{#if !emailValid}
<span class="form-notice error">Email not valid</span>
{/if}
</div>
<div class="spacer half" />
<div class="form-element">
<label class="form-label" for="email">Telephone</label>
<input
bind:value={telephone}
on:blur={validateTelephone}
on:input={validateTelephone}
type="text"
id="telephone"
name="telephone"
class="form-input"
/>
{#if !telephoneValid}
<span class="form-notice error">Telephone number not valid</span>
{/if}
</div>
<div class="spacer half" />
<hr>
<div class="spacer" />
<hr>
<div class="spacer half" />
<div class="form-element">
<label class="form-label" for="message">Message</label>
<textarea
bind:value={specialRequests}
on:input={validateSpecialRequests}
on:blur={validateSpecialRequests}
use:expandOnTyping
rows="1"
cols="50"
id="message"
name="message"
class="form-input"
/>
<span class="form-notice" class:error={!specialRequestsValid}>
({specialRequests.length}/{specialRequestsMax})
</span>
</div>
</form>
<style lang="scss">
@import "../styles/vars";
#name, #email {
width: 300px;
max-width: calc(100vw - calc(2 * $spacing-normal));
}
#telephone {
width: 180px;
max-width: calc(100vw - calc(2 * $spacing-normal));
}
#message {
min-width: 250px;
max-width: calc(100vw - calc(2 * $spacing-normal));
resize: none;
overflow: hidden;
}
</style>

View file

@ -20,9 +20,11 @@
function validateName() { function validateName() {
nameValid = name.length > 1 nameValid = name.length > 1
} }
function validateEmail() { function validateEmail() {
emailValid = email.length > 1 emailValid = email.length > 1
} }
function validateMessage() { function validateMessage() {
messageValid = message.length > minMessageLength messageValid = message.length > minMessageLength
} }
@ -67,9 +69,11 @@
{#await formMessage then formMessage} {#await formMessage then formMessage}
{#if formMessage} {#if formMessage}
<p class="form-message success"><SealCheck weight="fill" />&nbsp;{formMessage}</p> <p class="form-message success"><SealCheck weight="fill" />&nbsp;{formMessage}</p>
<div class="spacer half" />
{/if} {/if}
{:catch error} {:catch error}
<p class="form-message error"><SealWarning weight="fill" />&nbsp;{error.message}</p> <p class="form-message error"><SealWarning weight="fill" />&nbsp;{error.message}</p>
<div class="spacer half" />
{/await} {/await}
<div class="form-element"> <div class="form-element">
@ -88,6 +92,8 @@
{/if} {/if}
</div> </div>
<div class="spacer half" />
<div class="form-element"> <div class="form-element">
<label class="form-label" for="email">Email</label> <label class="form-label" for="email">Email</label>
<input <input
@ -104,6 +110,7 @@
{/if} {/if}
</div> </div>
<div class="spacer half" />
<!-- ToDo: Add dropdown for issue type, such as Technical, Order, Account, or other --> <!-- ToDo: Add dropdown for issue type, such as Technical, Order, Account, or other -->
<div class="form-element"> <div class="form-element">
@ -123,6 +130,8 @@
</span> </span>
</div> </div>
<div class="spacer" />
<button type="submit">Submit&nbsp;&nbsp;<PaperPlaneRight weight="fill" /></button> <button type="submit">Submit&nbsp;&nbsp;<PaperPlaneRight weight="fill" /></button>
</form> </form>

View file

@ -20,13 +20,14 @@
@media only screen and (max-width: 670px) { @media only screen and (max-width: 670px) {
.announcement-banner { .announcement-banner {
margin: -$spacing-small; margin: -$spacing-normal;
margin-bottom: 0; margin-bottom: 0;
//border-radius: 0; border-radius: 0;
img { img {
height: 250px; height: 250px;
//aspect-ratio: 16 / 9; //aspect-ratio: 16 / 9;
aspect-ratio: unset;
} }
} }
} }

View file

@ -1,5 +1,4 @@
.form-element { .form-element {
margin-bottom: $spacing-normal;
width: fit-content; width: fit-content;
overflow: hidden; overflow: hidden;
} }