mirror of
https://github.com/Fluffy-Bean/TastyBites.git
synced 2025-01-29 17:48:28 +00:00
Increase hit target for dropdown
Add CartRecord type Remove OOP style Promises from Contact Add contact reason dropdown The usual SCSS changes and adjustments
This commit is contained in:
parent
865654de87
commit
c908a544aa
|
@ -6,12 +6,10 @@
|
|||
</script>
|
||||
|
||||
<div class="dropdown" class:open={open}>
|
||||
<div class="dropdown-header">
|
||||
<p>{name}</p>
|
||||
<button on:click={() => { open = !open }}>
|
||||
<CaretDown />
|
||||
</button>
|
||||
</div>
|
||||
<button class="dropdown-header" on:click={() => { open = !open }}>
|
||||
<span class="dropdown-text">{name}</span>
|
||||
<span class="dropdown-button"><CaretDown /></span>
|
||||
</button>
|
||||
<div class="dropdown-content">
|
||||
<slot></slot>
|
||||
</div>
|
||||
|
@ -28,6 +26,8 @@
|
|||
.dropdown-header {
|
||||
padding: $spacing-normal;
|
||||
|
||||
width: 100%;
|
||||
|
||||
position: relative;
|
||||
|
||||
display: flex;
|
||||
|
@ -35,12 +35,15 @@
|
|||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
p {
|
||||
border: 0 solid transparent;
|
||||
background-color: transparent;
|
||||
|
||||
.dropdown-text {
|
||||
font-size: $font-size-h6;
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
|
||||
button {
|
||||
.dropdown-button {
|
||||
padding: 0;
|
||||
|
||||
height: 100%;
|
||||
|
@ -62,9 +65,13 @@
|
|||
color: $color-on-light;
|
||||
|
||||
transition: transform 0.1s ease-in-out;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&:hover, &:focus-visible {
|
||||
.dropdown-button {
|
||||
color: $color-primary;
|
||||
outline: 0 solid transparent;
|
||||
transform: rotate(-15deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -76,11 +83,15 @@
|
|||
|
||||
&.open {
|
||||
.dropdown-header {
|
||||
//padding: $spacing-normal $spacing-normal $spacing-small;
|
||||
|
||||
button {
|
||||
.dropdown-button {
|
||||
transform: rotate(-180deg);
|
||||
}
|
||||
|
||||
&:hover, &:focus-visible {
|
||||
.dropdown-button {
|
||||
transform: rotate(calc(-180deg + 15deg));
|
||||
}
|
||||
}
|
||||
}
|
||||
.dropdown-content {
|
||||
display: block;
|
||||
|
|
|
@ -1,24 +1,23 @@
|
|||
import { type Writable, get, writable } from "svelte/store";
|
||||
|
||||
import { type CartItem, type Item } from "./types";
|
||||
import { type CartRecord, type CartItem, type Item } from "./types";
|
||||
import { getItemByUUID, postVerifyCart } from "./test-api";
|
||||
|
||||
function createCartStore() {
|
||||
let loaded = false;
|
||||
|
||||
const cart: Writable<Record<string, CartItem>> = writable({});
|
||||
const cart: Writable<CartRecord> = writable({});
|
||||
|
||||
async function init() {
|
||||
let localData: Record<string, CartItem> = {};
|
||||
async function init(): Promise<void> {
|
||||
let localData: CartRecord = {};
|
||||
try {
|
||||
localData = JSON.parse(localStorage.getItem("basket")) || {};
|
||||
} catch {
|
||||
console.error("Local Cart data fucked");
|
||||
console.error("Local Cart data could not be parsed");
|
||||
}
|
||||
|
||||
try {
|
||||
const newData: Record<string, CartItem> =
|
||||
await postVerifyCart(localData);
|
||||
const newData: CartRecord = await postVerifyCart(localData);
|
||||
cart.set(newData);
|
||||
} catch (error) {
|
||||
console.error("Could not load basket:", error);
|
||||
|
@ -28,18 +27,16 @@ function createCartStore() {
|
|||
}
|
||||
|
||||
async function addToCart(uuid: string, amount: number) {
|
||||
if (!loaded) {
|
||||
return;
|
||||
}
|
||||
if (!loaded) return;
|
||||
|
||||
if (get(cart)[uuid] !== undefined) {
|
||||
cart.update((cart: Record<string, CartItem>) => {
|
||||
cart.update((cart: CartRecord) => {
|
||||
cart[uuid].amount += amount;
|
||||
return cart;
|
||||
});
|
||||
} else {
|
||||
await getItemByUUID(uuid).then((data: Item) => {
|
||||
cart.update((cart: Record<string, CartItem>) =>
|
||||
cart.update((cart: CartRecord) =>
|
||||
Object.assign({}, cart, {
|
||||
[uuid]: { uuid, amount, data },
|
||||
})
|
||||
|
@ -47,13 +44,9 @@ function createCartStore() {
|
|||
});
|
||||
}
|
||||
|
||||
cart.update((cart: Record<string, CartItem>) => {
|
||||
if (cart[uuid].amount <= 0) {
|
||||
delete cart[uuid]; // skipcq: JS-0320
|
||||
} else if (cart[uuid].amount > 99) {
|
||||
cart[uuid].amount = 99; // skipcq: JS-0320
|
||||
}
|
||||
|
||||
cart.update((cart: CartRecord) => {
|
||||
if (cart.uuid.amount <= 0) delete cart.uuid;
|
||||
if (cart.uuid.amount > 99) cart.uuid.amount = 99;
|
||||
return cart;
|
||||
});
|
||||
}
|
||||
|
@ -82,12 +75,10 @@ function createCartStore() {
|
|||
return totalCartPrice;
|
||||
}
|
||||
|
||||
function removeByUUID(uuid: string) {
|
||||
if (!loaded) {
|
||||
return;
|
||||
}
|
||||
function removeByUUID(uuid: string): void {
|
||||
if (!loaded) return;
|
||||
|
||||
cart.update((cart) => {
|
||||
cart.update((cart: CartRecord) => {
|
||||
delete cart[uuid]; // skipcq: JS-0320
|
||||
return cart;
|
||||
});
|
||||
|
@ -110,7 +101,7 @@ const Cart = createCartStore();
|
|||
export const cartLoaded = Cart.init();
|
||||
|
||||
// Make sure to update localstorage on any changes
|
||||
Cart.subscribe((value) => {
|
||||
Cart.subscribe((value: CartRecord) => {
|
||||
localStorage.setItem("basket", JSON.stringify(value));
|
||||
});
|
||||
|
||||
|
|
|
@ -71,12 +71,14 @@ export async function getItemByUUID(uuid: string): Promise<Item> {
|
|||
export async function postContactEmail(
|
||||
name: string,
|
||||
email: string,
|
||||
reason: string,
|
||||
message: string
|
||||
): Promise<string> {
|
||||
await fakeDelay(200);
|
||||
|
||||
if (!name) throw new Error("Name missing");
|
||||
if (!email) throw new Error("Email missing");
|
||||
if (!reason) throw new Error("Reason missing");
|
||||
if (!message) throw new Error("Message missing");
|
||||
if (message.length < 150) throw new Error("Message FUCKED");
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@ export type CartItem = {
|
|||
data: Item;
|
||||
};
|
||||
|
||||
export type CartRecord = Record<string, CartItem>
|
||||
|
||||
export type JSONResponse = {
|
||||
data?: {
|
||||
item: Item[]; // Todo Make this not just item type
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { PaperPlaneRight, SealWarning, SealCheck } from "phosphor-svelte";
|
||||
import { PaperPlaneRight, SealWarning, SealCheck, CaretDown } from "phosphor-svelte";
|
||||
|
||||
import { postContactEmail } from "../lib/test-api";
|
||||
import { expandOnTyping } from "../lib/utils";
|
||||
|
@ -11,27 +11,28 @@
|
|||
|
||||
let name = "";
|
||||
let email = "";
|
||||
let reason = "";
|
||||
let message = "";
|
||||
|
||||
let nameValid = true;
|
||||
let emailValid = true;
|
||||
let reasonValid = true;
|
||||
let messageValid = false;
|
||||
|
||||
function validateName() { nameValid = name.length > 1 }
|
||||
function validateEmail() { emailValid = email.length > 1 }
|
||||
function validateReason() { reasonValid = reason != "" }
|
||||
function validateMessage() { messageValid = message.length > minMessageLength }
|
||||
|
||||
function onSubmit() {
|
||||
nameValid = true;
|
||||
emailValid = true;
|
||||
|
||||
formMessage = postContactEmail(name, email, message)
|
||||
.catch((error) => {
|
||||
validateName();
|
||||
validateEmail();
|
||||
validateMessage();
|
||||
throw error;
|
||||
});
|
||||
try {
|
||||
formMessage = postContactEmail(name, email, reason, message)
|
||||
} catch (error) {
|
||||
validateName();
|
||||
validateEmail();
|
||||
validateReason();
|
||||
validateMessage();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -96,13 +97,41 @@
|
|||
</div>
|
||||
|
||||
<div class="spacer half" />
|
||||
<!-- ToDo: Add dropdown for issue type, such as Technical, Order, Account, or other -->
|
||||
|
||||
<div class="form-element">
|
||||
<label class="form-label" for="reason">Contact Reason</label>
|
||||
<div class="select-container">
|
||||
<select
|
||||
bind:value={reason}
|
||||
on:blur={validateReason}
|
||||
on:input={validateReason}
|
||||
class="form-input"
|
||||
id="reason"
|
||||
name="reason"
|
||||
>
|
||||
<option value="general">General Enquiry</option>
|
||||
<option value="technical">Technical/Website</option>
|
||||
<option value="order">Order</option>
|
||||
<option value="booking">Booking</option>
|
||||
</select>
|
||||
<div class="select-arrow">
|
||||
<CaretDown />
|
||||
</div>
|
||||
</div>
|
||||
<span class="form-notice error">
|
||||
{#if !reasonValid}
|
||||
You must provide a reason for contact
|
||||
{/if}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="spacer half" />
|
||||
|
||||
<div class="form-element">
|
||||
<label class="form-label" for="message">Message</label>
|
||||
<textarea
|
||||
bind:value={message}
|
||||
on:input={validateMessage}
|
||||
on:blur={validateMessage}
|
||||
use:expandOnTyping
|
||||
rows="1"
|
||||
cols="50"
|
||||
|
@ -146,6 +175,37 @@
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
.select-container{
|
||||
width: max-content;
|
||||
position: relative;
|
||||
|
||||
> select {
|
||||
width: 200px;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
> .select-arrow {
|
||||
height: 100%;
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: $spacing-small;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
transition: transform 0.1s ease-in-out;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
> .select-arrow {
|
||||
transform: translateY(2px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 0 $spacing-normal;
|
||||
|
||||
|
|
|
@ -170,6 +170,10 @@
|
|||
margin-left: $spacing-normal;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
|
||||
> h2, p {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
#filter {
|
||||
|
@ -222,6 +226,10 @@
|
|||
#menu-list {
|
||||
margin-left: 0;
|
||||
margin-top: $spacing-normal;
|
||||
|
||||
> h2, p {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
font-family: $font-family;
|
||||
font-size: $font-size-p;
|
||||
|
||||
border: 1px solid rgba($color-dark, 0.2);
|
||||
border: 1px solid $color-light;
|
||||
border-radius: $border-radius-normal;
|
||||
background-color: $color-light;
|
||||
color: $color-on-light;
|
||||
|
|
Loading…
Reference in a new issue