From a4e20f5ff35d68bcd61e5765ac70e8e4edf35e5c Mon Sep 17 00:00:00 2001 From: BOTAlex Date: Thu, 14 Aug 2025 06:05:23 +0200 Subject: [PATCH] Big progress! gets data from pocketbase --- .prettierrc | 12 +++++ jsconfig.json | 6 +++ package-lock.json | 36 +++++++++++++++ package.json | 3 ++ pnpm-lock.yaml | 8 ++++ src/pages/shop/_shop_main.svelte | 27 ++++++++--- src/pages/shop/comps/ShopItemCard.svelte | 16 +++++-- src/routes/+layout.svelte | 11 +++-- src/ts/Helper.ts | 57 ++++++++++++++++++++++++ src/ts/api/api.ts | 18 ++++++++ src/ts/api/classes/ShopItem.ts | 46 +++++++++++++++++++ src/ts/store.ts | 5 ++- vite.config.js | 2 + 13 files changed, 232 insertions(+), 15 deletions(-) create mode 100644 .prettierrc create mode 100644 src/ts/Helper.ts create mode 100644 src/ts/api/api.ts create mode 100644 src/ts/api/classes/ShopItem.ts diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..bd2257d --- /dev/null +++ b/.prettierrc @@ -0,0 +1,12 @@ +{ + "plugins": ["prettier-plugin-svelte"], + "overrides": [ + { + "files": "*.svelte", + "options": { + "parser": "svelte", + "svelteIndentScriptAndStyle": true + } + } + ] +} diff --git a/jsconfig.json b/jsconfig.json index 04a3e53..09de4c3 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -26,6 +26,12 @@ ], "@static/*": [ "./static/*" + ], + "@ts/*": [ + "./src/ts/*" + ], + "@stores": [ + "./src/ts/store.ts" ] } } diff --git a/package-lock.json b/package-lock.json index cf45851..9c10e63 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@lucide/svelte": "^0.487.0", "@tailwindcss/vite": "^4.1.3", "lucide-svelte": "^0.475.0", + "pocketbase": "^0.26.2", "svelte-katex": "^0.1.2", "svelte-media-queries": "^1.6.2", "theme-change": "^2.5.0" @@ -23,6 +24,8 @@ "@tailwindcss/typography": "^0.5.15", "autoprefixer": "^10.4.20", "daisyui": "^5.0.12", + "prettier": "^3.6.2", + "prettier-plugin-svelte": "^3.4.0", "sass": "^1.77.4", "svelte": "^5.25.7", "svelte-check": "^3.8.6", @@ -3137,6 +3140,12 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pocketbase": { + "version": "0.26.2", + "resolved": "https://registry.npmjs.org/pocketbase/-/pocketbase-0.26.2.tgz", + "integrity": "sha512-WA8EOBc3QnSJh8rJ3iYoi9DmmPOMFIgVfAmIGux7wwruUEIzXgvrO4u0W2htfQjGIcyezJkdZOy5Xmh7SxAftw==", + "license": "MIT" + }, "node_modules/postcss": { "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", @@ -3183,6 +3192,33 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true }, + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-plugin-svelte": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.4.0.tgz", + "integrity": "sha512-pn1ra/0mPObzqoIQn/vUTR3ZZI6UuZ0sHqMK5x2jMLGrs53h0sXhkVuDcrlssHwIMk7FYrMjHBPoUSyyEEDlBQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "prettier": "^3.0.0", + "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0" + } + }, "node_modules/readdirp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", diff --git a/package.json b/package.json index 8c78502..e77804c 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,8 @@ "@tailwindcss/typography": "^0.5.15", "autoprefixer": "^10.4.20", "daisyui": "^5.0.12", + "prettier": "^3.6.2", + "prettier-plugin-svelte": "^3.4.0", "sass": "^1.77.4", "svelte": "^5.25.7", "svelte-check": "^3.8.6", @@ -31,6 +33,7 @@ "@lucide/svelte": "^0.487.0", "@tailwindcss/vite": "^4.1.3", "lucide-svelte": "^0.475.0", + "pocketbase": "^0.26.2", "svelte-katex": "^0.1.2", "svelte-media-queries": "^1.6.2", "theme-change": "^2.5.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d4195cc..c560233 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,6 +17,9 @@ importers: lucide-svelte: specifier: ^0.475.0 version: 0.475.0(svelte@5.25.7) + pocketbase: + specifier: ^0.26.2 + version: 0.26.2 svelte-katex: specifier: ^0.1.2 version: 0.1.2 @@ -1150,6 +1153,9 @@ packages: resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} engines: {node: '>=12'} + pocketbase@0.26.2: + resolution: {integrity: sha512-WA8EOBc3QnSJh8rJ3iYoi9DmmPOMFIgVfAmIGux7wwruUEIzXgvrO4u0W2htfQjGIcyezJkdZOy5Xmh7SxAftw==} + postcss-selector-parser@6.0.10: resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==} engines: {node: '>=4'} @@ -2281,6 +2287,8 @@ snapshots: picomatch@4.0.2: {} + pocketbase@0.26.2: {} + postcss-selector-parser@6.0.10: dependencies: cssesc: 3.0.0 diff --git a/src/pages/shop/_shop_main.svelte b/src/pages/shop/_shop_main.svelte index 1eb0724..af49449 100644 --- a/src/pages/shop/_shop_main.svelte +++ b/src/pages/shop/_shop_main.svelte @@ -1,14 +1,29 @@ - +
Items
-
- {#each { length: 5 } as _, i} - - {/each} +
+ {#if allItems != undefined} + {#each allItems as item, i} + + {/each} + {:else} +
+ {/if}
diff --git a/src/pages/shop/comps/ShopItemCard.svelte b/src/pages/shop/comps/ShopItemCard.svelte index a3049e3..8d06766 100644 --- a/src/pages/shop/comps/ShopItemCard.svelte +++ b/src/pages/shop/comps/ShopItemCard.svelte @@ -1,14 +1,22 @@ -
-
- +
- diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 5621849..d9a3352 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -26,7 +26,7 @@ afterNavigate(() => { const params = new URLSearchParams(window.location.search); hideOnPrint = params.get("hideOnPrint") === "1"; - console.log(hideOnPrint); + // console.log(hideOnPrint); }); import { onMount } from "svelte"; @@ -105,7 +105,8 @@ Zhen CVZhen CV Games @@ -142,7 +143,11 @@ href="https://botalex.itch.io/" target="_blank">Games - Zhen's CV + Zhen's CV
diff --git a/src/ts/Helper.ts b/src/ts/Helper.ts new file mode 100644 index 0000000..c248011 --- /dev/null +++ b/src/ts/Helper.ts @@ -0,0 +1,57 @@ +import { PUBLIC_URL_BASE } from "$env/static/public"; + +// Absolute vibe coded. Idk if it works or not. Not important anyways +// Assumes PUBLIC_URL_BASE is something like "https://deprived.dev" +const ABSOLUTE_RE = /^[a-zA-Z][a-zA-Z\d+\-.]*:\/\//; + +function withTrailingSlash(s: string): string { + return s.replace(/\/+$/, "") + "/"; +} + +export function ParseAssetUrl(url: string, base?: string): string { + // Handle empty/undefined url: if a base is given, return the base itself + if (!url) { + const origin = + (typeof PUBLIC_URL_BASE !== "undefined" && PUBLIC_URL_BASE) || ""; + if (!base) return ""; // no filename, no base → nothing to resolve + + try { + // Make base absolute + const absoluteBase = ABSOLUTE_RE.test(base) + ? withTrailingSlash(base) + : new URL(withTrailingSlash(base), withTrailingSlash(origin)).href; + + return absoluteBase; // e.g. "https://deprived.dev/assets/shop/preview-images/" + } catch { + return ""; + } + } + + // Already absolute + if (ABSOLUTE_RE.test(url)) { + try { + return new URL(url).href; + } catch { + return url; + } + } + + const origin = + (typeof PUBLIC_URL_BASE !== "undefined" && PUBLIC_URL_BASE) || ""; + let absoluteBase = ""; + + try { + if (base) { + absoluteBase = ABSOLUTE_RE.test(base) + ? withTrailingSlash(base) + : new URL(withTrailingSlash(base), withTrailingSlash(origin)).href; + } else { + if (!origin) return url; + absoluteBase = withTrailingSlash(origin); + } + + return new URL(url, absoluteBase).href; + } catch { + return url; + } +} diff --git a/src/ts/api/api.ts b/src/ts/api/api.ts new file mode 100644 index 0000000..963c5a4 --- /dev/null +++ b/src/ts/api/api.ts @@ -0,0 +1,18 @@ +// This files is meant for interaction with pocketbase. I might split this into multiple files later +// It is meant to be called from stores.ts + +import PocketBase from "pocketbase"; +import { ShopItem } from "./classes/ShopItem"; +import { PUBLIC_POCKET_URL, PUBLIC_ASSETS_URL_BASE } from "$env/static/public"; + +export let pb = new PocketBase(PUBLIC_POCKET_URL); + +console.log(PUBLIC_POCKET_URL); + +export class ApiService { + // read function name + static async GetAllShopItems(): Promise { + const list = await pb.collection("shopItems").getList(1, 50, {}); + return list.items.map((rec: any) => ShopItem.fromJSON(rec)); + } +} diff --git a/src/ts/api/classes/ShopItem.ts b/src/ts/api/classes/ShopItem.ts new file mode 100644 index 0000000..459ffc4 --- /dev/null +++ b/src/ts/api/classes/ShopItem.ts @@ -0,0 +1,46 @@ +import { PUBLIC_POCKET_URL, PUBLIC_URL_BASE } from "$env/static/public"; +import { ParseAssetUrl } from "@src/ts/Helper"; + +export class ShopItem { + item_name: string; + preview_image: string; + page_url: string; // the url used for the item + images_root: string; // might not be optimal to include this, in the same class, but should be fine, for now at least + category: string[]; + sold_quantity: number; + stock: number; + unlisted: boolean; + + constructor( + item_name: string, + preview_image: string, + redirect: string, + images_root: string, + category: string[], + sold_quantity: number, + stock: number, + unlisted: boolean, + ) { + this.item_name = item_name; + this.preview_image = preview_image; + this.page_url = redirect; + this.images_root = images_root; + this.category = category; + this.sold_quantity = sold_quantity; + this.stock = stock; + this.unlisted = unlisted; + } + + static fromJSON(json: any): ShopItem { + return new ShopItem( + json.item_name, + ParseAssetUrl(json.preview_image, "/assets/shop/preview-images"), + json.page_url, + ParseAssetUrl(json.images_root, "/assets/shop/" + json.item_name + "/"), // Please use better paths + json.category, + json.sold_quantity, + json.stock, + json.unlisted, + ); + } +} diff --git a/src/ts/store.ts b/src/ts/store.ts index 2061bcf..5519f84 100644 --- a/src/ts/store.ts +++ b/src/ts/store.ts @@ -1,2 +1,3 @@ -import PocketBase from "pocketbase"; -export let pb = new PocketBase("https://pocket.deprived.dev"); +import { ApiService } from "./api/api"; + +export let api = ApiService; diff --git a/vite.config.js b/vite.config.js index 456f4d1..a90f8dd 100644 --- a/vite.config.js +++ b/vite.config.js @@ -24,7 +24,9 @@ export default defineConfig({ "@src": path.resolve("./src"), "@static": path.resolve("./static"), "@pages": path.resolve("./src/pages"), + "@ts": path.resolve("./src/ts"), "@shop": path.resolve("./src/pages/shop"), + "@stores": path.resolve("./src/ts/store.ts"), }, }, server: {