Move to key-value basket, to keep track of information easier

Clean up code, add more types
Clean up error handling
This commit is contained in:
Michał Gdula 2024-05-03 18:35:39 +01:00
parent ec2ef95cca
commit 7066cc492b
7 changed files with 196 additions and 138 deletions

View file

@ -1,86 +1,84 @@
import type { Writable } from "svelte/store";
import { get, writable } from "svelte/store";
import type { Item, CartItem } from './types';
import { type CartItem } from './types';
import { getItemByUUID, postVerifyCart } from "./test-api";
// Load content from localstorage
let local: CartItem[] = [];
let local: Record<string, CartItem> = {};
try {
let verified = await postVerifyCart(
JSON.parse(localStorage.getItem("basket")) || []
);
if (verified instanceof Error) {
throw new Error("Bruh");
}
local = <CartItem[]>verified;
await postVerifyCart(JSON.parse(localStorage.getItem("basket")))
.then((data: Record<string, CartItem>) => {
local = data;
console.log(data);
})
.catch((error) => {
throw error; // Hot potato style
});
} catch {
console.error("Failed to load cart")
}
// Store function
function createCartStore() {
const cart = writable(local);
const cart: Writable<Record<string, CartItem>> = writable(local);
async function addToCart(uuid: string, amount: number) {
let found = false;
get(cart).forEach((item: CartItem) => {
if (item.uuid === uuid) {
item.amount += amount;
found = true;
}
});
if (!found) {
let cartData: Item;
try {
let data: Item | Error = await getItemByUUID(uuid);
if (data instanceof Error) {
return;
}
cartData = <Item>data;
} finally {
const newItem: CartItem = {
uuid: uuid,
amount: amount,
data: cartData,
};
cart.update((cart: CartItem[]) => [...cart, newItem]);
}
if (get(cart)[uuid] !== undefined) {
cart.update((cart: Record<string, CartItem>) => {
cart[uuid].amount += amount;
return cart;
});
} else {
await getItemByUUID(uuid)
.then((data) => {
cart.update((cart: Record<string, CartItem>) =>
Object.assign({}, cart, {[uuid]: {
uuid: uuid,
amount: amount,
data: data,
}})
)
});
}
// Remove items that have an amount of 0 or lower
cart.update((cart) => cart.filter((item) => item.amount > 0))
}
function getUniqueLength() {
return get(cart).length;
function getEntries(): [string, CartItem][] {
return Object.entries(get(cart));
}
function getTotalLength() {
let amounts = get(cart).map((item) => item.amount);
return amounts.reduce((a, b) => a + b, 0);
function getUniqueLength(): number {
return Object.keys(get(cart)).length;
}
function getTotalPrice() {
let price = 0;
get(cart).forEach((item) => {
price += item.amount * item.data.price;
})
return price;
function getTotalLength(): number {
let totalCartSize: number = 0;
Object.values(get(cart)).forEach((item: CartItem) => {
totalCartSize += item.amount;
});
return totalCartSize;
}
function getTotalPrice(): number {
let totalCartPrice: number = 0;
Object.values(get(cart)).forEach((item: CartItem) => {
totalCartPrice += (item.amount * item.data.price);
});
return totalCartPrice;
}
function removeByUUID(uuid: string) {
cart.update((cart) => cart.filter((item) => item.uuid !== uuid))
cart.update((cart) => {
delete cart[uuid];
return cart;
})
}
return {
...cart,
addToCart,
getEntries,
getUniqueLength,
getTotalLength,
getTotalPrice,
@ -96,4 +94,9 @@ Cart.subscribe((value) => {
localStorage.setItem("basket", JSON.stringify(value));
});
// Debug
Cart.subscribe((value) => {
console.log(value);
});
export default Cart;

View file

@ -1,4 +1,4 @@
import type {CartItem, Item} from './types';
import { type CartItem, type Item } from './types';
import TestData from './test-data';
@ -19,13 +19,13 @@ export async function getAnnouncements(): Promise<{image: string}> {
if (cache.announcement_banner) {
return cache.announcement_banner;
}
await fakeDelay(200)
const data = {
image: "/BannerExampleImage.jpg",
};
cache.announcement_banner = data;
await fakeDelay(200)
return data;
}
@ -34,17 +34,18 @@ export async function getPopularToday(): Promise<Item[]> {
if (cache.popular_today) {
return cache.popular_today;
}
await fakeDelay(200)
const data: Item[] = TestData;
cache.popular_today = data;
await fakeDelay(200)
return data;
}
export async function getMenuItems() {
const data = [
export async function getMenuItems(): Promise<{name: string, items: Item[]}[]> {
await fakeDelay(20);
return [
{
name: "Main Menu",
items: TestData,
@ -58,12 +59,12 @@ export async function getMenuItems() {
items: TestData,
},
];
await fakeDelay(20)
return data;
}
export async function getItemsByUUID(items: string[]): Promise<Item[] | Error> {
export async function getItemsByUUID(items: string[]): Promise<Item[]> {
await fakeDelay(200)
let data: Item[] = [];
TestData.forEach((itemInDatabase: Item) => {
@ -74,8 +75,6 @@ export async function getItemsByUUID(items: string[]): Promise<Item[] | Error> {
});
});
await fakeDelay(200)
if (data.length < 0) {
throw new Error("Resource could not be found");
}
@ -84,21 +83,26 @@ export async function getItemsByUUID(items: string[]): Promise<Item[] | Error> {
}
export async function getItemByUUID(uuid: string): Promise<Item | Error> {
let data: Item[] | Error = await getItemsByUUID([uuid]);
export async function getItemByUUID(uuid: string): Promise<Item> {
let data: Item[];
if (data instanceof Error) {
throw new Error("Resource could not be found");
}
if (data.length != 1) {
throw new Error("Resource could not be found");
}
await getItemsByUUID([uuid])
.then((result) => {
if (result.length != 1) {
throw new Error("Resource could not be found");
} else {
data = result;
}
})
.catch((error) => {
throw error;
});
return data[0];
}
export async function postContactEmail(name: string, email: string, message: string): Promise<string | Error> {
export async function postContactEmail(name: string, email: string, message: string): Promise<string> {
await fakeDelay(200)
if (!name) {
@ -116,34 +120,28 @@ export async function postContactEmail(name: string, email: string, message: str
return "Check your email to confirm the message!";
}
export async function postVerifyCart(currentCartData: CartItem[]): Promise<CartItem[] | Error> {
if (currentCartData.length <= 0) {
return [];
}
export async function postVerifyCart(currentCartData: Record<string, CartItem>): Promise<Record<string, CartItem>> {
let verifiedItems: Item[] = []
let itemUUIDs: string[] = currentCartData.map((item) => item.uuid);
let verifiedItems: Item[] | Error = await getItemsByUUID(itemUUIDs);
if (verifiedItems instanceof Error) {
return new Error("Could not collect new cart information");
}
let newCartData: CartItem[] = [];
currentCartData.forEach((currentItem) => {
let data: Item;
verifiedItems.forEach((verifiedItem) => {
if (verifiedItem.uuid === currentItem.uuid) {
data = verifiedItem;
}
await getItemsByUUID(Object.keys(currentCartData))
.then((data) => {
verifiedItems = data
})
.catch(() => {
return new Error("Could not collect new cart information")
});
if (data) {
newCartData.push({
uuid: currentItem.uuid,
amount: currentItem.amount,
data: data,
});
}
let newCartData: Record<string, CartItem> = {};
Object.entries(currentCartData).forEach(([key, value]) => {
verifiedItems.forEach((verifiedItem) => {
if (verifiedItem.uuid === key) {
newCartData[key] = {
uuid: value.uuid,
amount: value.amount,
data: verifiedItem,
};
}
});
});
return newCartData;

View file

@ -44,13 +44,13 @@ const TestData: Item[] = [
labels: [Labels.nut],
detail: "Example",
},
// {
// uuid: "gwagwa",
// name: "GwaGwa",
// price: 69,
// labels: [Labels.nut],
// image: "/dab.jpg",
// },
{
uuid: "gwagwa",
name: "GwaGwa",
price: 69,
labels: [Labels.nut],
image: "/dab.jpg",
},
{
uuid: "hogmelon",
name: "Hogermellon",
@ -59,14 +59,14 @@ const TestData: Item[] = [
image: "/wathog.jpg",
detail: "Example",
},
// {
// uuid: "bluhog",
// name: "Blue HOGGGGG",
// price: 0,
// labels: [Labels.nut, Labels.gluten, Labels.spicy],
// image: "/sonichog.jpg",
// detail: "Example",
// },
{
uuid: "bluhog",
name: "Blue HOGGGGG",
price: 0,
labels: [Labels.nut, Labels.gluten, Labels.spicy],
image: "/sonichog.jpg",
detail: "Example",
},
];
export default TestData;