commit 72e0d0d9573803afcba182a6f18560c5c0eb78fc parent 4ab7f818ce0a32c1827191c125bed351e256bd69 Author: triesap <triesap@radroots.dev> Date: Thu, 20 Nov 2025 13:47:13 +0000 apps-lib-pwa: refactor ui package to export core components and app state backup types, update loading and select utilities Diffstat:
71 files changed, 179 insertions(+), 3899 deletions(-)
diff --git a/apps-lib-pwa/.env.example b/apps-lib-pwa/.env.example @@ -1,4 +0,0 @@ -VITE_PUBLIC_IDB_NAME= -VITE_PUBLIC_NDK_CACHE_NAME= -VITE_PUBLIC_NDK_CLIENT_NAME= -VITE_PUBLIC_RADROOTS_MARKET_RELAY_URL= diff --git a/apps-lib-pwa/.gitignore b/apps-lib-pwa/.gitignore @@ -1,6 +1,7 @@ node_modules dist .turbo +.svelte-kit # Logs logs/ diff --git a/apps-lib-pwa/package.json b/apps-lib-pwa/package.json @@ -1,6 +1,6 @@ { "name": "@radroots/apps-lib-pwa", - "version": "0.0.0", + "version": "0.0.1", "private": true, "license": "GPLv3", "scripts": { @@ -29,6 +29,34 @@ ".": { "types": "./dist/index.d.ts", "svelte": "./dist/index.js" + }, + "./stores/*": { + "types": "./dist/stores/*.d.ts", + "import": "./dist/stores/*.js", + "default": "./dist/stores/*.js" + }, + "./types/*": { + "types": "./dist/types/*.d.ts", + "import": "./dist/types/*.js", + "default": "./dist/types/*.js" + }, + "./utils/*": { + "types": "./dist/utils/*.d.ts", + "import": "./dist/utils/*.js", + "default": "./dist/utils/*.js" + } + }, + "typesVersions": { + "*": { + "stores/*": [ + "dist/stores/*" + ], + "types/*": [ + "dist/types/*" + ], + "utils/*": [ + "dist/utils/*" + ] } }, "peerDependencies": { diff --git a/apps-lib-pwa/src/lib/client/keystore-nostr.ts b/apps-lib-pwa/src/lib/client/keystore-nostr.ts @@ -1,94 +0,0 @@ -import { keystore } from "@radroots/client"; -import { err_msg, handle_err, type ResolveError, type ResultObj, type ResultPass, type ResultPublicKey, type ResultSecretKey, type ResultsList } from '@radroots/utils'; -import { lib_nostr_key_generate, lib_nostr_public_key, lib_nostr_secret_key_validate } from '@radroots/utils-nostr'; - -export type INostrKeystore = { - generate(): Promise<ResolveError<ResultPublicKey>>; - add(secret_key: string): Promise<ResolveError<ResultPublicKey>>; - read(public_key: string): Promise<ResolveError<ResultSecretKey>>; - keys(): Promise<ResolveError<ResultsList<string>>>; - remove(public_key: string): Promise<ResolveError<ResultObj<string>>>; - reset(): Promise<ResolveError<ResultPass>>; -}; - -export class PwaKeystoreNostr implements INostrKeystore { - private static readonly keystore_database = "radroots-pwa-v1-keystore"; - private static readonly keystore_store = "nostr"; - - private _keystore: keystore.WebKeystore; - - constructor() { - this._keystore = new keystore.WebKeystore({ - database: PwaKeystoreNostr.keystore_database, - store: PwaKeystoreNostr.keystore_store, - }); - } - - private async add_secret_key(secret_key_raw: string) { - const secret_key = lib_nostr_secret_key_validate(secret_key_raw); - if (!secret_key) throw new Error("error.nostr.invalid_secret_key"); - const public_key = lib_nostr_public_key(secret_key); - return await this._keystore.add(public_key, secret_key); - } - - public async generate() { - try { - const secret_key = lib_nostr_key_generate(); - const resolve = await this.add_secret_key(secret_key); - if ("err" in resolve) return resolve; - return { public_key: resolve.result }; - } catch (e) { - return handle_err(e); - } - }; - - public async add(secret_key_raw: string) { - try { - const resolve = await this.add_secret_key(secret_key_raw); - if ("err" in resolve) return resolve; - return { public_key: resolve.result }; - } catch (e) { - return handle_err(e); - } - }; - - public async read(public_key?: string) { - try { - const resolve = await this._keystore.read(public_key); - if ("err" in resolve) return resolve; - return { secret_key: resolve.result }; - } catch (e) { - return handle_err(e); - } - }; - - public async keys() { - try { - const resolve = await this._keystore.keys(); - if ("err" in resolve) return resolve; - if (resolve.results.length) return resolve; - return err_msg("error.client.keystore-nostr.no_results"); - } catch (e) { - return handle_err(e); - } - }; - - public async remove(public_key: string) { - try { - const resolve = await this._keystore.remove(public_key); - if ("err" in resolve) return resolve; - return { result: public_key }; - } catch (e) { - return handle_err(e); - } - }; - - public async reset() { - try { - const resolve = await this._keystore.reset(); - return resolve; - } catch (e) { - return handle_err(e); - } - }; -} diff --git a/apps-lib-pwa/src/lib/components/buttons/button-layout-pair.svelte b/apps-lib-pwa/src/lib/components/button/button-layout-pair.svelte diff --git a/apps-lib-pwa/src/lib/components/buttons/button-layout.svelte b/apps-lib-pwa/src/lib/components/button/button-layout.svelte diff --git a/apps-lib-pwa/src/lib/components/buttons/button-label-dashed.svelte b/apps-lib-pwa/src/lib/components/buttons/button-label-dashed.svelte @@ -1,22 +0,0 @@ -<script lang="ts"> - import type { ICb } from "@radroots/apps-lib"; - - let { - basis, - }: { - basis: ICb & { - label: string; - }; - } = $props(); -</script> - -<button - class={`flex flex-row h-line_button w-full justify-center items-center`} - onclick={async () => { - await basis.callback(); - }} -> - <p class={`font-sans font-[500] text-lg text-ly0-gl-hl tracking-wide`}> - {`- ${basis.label} -`} - </p> -</button> diff --git a/apps-lib-pwa/src/lib/components/buttons/button-round-nav.svelte b/apps-lib-pwa/src/lib/components/buttons/button-round-nav.svelte @@ -1,26 +0,0 @@ -<script lang="ts"> - import type { IButtonNavRound } from "$lib/types/components"; - import { Glyph } from "@radroots/apps-lib"; - import LoadSymbol from "../lib/load-symbol.svelte"; - - let { basis }: { basis: IButtonNavRound } = $props(); -</script> - -<button - class={`flex flex-row h-12 w-12 justify-center items-center bg-ly1 rounded-full el-re`} - disabled={!!basis.disabled} - onclick={basis.callback} -> - {#if basis.loading} - <LoadSymbol /> - {:else} - <Glyph - basis={{ - classes: `text-ly0-gl`, - dim: `sm+`, - - key: basis.glyph, - }} - /> - {/if} -</button> diff --git a/apps-lib-pwa/src/lib/components/buttons/button-simple.svelte b/apps-lib-pwa/src/lib/components/buttons/button-simple.svelte @@ -1,22 +0,0 @@ -<script lang="ts"> - import type { IButtonSimple } from "$lib/types/components"; - import { parse_layer } from "@radroots/apps-lib"; - - let { basis }: { basis: IButtonSimple } = $props(); - - const layer = $derived(parse_layer(basis.layer || 1)); -</script> - -<button - class={`group flex flex-row h-line_button w-full justify-center items-center rounded-touch bg-ly${layer} ly${layer}-active-surface ly${layer}-active-ring`} - onclick={async (ev) => { - if (!basis.allow_propogation) ev.stopPropagation(); - await basis.callback(); - }} -> - <p - class={`font-sans font-[600] text-xl text-ly0-gl capitalize tracking-wider opacity-active`} - > - {basis.label} - </p> -</button> diff --git a/apps-lib-pwa/src/lib/components/buttons/glyph-button-simple.svelte b/apps-lib-pwa/src/lib/components/buttons/glyph-button-simple.svelte @@ -1,45 +0,0 @@ -<script lang="ts"> - import { - type GlyphKey, - type IClOpt, - fmt_cl, - Glyph, - } from "@radroots/apps-lib"; - import { type CallbackPromise } from "@radroots/utils"; - - let { - basis, - }: { - basis: IClOpt & { - kind?: `primary` | `neutral`; - label: string; - callback: CallbackPromise; - glyph?: GlyphKey; - }; - } = $props(); - - const classes_kind = $derived( - basis.kind === `neutral` ? `text-ly0-gl-shade` : `text-ly0-gl-hl`, - ); -</script> - -<button - class={`${fmt_cl(basis.classes)} group flex flex-row justify-center items-center`} - onclick={basis.callback} -> - {#if basis.glyph} - <Glyph - basis={{ - classes: `${classes_kind}`, - dim: `sm+`, - - key: basis.glyph, - }} - /> - {/if} - <p - class={`font-sans font-[600] text-line_label ${classes_kind} opacity-active`} - > - {basis.label} - </p> -</button> diff --git a/apps-lib-pwa/src/lib/components/buttons/glyph-button.svelte b/apps-lib-pwa/src/lib/components/buttons/glyph-button.svelte @@ -1,18 +0,0 @@ -<script lang="ts"> - import { type IGlyph, fmt_cl, glyph_style_map } from "@radroots/apps-lib"; - - let { basis }: { basis: IGlyph } = $props(); - const styles = $derived( - basis?.dim ? glyph_style_map.get(basis.dim) : glyph_style_map.get(`sm`), - ); -</script> - -<!-- svelte-ignore a11y_consider_explicit_label --> -<button - class={`${fmt_cl(basis.classes)} flex flex-col justify-center items-center text-[${styles?.gl_1}px] el-re`} - onclick={async () => { - if (basis.callback) await basis.callback(); - }} -> - <i class={`ph-bold ph-${basis.key}`}></i> -</button> diff --git a/apps-lib-pwa/src/lib/components/forms/entry-line.svelte b/apps-lib-pwa/src/lib/components/form/entry-line.svelte diff --git a/apps-lib-pwa/src/lib/components/forms/entry-wrap.svelte b/apps-lib-pwa/src/lib/components/form/entry-wrap.svelte diff --git a/apps-lib-pwa/src/lib/components/forms/form-line-ledger-label-select-label.svelte b/apps-lib-pwa/src/lib/components/forms/form-line-ledger-label-select-label.svelte @@ -1,36 +0,0 @@ -<script lang="ts"> - import { symbols } from "@radroots/apps-lib"; - - let { - basis, - }: { - basis: { - label: string; - }; - } = $props(); -</script> - -<div class={`flex flex-row justify-start items-center`}> - <p - class={`pr-[13px] font-sansd text-trellis_ti text-ly0-gl-label uppercase`} - > - {`(${basis.label}`} - </p> - <div - class={`relative flex flex-row justify-start items-center -translate-x-[10px] -translate-y-[1px]`} - > - <p - class={`absolute font-sansd text-trellis_ti text-ly0-gl-label uppercase scale-y-[70%] scale-x-[80%] -translate-y-[1px]`} - > - {`${symbols.up}`} - </p> - <p - class={`absolute font-sansd text-trellis_ti text-ly0-gl-label uppercase scale-y-[70%] scale-x-[80%] translate-y-[2px]`} - > - {`${symbols.down}`} - </p> - </div> - <p class={`font-sansd text-trellis_ti text-ly0-gl-label uppercase`}> - {`)`} - </p> -</div> diff --git a/apps-lib-pwa/src/lib/components/forms/form-line-ledger-select.svelte b/apps-lib-pwa/src/lib/components/forms/form-line-ledger-select.svelte @@ -1,86 +0,0 @@ -<script lang="ts"> - import { - type ElementCallbackValueKeydown, - type IIdOpt, - type ISelectCallback, - type ISelectOption, - fmt_id, - } from "@radroots/apps-lib"; - import InputPwa from "../lib/input-pwa.svelte"; - import SelectPwa from "../lib/select-pwa.svelte"; - - let { - basis, - value_input = $bindable(``), - value_sel = $bindable(``), - }: { - basis: IIdOpt & { - display_value?: string; - label?: string; - input: { - placeholder?: string; - callback_keydown?: - | ElementCallbackValueKeydown<HTMLInputElement> - | undefined; - }; - select: { - entries: ISelectOption<string>[]; - callback?: ISelectCallback; - }; - }; - value_input?: string; - value_sel?: string; - } = $props(); - - const id = $derived(basis.id || ``); -</script> - -<div class={`flex flex-col w-full gap-2 justify-start items-start`}> - {#if basis.label} - <div class={`flex flex-row w-full justify-start items-center`}> - <p class={`font-sansd text-trellis_ti text-ly0-gl-label uppercase`}> - {basis.label} - </p> - </div> - {/if} - <div - class={`relative flex flex-row h-12 w-full justify-start items-center border-y-line border-ly0-edge`} - > - {#if basis.display_value} - <p class={`font-sans font-[400] text-ly0-gl text-form_base`}> - {basis.display_value} - </p> - {:else} - <InputPwa - bind:value={value_input} - basis={{ - id: id ? fmt_id(`${id}_input`) : undefined, - layer: 0, - classes: `h-10 placeholder:text-[1.1rem]`, - placeholder: basis.input.placeholder || ``, - callback_keydown: basis.input.callback_keydown, - }} - /> - <div - class={`absolute right-0 flex flex-row justify-center items-center`} - > - <SelectPwa - bind:value={value_sel} - basis={{ - classes: `w-fit text-ly1-gl`, - id: id ? fmt_id(`${id}_sel`) : undefined, - sync: true, - layer: 1, - show_arrows: `r`, - options: [ - { - entries: basis.select.entries, - }, - ], - callback: basis.select.callback, - }} - /> - </div> - {/if} - </div> -</div> diff --git a/apps-lib-pwa/src/lib/components/forms/form-line-ledger.svelte b/apps-lib-pwa/src/lib/components/forms/form-line-ledger.svelte @@ -1,88 +0,0 @@ -<script lang="ts"> - import { - type ElementCallbackValueKeydown, - type IIdOpt, - type ISelectOption, - fmt_id, - } from "@radroots/apps-lib"; - import { type FormField } from "@radroots/utils"; - import InputPwa from "../lib/input-pwa.svelte"; - import SelectMenu from "../lib/select-menu.svelte"; - import FormLineLedgerLabelSelectLabel from "./form-line-ledger-label-select-label.svelte"; - - let { - basis, - value = $bindable(``), - value_label_sel = $bindable(``), - }: { - basis: IIdOpt & { - display_value?: string; - label?: string; - label_select?: { - label: string; - entries: ISelectOption<string>[]; - }; - input?: { - placeholder?: string; - field?: FormField; - callback_keydown?: - | ElementCallbackValueKeydown<HTMLInputElement> - | undefined; - }; - }; - value?: string; - value_label_sel?: string; - } = $props(); - - const id = $derived(basis.id || ``); -</script> - -<div class={`flex flex-col w-full gap-2 justify-start items-start`}> - {#if basis.label} - <div class={`flex flex-row w-full justify-start gap-1 items-center`}> - <p class={`font-sansd text-trellis_ti text-ly0-gl-label uppercase`}> - {basis.label} - </p> - {#if basis.label_select} - <SelectMenu - bind:value={value_label_sel} - basis={{ - layer: 0, - options: [ - { - entries: basis.label_select.entries, - }, - ], - }} - > - <FormLineLedgerLabelSelectLabel - basis={{ - label: basis.label_select.label, - }} - /> - </SelectMenu> - {/if} - </div> - {/if} - <div - class={`flex flex-row h-12 w-full justify-start items-center border-y-line border-ly0-edge`} - > - {#if basis.display_value} - <p class={`font-sans font-[400] text-ly1-gl text-form_base`}> - {basis.display_value} - </p> - {:else if basis.input} - <InputPwa - bind:value - basis={{ - id: id ? fmt_id(id) : undefined, - layer: 0, - classes: `h-10 placeholder:text-[1.1rem]`, - field: basis.input?.field || undefined, - placeholder: basis.input?.placeholder || ``, - callback_keydown: basis.input?.callback_keydown, - }} - /> - {/if} - </div> -</div> diff --git a/apps-lib-pwa/src/lib/components/layout/layout-window.svelte b/apps-lib-pwa/src/lib/components/layout/layout-window.svelte @@ -0,0 +1,57 @@ +<script lang="ts"> + import { + app_lo, + app_tilt, + envelope_tilt, + envelope_visible, + } from "$lib/stores/app"; + import { handle_err, window_set } from "@radroots/apps-lib"; + import { onMount } from "svelte"; + import LogoCircle from "../lib/logo-circle.svelte"; + + let { children } = $props(); + + onMount(async () => { + try { + window_set(); + } catch (e) { + handle_err(e, `on_mount`); + } + }); + + envelope_visible.subscribe(async (_envelope_visible) => { + if (_envelope_visible && $envelope_tilt) app_tilt.set(true); + else app_tilt.set(false); + }); +</script> + +<div + class={`relative lg:hidden flex flex-col h-[100vh] w-full bg-ly0 ${ + $app_tilt ? `scale-y-[96%] translate-y-4 rounded-t-[3rem]` : `` + } overflow-x-hidden overflow-y-scroll scroll-hide delay-75 duration-200 el-re cursor-default`} +> + {#if $app_lo} + <div class={`flex flex-col h-full w-full`}> + {@render children()} + </div> + {/if} +</div> +<div + class={`max-lg:hidden flex flex-col h-[100vh] w-full justify-center items-center bg-ly0 cursor-default el-re`} +> + <div class={`flex flex-col justify-center items-center`}> + <LogoCircle /> + <div class={`flex flex-col w-full gap-1 justify-center items-center`}> + <p class={`font-sans font-[400] text-base text-ly0-gl italic`}> + {`Welcome to the`} + <span class={`font-[600]`}> + {`Rad Roots`} + </span> + {`app!`} + </p> + <p class={`font-sans font-[400] text-base text-ly0-gl`}> + {`Please view this application on mobile device`} + </p> + </div> + </div> +</div> diff --git a/apps-lib-pwa/src/lib/components/layouts/layout-bottom-button.svelte b/apps-lib-pwa/src/lib/components/layouts/layout-bottom-button.svelte @@ -1,22 +0,0 @@ -<script lang="ts"> - import { app_lo } from "$lib/stores/app"; - import type { Snippet } from "svelte"; - - let { - basis, - children, - }: { - basis?: { - hidden: boolean; - }; - children: Snippet; - } = $props(); -</script> - -{#if !basis?.hidden} - <div - class={`z-10 absolute bottom-0 h-lo_bottom_button_${$app_lo} flex flex-col w-full px-4 gap-1 justify-start items-center`} - > - {@render children()} - </div> -{/if} diff --git a/apps-lib-pwa/src/lib/components/layouts/layout-page.svelte b/apps-lib-pwa/src/lib/components/layouts/layout-page.svelte @@ -1,18 +0,0 @@ -<script lang="ts"> - import { type IBasisOpt, type IClOpt, fmt_cl } from "@radroots/apps-lib"; - import type { Snippet } from "svelte"; - - let { - basis = undefined, - children, - }: { - basis?: IBasisOpt<IClOpt>; - children: Snippet; - } = $props(); -</script> - -<div - class={`${fmt_cl(basis?.classes)} flex flex-col w-full pt-4 px-4 pb-24 gap-4 justify-center items-center`} -> - {@render children()} -</div> diff --git a/apps-lib-pwa/src/lib/components/layouts/layout-trellis.svelte b/apps-lib-pwa/src/lib/components/layouts/layout-trellis.svelte @@ -1,18 +0,0 @@ -<script lang="ts"> - import { type IBasisOpt, type IClOpt, fmt_cl } from "@radroots/apps-lib"; - import type { Snippet } from "svelte"; - - let { - basis = undefined, - children, - }: { - basis?: IBasisOpt<IClOpt>; - children: Snippet; - } = $props(); -</script> - -<div - class={`${fmt_cl(basis?.classes)} flex flex-col pb-12 gap-6 justify-center items-center scroll-hide`} -> - {@render children()} -</div> diff --git a/apps-lib-pwa/src/lib/components/layouts/layout-view.svelte b/apps-lib-pwa/src/lib/components/layouts/layout-view.svelte @@ -1,48 +0,0 @@ -<script lang="ts"> - import { nav_blur, ph_blur, tabs_blur } from "$lib/stores/app"; - import { fmt_cl, type IBasisOpt, type IClOpt } from "@radroots/apps-lib"; - import { onDestroy, onMount, type Snippet } from "svelte"; - - let { - basis = undefined, - el = $bindable(null), - children, - }: { - el?: HTMLDivElement | null; - basis?: IBasisOpt<IClOpt & { fade?: boolean }>; - children: Snippet; - } = $props(); - - onMount(async () => { - try { - el?.addEventListener("scroll", scrollChange); - } catch (e) { - } finally { - } - }); - - onDestroy(async () => { - try { - el?.removeEventListener("scroll", scrollChange); - } catch (e) { - } finally { - } - }); - - const scrollChange = (): void => { - if (Math.max(el?.scrollTop || 0, 0) > 10) nav_blur.set(true); - else nav_blur.set(false); - if (Math.max(el?.scrollTop || 0, 0) > 10) tabs_blur.set(true); - else tabs_blur.set(false); - if (Math.max(el?.scrollTop || 0, 0) > 30) ph_blur.set(true); - else ph_blur.set(false); - }; -</script> - -<div - bind:this={el} - class={`${fmt_cl(basis?.classes)} absolute top-0 left-0 flex flex-col h-[100vh] w-full justify-start items-center scroll-hide overflow-auto`} - class:fade-in={basis?.fade} -> - {@render children()} -</div> diff --git a/apps-lib-pwa/src/lib/components/layouts/layout-window.svelte b/apps-lib-pwa/src/lib/components/layouts/layout-window.svelte @@ -1,35 +0,0 @@ -<script lang="ts"> - import { - app_lo, - app_tilt, - envelope_tilt, - envelope_visible, - } from "$lib/stores/app"; - import { handle_err, window_set } from "@radroots/apps-lib"; - import { onMount } from "svelte"; - - let { children } = $props(); - - onMount(async () => { - try { - window_set(); - } catch (e) { - handle_err(e, `on_mount`); - } - }); - - envelope_visible.subscribe(async (_envelope_visible) => { - if (_envelope_visible && $envelope_tilt) app_tilt.set(true); - else app_tilt.set(false); - }); -</script> - -<div - class={`relative lg:hidden flex flex-col h-[100vh] w-full bg-ly0 ${$app_tilt ? `scale-y-[96%] translate-y-4 rounded-t-[3rem]` : ``} overflow-x-hidden overflow-y-scroll scroll-hide delay-75 duration-200 el-re`} -> - {#if $app_lo} - <div class={`flex flex-col h-full w-full`}> - {@render children()} - </div> - {/if} -</div> diff --git a/apps-lib-pwa/src/lib/components/lib/float-page.svelte b/apps-lib-pwa/src/lib/components/lib/float-page.svelte @@ -1,12 +0,0 @@ -<script lang="ts"> - import type { IFloatPage } from "$lib/types/components"; - import type { Snippet } from "svelte"; - - let { basis, children }: { basis: IFloatPage; children: Snippet } = - $props(); -</script> - -<div class={`absolute top-10 ${basis.posx}-6 flex flex-row`}> - {@render children()} -</div> -<div class="hidden left-6 right-6"></div> diff --git a/apps-lib-pwa/src/lib/components/lib/glyph-circle.svelte b/apps-lib-pwa/src/lib/components/lib/glyph-circle.svelte @@ -1,21 +0,0 @@ -<script lang="ts"> - import type { IGlyphCircle } from "$lib/types/components"; - import { fmt_cl, glyph_style_map } from "@radroots/apps-lib"; - import GlyphButton from "../buttons/glyph-button.svelte"; - - let { basis }: { basis: IGlyphCircle } = $props(); - - const styles = $derived( - basis?.glyph?.dim - ? glyph_style_map.get(basis?.glyph?.dim) - : glyph_style_map.get(`sm`), - ); -</script> - -{#if styles?.dim_1} - <div - class={`${fmt_cl(basis?.classes_wrap)} flex flex-col h-[${styles?.dim_1}px] w-[${styles?.dim_1}px] justify-center items-center rounded-full el-re`} - > - <GlyphButton basis={basis?.glyph} /> - </div> -{/if} diff --git a/apps-lib-pwa/src/lib/components/lib/image-upload-add-photo.svelte b/apps-lib-pwa/src/lib/components/lib/image-upload-add-photo.svelte @@ -1,46 +0,0 @@ -<script lang="ts"> - import { get_context, Glyph } from "@radroots/apps-lib"; - import LoadSymbol from "./load-symbol.svelte"; - - const { ls, lc_photos_add } = get_context(`lib`); - - let { - basis, - photo_path = $bindable(``), - }: { - basis: { - loading?: boolean; - }; - photo_path: string; - } = $props(); -</script> - -<div class={`relative flex flex-row w-full justify-center items-center`}> - <button - class={`flex flex-row h-[5rem] w-[5rem] justify-center items-center bg-ly1/60 rounded-full`} - onclick={async () => { - const photo_paths_add = await lc_photos_add(); - if (photo_paths_add) photo_path = photo_paths_add[0]; - }} - > - {#if basis.loading} - <LoadSymbol basis={{ dim: `md` }} /> - {:else} - <Glyph - basis={{ - classes: `text-[40px] text-ly2-gl`, - dim: `sm`, - key: `camera`, - }} - /> - {/if} - - <div - class={`absolute -bottom-[1.8rem] flex flex-row justify-start items-center`} - > - <p class={`font-arch font-[600] text-sm text-ly0-gl capitalize`}> - {`${$ls(`icu.add_*`, { value: `${$ls(`common.photo`)}` })}`} - </p> - </div> - </button> -</div> diff --git a/apps-lib-pwa/src/lib/components/lib/input-pwa.svelte b/apps-lib-pwa/src/lib/components/lib/input-pwa.svelte @@ -1,120 +0,0 @@ -<script lang="ts"> - import { browser } from "$app/environment"; - import { - fmt_cl, - idb, - type IInput, - parse_layer, - value_constrain, - } from "@radroots/apps-lib"; - import { handle_err } from "@radroots/utils"; - import { onMount } from "svelte"; - - let { - basis, - el = $bindable(null), - value = $bindable(``), - }: { - basis: IInput<string>; - el?: HTMLInputElement | null; - value?: string; - } = $props(); - - const id = $derived(basis?.id ? basis.id : null); - const layer = $derived( - typeof basis?.layer === `boolean` ? 0 : parse_layer(basis?.layer), - ); - const classes_layer = $derived( - typeof basis?.layer === `boolean` || typeof basis?.layer === `undefined` - ? `` - : `bg-ly${layer} text-ly${layer}-gl_d placeholder:text-ly${layer}-gl_pl caret-ly${layer}-gl`, - ); - - const sync_from_idb = async (): Promise<void> => { - if (!browser || !idb || !id) return; - try { - const kv_val = await idb.get(id); - if (kv_val !== null && kv_val !== undefined && kv_val !== value) { - value = kv_val; - } else if (kv_val === null || kv_val === undefined) { - value = ``; - await idb.set(id, ``); - } - } catch (e) { - handle_err(e, `sync_from_idb`); - } - }; - - const sync_to_idb = async (): Promise<void> => { - if (!browser || !idb || !id) return; - try { - await idb.set(id, value || ``); - } catch (e) { - handle_err(e, `input_idb_sync`); - } - }; - - onMount(async () => { - await sync_from_idb(); - if (basis?.callback_mount && el) { - try { - await basis.callback_mount({ el }); - } catch (e) { - handle_err(e, `callback_mount`); - } - } - }); - - $effect(() => { - if (id && basis?.sync && browser && idb) { - (async () => { - await sync_to_idb(); - })(); - } - }); - - const handle_on_input = async (): Promise<void> => { - try { - let val_cur = value; - let pass = true; - if (basis?.field) { - val_cur = value_constrain(basis.field?.charset, val_cur); - if (val_cur !== value) { - value = val_cur; - } - pass = basis.field?.validate.test(val_cur); - } - if (basis?.callback) { - await basis.callback({ value: val_cur, pass }); - } - } catch (e) { - handle_err(e, `handle_on_input`); - } - }; -</script> - -<input - bind:this={el} - bind:value - disabled={!!basis.disabled} - oninput={handle_on_input} - onblur={async ({ currentTarget: el }) => { - if (basis.callback_blur) await basis.callback_blur({ el }); - }} - onfocus={async ({ currentTarget: el }) => { - if (id && basis.sync && browser && idb) await sync_from_idb(); - if (basis.callback_focus) await basis.callback_focus({ el }); - }} - onkeydown={async (ev) => { - if (basis?.callback_keydown) - await basis.callback_keydown({ - key: ev.key, - key_s: ev.key === `Enter`, - el: ev.currentTarget, - }); - }} - {id} - type="text" - class={`${fmt_cl(basis?.classes)} el-input ${classes_layer} el-re`} - placeholder={basis?.placeholder || ``} -/> diff --git a/apps-lib-pwa/src/lib/components/lib/label-swap.svelte b/apps-lib-pwa/src/lib/components/lib/label-swap.svelte @@ -1,41 +0,0 @@ -<script lang="ts"> - import { - fmt_cl, - type ILabelSwap, - type ILyOpt, - parse_layer, - } from "@radroots/apps-lib"; - - let { - basis, - el = $bindable(null), - }: { - basis: ILabelSwap & ILyOpt; - el?: HTMLLabelElement | null; - } = $props(); - - const layer = $derived(parse_layer(basis?.layer ? basis.layer : 1)); -</script> - -<div class={`flex flex-row justify-start items-center`}> - <!-- svelte-ignore a11y_label_has_associated_control --> - <label - bind:this={el} - class={`swap${basis.swap.toggle ? ` swap-active` : ``}`} - > - <div class="swap-on"> - <p - class={`${fmt_cl(basis.swap.on.classes || `text-nav_prev text-ly${layer}-gl-hl group-active:opacity-60`)} font-sans -translate-y-[1px] el-re`} - > - {basis.swap.on.value} - </p> - </div> - <div class="swap-off"> - <p - class={`${fmt_cl(basis.swap.off.classes || `text-nav_prev text-ly${layer}-gl-hl group-active:opacity-60`)} font-sans -translate-y-[1px] el-re`} - > - {basis.swap.off.value} - </p> - </div> - </label> -</div> diff --git a/apps-lib-pwa/src/lib/components/lib/load-symbol.svelte b/apps-lib-pwa/src/lib/components/lib/load-symbol.svelte @@ -1,5 +1,5 @@ <script lang="ts"> - import { loading_style_map } from "$lib/styles/lib"; + import { loading_style_map } from "$lib/utils/styles"; import type { ILoadSymbol } from "@radroots/apps-lib"; let { @@ -21,50 +21,80 @@ class={`relative flex flex-row justify-center items-center h-[${styles?.dim_1}px] w-[${styles?.dim_1}px] fade-in el-re`} > <div - class={`${num_blades === 12 ? `spinner12 center` : `spinner8 center`} text-[${styles?.gl_2 || styles?.dim_1}px]`} + class={`${ + num_blades === 12 ? `spinner12 center` : `spinner8 center` + } text-[${styles?.gl_2 || styles?.dim_1}px]`} > <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} + class={`${ + num_blades === 12 ? `spinner12-blade` : `spinner8-blade` + }`} ></div> <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} + class={`${ + num_blades === 12 ? `spinner12-blade` : `spinner8-blade` + }`} ></div> <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} + class={`${ + num_blades === 12 ? `spinner12-blade` : `spinner8-blade` + }`} ></div> <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} + class={`${ + num_blades === 12 ? `spinner12-blade` : `spinner8-blade` + }`} ></div> <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} + class={`${ + num_blades === 12 ? `spinner12-blade` : `spinner8-blade` + }`} ></div> <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} + class={`${ + num_blades === 12 ? `spinner12-blade` : `spinner8-blade` + }`} ></div> <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} + class={`${ + num_blades === 12 ? `spinner12-blade` : `spinner8-blade` + }`} ></div> <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} + class={`${ + num_blades === 12 ? `spinner12-blade` : `spinner8-blade` + }`} ></div> {#if num_blades === 12} <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} + class={`${ + num_blades === 12 ? `spinner12-blade` : `spinner8-blade` + }`} ></div> <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} + class={`${ + num_blades === 12 ? `spinner12-blade` : `spinner8-blade` + }`} ></div> <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} + class={`${ + num_blades === 12 ? `spinner12-blade` : `spinner8-blade` + }`} ></div> <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} + class={`${ + num_blades === 12 ? `spinner12-blade` : `spinner8-blade` + }`} ></div> <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} + class={`${ + num_blades === 12 ? `spinner12-blade` : `spinner8-blade` + }`} ></div> <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} + class={`${ + num_blades === 12 ? `spinner12-blade` : `spinner8-blade` + }`} ></div> {/if} </div> diff --git a/apps-lib-pwa/src/lib/components/lib/logo-circle-sm.svelte b/apps-lib-pwa/src/lib/components/lib/logo-circle-sm.svelte @@ -1,14 +0,0 @@ -<div - class={`relative flex flex-row h-12 w-12 justify-center items-center bg-ly2 rounded-full`} -> - <p - class={`font-sans font-[900] text-[1.5rem] text-ly0-gl -tracking-[0.4rem] -translate-x-[2px]`} - > - {"»`,"} - </p> - <p - class={`font-sans font-[900] text-[1.5rem] text-ly0-gl translate-x-[3px]`} - > - {"-"} - </p> -</div> diff --git a/apps-lib-pwa/src/lib/components/lib/logo-letters.svelte b/apps-lib-pwa/src/lib/components/lib/logo-letters.svelte @@ -1,3 +0,0 @@ -<p class={`font-sansd italic font-[700] text-[1.7rem] text-ly0-gl lowercase`}> - {`radroots`} -</p> diff --git a/apps-lib-pwa/src/lib/components/lib/select-menu.svelte b/apps-lib-pwa/src/lib/components/lib/select-menu.svelte @@ -10,7 +10,7 @@ children, }: { basis: ISelect; - value: string; + value?: string; el_wrap?: HTMLDivElement | null; el_select?: HTMLSelectElement | null; children?: Snippet; @@ -30,7 +30,9 @@ bind:this={el_wrap} > <div - class={`${fmt_cl(basis.classes)} z-20 absolute top-0 left-0 flex flex-row h-full w-full justify-end items-center ${classes_layer}`} + class={`${fmt_cl( + basis.classes, + )} z-20 absolute top-0 left-0 flex flex-row h-full w-full justify-end items-center ${classes_layer}`} > <select class={`select select-ghost h-full w-full bg-transparent focus:border-0 focus:outline-0 text-transparent focus:text-transparent`} diff --git a/apps-lib-pwa/src/lib/components/lib/select-pwa.svelte b/apps-lib-pwa/src/lib/components/lib/select-pwa.svelte @@ -1,126 +0,0 @@ -<script lang="ts"> - import { browser } from "$app/environment"; - import { - Glyph, - type ISelect, - fmt_cl, - idb, - parse_layer, - } from "@radroots/apps-lib"; - import { handle_err } from "@radroots/utils"; - import { onMount } from "svelte"; - - let { - basis, - value = $bindable(``), - el = $bindable(null), - }: { - basis: ISelect; - value: string; - el?: HTMLSelectElement | null; - } = $props(); - - const id = $derived(basis?.id ? basis.id : null); - - const layer = $derived( - typeof basis?.layer === `boolean` - ? parse_layer(0) - : parse_layer(basis.layer), - ); - - const classes_layer = $derived( - typeof basis?.layer === `boolean` - ? `` - : !value - ? `text-ly${layer}-gl/60` - : `text-ly${layer}-gl_d`, - ); - - onMount(async () => { - try { - if (id && basis?.sync_init && browser) { - const sync_val = await idb.get(id); - await idb.set(id, sync_val || ``); - } - } catch (e) { - handle_err(e, `on_mount`); - } - }); - - $effect(() => { - if (browser && id && basis?.sync) { - (async () => { - await idb.set(id, value); - })(); - } - }); - - const handle_on_change = async (el: HTMLSelectElement): Promise<void> => { - try { - const opt = basis.options - .map((i) => i.entries) - .reduce((_, j) => j, []) - .find((k) => k.value === el?.value); - if (el) el.value = value; - if (basis?.sync && id && browser) await idb.set(id, value); - if (basis.callback && opt) await basis.callback(opt); - } catch (e) { - console.log(`(error) handle_on_change `, e); - } - }; -</script> - -{#if basis?.show_arrows === "l"} - <div class={`flex flex-row pr-[2px] justify-center items-center`}> - <Glyph - basis={{ - key: `caret-up-down`, - dim: `xs`, - - classes: `text-ly${layer}-gl translate-y-[1px]`, - }} - /> - </div> -{/if} -<select - bind:this={el} - bind:value - onchange={async ({ currentTarget: el }) => { - handle_on_change(el); - }} - {id} - class={`${fmt_cl(basis.classes)} z-10 el-select ${classes_layer}`} -> - {#each basis.options as opt_g} - {#if opt_g.group} - <optgroup> - {#each opt_g.entries as opt} - <option - label={opt_g.group === true - ? `-`.repeat(21) - : opt_g.group || ``} - > - {opt.label} - </option> - {/each} - </optgroup> - {:else} - {#each opt_g.entries as opt} - <option value={opt.value} disabled={!!opt.disabled}> - {opt.label} - </option> - {/each} - {/if} - {/each} -</select> -{#if basis?.show_arrows === "r"} - <div class={`flex flex-row pl-[2px] justify-center items-center`}> - <Glyph - basis={{ - key: `caret-up-down`, - dim: `xs`, - classes: `text-ly${layer}-gl`, - }} - /> - </div> -{/if} diff --git a/apps-lib-pwa/src/lib/components/lib/wrap-border.svelte b/apps-lib-pwa/src/lib/components/lib/wrap-border.svelte @@ -1,22 +0,0 @@ -<script lang="ts"> - import { type IClOpt, fmt_cl } from "@radroots/apps-lib"; - import type { Snippet } from "svelte"; - - let { - basis, - children, - }: { - basis: IClOpt; - children: Snippet; - } = $props(); -</script> - -<div - class={`${fmt_cl(basis.classes)} relative flex flex-col w-full py-[4px] px-[4px] justify-start items-center rounded-[32px] overflow-hidden bg-white shadow-sm`} -> - <div - class={`flex flex-row h-full w-full justify-center items-center bg-white/30 overflow-hidden rounded-[28px]`} - > - {@render children()} - </div> -</div> diff --git a/apps-lib-pwa/src/lib/components/map/map-marker-area-display.svelte b/apps-lib-pwa/src/lib/components/map/map-marker-area-display.svelte @@ -1,57 +0,0 @@ -<script lang="ts"> - import { Fade, Glyph, type IBasisOpt } from "@radroots/apps-lib"; - - let { - basis = undefined, - }: { - basis?: IBasisOpt<{ - primary: string; - admin: string; - country: string; - }>; - } = $props(); -</script> - -{#if basis} - <Fade - basis={{ - classes: `flex-col w-full justify-center items-start`, - }} - > - <div - class={`flex flex-col w-fit px-5 py-[10px] justify-start items-start bg-ly1 rounded-3xl shadow-lg`} - > - <div class={`flex flex-col w-full gap-1 justify-start items-start`}> - <div class={`flex flex-row gap-1 justify-start items-center`}> - <p - class={`font-sans font-[600] text-[0.95rem] text-ly2-gl`} - > - {basis.primary} - </p> - <Glyph - basis={{ - classes: `text-ly2-gl -translate-y-[2px]`, - dim: `xs`, - - key: `map-pin-simple`, - }} - /> - </div> - <div - class={`flex flex-row w-full gap-1 justify-start items-center`} - > - <p - class={`font-sans font-[600] text-[0.95rem] tracking-tight text-ly2-gl`} - > - {`${basis.admin},`} - </p> - <p - class={`font-sans font-[600] text-[0.95rem] tracking-tight text-ly2-gl`} - > - {`${basis.country}`} - </p> - </div> - </div> - </div> - </Fade> -{/if} diff --git a/apps-lib-pwa/src/lib/components/map/map-marker-area.svelte b/apps-lib-pwa/src/lib/components/map/map-marker-area.svelte @@ -1,47 +0,0 @@ -<script lang="ts"> - import type { IMapMarkerArea } from "$lib/types/components"; - import { get_context } from "@radroots/apps-lib"; - import { - type GeocoderReverseResult, - type GeolocationPoint, - } from "@radroots/utils"; - import { Marker, Popup } from "svelte-maplibre"; - import MapMarkerAreaDisplay from "./map-marker-area-display.svelte"; - - const { lc_geocode } = get_context(`lib`); - - let { - basis, - map_geop = $bindable(), - map_geoc = $bindable(undefined), - }: { - basis: IMapMarkerArea; - map_geop: GeolocationPoint; - map_geoc?: GeocoderReverseResult | undefined; - } = $props(); -</script> - -<Marker - bind:lngLat={map_geop} - draggable={!basis.no_drag} - class={`flex flex-row h-[100px] w-[100px] bg-blue-400/20 border-[2px] border-white justify-center items-center rounded-full shadow-lg`} - ondragend={async () => { - if (!map_geop) return; - const geoc = await lc_geocode(map_geop); - if (geoc) map_geoc = geoc; - }} -> - {#if basis.show_display} - <Popup open={basis.show_display} offset={[0, -55]}> - <MapMarkerAreaDisplay - basis={map_geoc - ? { - primary: map_geoc.name, - admin: map_geoc.admin1_name, - country: map_geoc.country_name, - } - : undefined} - /> - </Popup> - {/if} -</Marker> diff --git a/apps-lib-pwa/src/lib/components/map/map.svelte b/apps-lib-pwa/src/lib/components/map/map.svelte @@ -1,42 +0,0 @@ -<script lang="ts"> - import { cfg_map } from "$lib/utils/map"; - import { type IClOpt, fmt_cl, theme_mode } from "@radroots/apps-lib"; - import type { Snippet } from "svelte"; - import { MapLibre } from "svelte-maplibre"; - - let { - basis = undefined, - map = $bindable(undefined), - children, - }: { - basis?: IClOpt & { - interactive?: boolean; - zoom_click_off?: boolean; - }; - map?: maplibregl.Map; - interactive?: boolean; - children: Snippet; - } = $props(); - - const interactive = $derived( - typeof basis?.interactive === `boolean` ? basis?.interactive : true, - ); - - const zoomOnDoubleClick = $derived( - typeof basis?.zoom_click_off === `boolean` - ? basis?.zoom_click_off - : true, - ); -</script> - -<MapLibre - bind:map - class="{fmt_cl(basis?.classes)} relative h-full w-full" - zoom={10} - style={cfg_map.styles.base[$theme_mode]} - attributionControl={false} - {interactive} - {zoomOnDoubleClick} -> - {@render children()} -</MapLibre> diff --git a/apps-lib-pwa/src/lib/components/navigation/navigation-tabs.svelte b/apps-lib-pwa/src/lib/components/navigation/navigation-tabs.svelte @@ -1,100 +0,0 @@ -<script lang="ts"> - import { goto } from "$app/navigation"; - import { page } from "$app/state"; - import { app_lo } from "$lib/stores/app"; - import { Flex, Glyph } from "@radroots/apps-lib"; -</script> - -<div - class={`fixed bottom-0 left-0 h-nav_tabs_${$app_lo} flex flex-row w-full pt-2 justify-center items-start`} -> - <div class={`flex flex-row justify-between gap-10 items-center`}> - <div - class={`grid grid-cols-4 flex flex-row h-[3.1rem] px-6 gap-6 justify-start items-center bg-ly1 rounded-full backdrop-blur-lg`} - > - <button - class={`col-span-1 flex flex-row justify-center items-center`} - onclick={async () => { - await goto(`/`); - }} - > - <Glyph - basis={{ - classes: `text-[26px] text-ly0-gl/80 rotate-90`, - key: `columns`, - weight: page.url.pathname === `/` ? `fill` : `bold`, - }} - /> - </button> - <button - class={`relative col-span-1 flex flex-row justify-center items-center`} - onclick={async () => { - await goto(`/search`); - }} - > - <Glyph - basis={{ - classes: `text-[24px] text-ly0-gl/80`, - key: `magnifying-glass`, - weight: page.url.pathname.includes(`search`) - ? `fill` - : `bold`, - }} - /> - </button> - <button - class={`relative col-span-1 flex flex-row justify-center items-center`} - onclick={async () => { - goto(`/profile`); - }} - > - <Glyph - basis={{ - classes: `text-[24px] text-ly0-gl/80`, - key: `user`, - weight: page.url.pathname.includes(`profile`) - ? `fill` - : `bold`, - }} - /> - </button> - <button - class={`relative col-span-1 flex flex-row h-full justify-center items-center`} - onclick={async () => { - await goto(`/notifications`); - }} - > - <Glyph - basis={{ - classes: `text-[24px] text-ly0-gl/80`, - key: `bell`, - weight: page.url.pathname.includes(`notifications`) - ? `fill` - : `bold`, - }} - /> - <div - class={`absolute top-2 -right-1 flex flex-row justify-start items-center`} - > - <div - class={`flex flex-row h-2 w-2 justify-start items-center bg-yellow-400 rounded-full`} - > - <Flex /> - </div> - </div> - </button> - </div> - <button - class={`flex flex-row h-[3.1rem] w-[3.1rem] justify-center items-center bg-ly1 rounded-full backdrop-blur-lg`} - onclick={async () => {}} - > - <Glyph - basis={{ - classes: `text-[22px] text-ly0-gl/80`, - - key: `plus`, - }} - /> - </button> - </div> -</div> diff --git a/apps-lib-pwa/src/lib/components/navigation/page-header.svelte b/apps-lib-pwa/src/lib/components/navigation/page-header.svelte @@ -1,55 +0,0 @@ -<script lang="ts"> - import { app_lo, ph_blur } from "$lib/stores/app"; - import type { IPageHeader } from "$lib/types/components"; - import { callback_route, Flex } from "@radroots/apps-lib"; - import type { Snippet } from "svelte"; - import { fade } from "svelte/transition"; - - let { - basis, - children, - }: { - basis: IPageHeader<string>; - children?: Snippet; - } = $props(); -</script> - -{#if $ph_blur} - <div - in:fade={{ duration: 50 }} - out:fade={{ delay: 50, duration: 200 }} - class={`z-20 fixed top-0 left-0 flex flex-row h-nav_page_header_${$app_lo} w-full justify-center items-center bg-ly0-blur/30 backdrop-blur-lg`} - > - <Flex /> - </div> -{/if} -<div - class={`z-20 sticky top-0 flex flex-row min-h-nav_page_header_${$app_lo} h-nav_page_header_${$app_lo} w-full px-6 justify-between items-center`} -> - <div class={`flex flex-row justify-start items-center`}> - <button - class={`flex flex-row justify-center items-center`} - onclick={async () => { - if (basis.callback_route) - await callback_route(basis.callback_route); - }} - > - <p - class={`font-sansd font-[700] text-2xl text-ly0-gl capitalize max-w-lo_${$app_lo} truncate`} - > - {basis.label || ``} - </p> - </button> - </div> - {#if children} - {#if !$ph_blur} - <div - in:fade={{ duration: 50 }} - out:fade={{ delay: 50, duration: 200 }} - class={`flex flex-row justify-center items-center`} - > - {@render children()} - </div> - {/if} - {/if} -</div> diff --git a/apps-lib-pwa/src/lib/components/navigation/page-toolbar.svelte b/apps-lib-pwa/src/lib/components/navigation/page-toolbar.svelte @@ -1,57 +0,0 @@ -<script lang="ts"> - import { goto } from "$app/navigation"; - import { app_lo } from "$lib/stores/app"; - import type { IPageToolbar } from "$lib/types/components"; - import { type IBasisOpt, Glyph } from "@radroots/apps-lib"; - import type { Snippet } from "svelte"; - import LogoCircleSm from "../lib/logo-circle-sm.svelte"; - import LogoLetters from "../lib/logo-letters.svelte"; - import PageHeader from "./page-header.svelte"; - - let { - basis = undefined, - header_option, - }: { - basis?: IBasisOpt<IPageToolbar<string>>; - header_option?: Snippet; - } = $props(); -</script> - -<div - class={`flex flex-row min-h-nav_page_toolbar_${$app_lo} h-nav_page_toolbar_${$app_lo} w-full px-6 justify-between items-end`} -> - <div class={`flex flex-row w-full justify-between items-center`}> - <button - class={`flex flex-row gap-2 justify-start items-center`} - onclick={async () => { - if (basis?.callback) await basis.callback(); - else await goto(`/`); - }} - > - <LogoCircleSm /> - <LogoLetters /> - </button> - <button - class={`flex flex-row justify-center items-center`} - onclick={async () => { - await goto(`/settings`); - }} - > - <Glyph - basis={{ - classes: `text-ly0-gl`, - dim: `lg`, - - key: `gear`, - }} - /> - </button> - </div> -</div> -{#if basis?.header} - <PageHeader basis={basis.header}> - {#if header_option} - {@render header_option()} - {/if} - </PageHeader> -{/if} diff --git a/apps-lib-pwa/src/lib/components/trellis/trellis-default-label.svelte b/apps-lib-pwa/src/lib/components/trellis/trellis-default-label.svelte @@ -1,37 +0,0 @@ -<script lang="ts"> - import type { ITrellisDefaultLabel } from "$lib/types/components/trellis"; - import { fmt_cl } from "@radroots/apps-lib"; - import type { ThemeLayer } from "@radroots/themes"; - - let { - layer, - labels, - classes = ``, - }: { - layer: ThemeLayer; - labels: ITrellisDefaultLabel[]; - classes?: string; - } = $props(); -</script> - -<div class={`${fmt_cl(classes)} flex flex-row`}> - <p class={`font-sans text-trellis_ti text-ly${layer}-gl-shade`}> - {#each labels as label} - <span class={`${fmt_cl(label.classes)} font-sans text-trellis_ti`}> - {#if `callback` in label} - <button - class={``} - onclick={async () => { - if (`callback` in label && label.callback) - await label.callback(); - }} - > - {label.label} - </button> - {:else} - {label.label} - {/if} - </span> - {/each} - </p> -</div> diff --git a/apps-lib-pwa/src/lib/components/trellis/trellis-end.svelte b/apps-lib-pwa/src/lib/components/trellis/trellis-end.svelte @@ -1,36 +0,0 @@ -<script lang="ts"> - import type { ITrellisBasisTouchEnd } from "$lib/types/components/trellis"; - import { Glyph } from "@radroots/apps-lib"; - import type { ThemeLayer } from "@radroots/themes"; - - let { - basis, - layer, - hide_active, - }: { - basis: ITrellisBasisTouchEnd; - layer: ThemeLayer; - hide_active: boolean; - } = $props(); -</script> - -<div - class={`absolute top-0 right-0 h-full w-max flex flex-row justify-center items-center`} -> - <button - class={`flex pr-3`} - onclick={async (ev) => { - if (basis.callback) await basis.callback(ev); - }} - > - {#if basis.glyph} - <Glyph - basis={{ - classes: `text-ly${layer}-gl-shade ${hide_active ? `` : `group-active:text-ly${layer}-gl_a`} translate-y-[1px] opacity-70`, - dim: `xs+`, - ...basis.glyph, - }} - /> - {/if} - </button> -</div> diff --git a/apps-lib-pwa/src/lib/components/trellis/trellis-input.svelte b/apps-lib-pwa/src/lib/components/trellis/trellis-input.svelte @@ -1,86 +0,0 @@ -<script lang="ts"> - import type { ITrellisBasisInput } from "$lib/types/components/trellis"; - import { fmt_trellis } from "$lib/utils/app"; - import { fmt_cl, Glyph } from "@radroots/apps-lib"; - import type { ThemeLayer } from "@radroots/themes"; - import InputPwa from "../lib/input-pwa.svelte"; - import LoadSymbol from "../lib/load-symbol.svelte"; - - let { - basis, - layer, - hide_border_b, - hide_border_t, - }: { - basis: ITrellisBasisInput; - layer: ThemeLayer; - hide_border_b: boolean; - hide_border_t: boolean; - } = $props(); -</script> - -<div class={`flex flex-row flex-grow h-full w-full`}> - <div - class={`${fmt_trellis(hide_border_b, hide_border_t)} flex flex-row h-line w-full justify-start items-center border-t-line border-ly${layer}-edge overflow-hidden`} - > - {#if basis.line_label && basis.line_label.value} - <div - class={`${fmt_cl(basis.line_label.classes)} flex flex-row h-full justify-start items-center overflow-x-hidden`} - > - <p class={`font-sans text-ly${layer}-gl_b`}> - {basis.line_label.value} - </p> - </div> - {/if} - <div - class={`relative flex flex-row flex-grow h-full pr-12 justify-start items-center`} - > - <InputPwa - basis={{ - ...basis.basis, - layer: layer, - }} - /> - {#if basis.action} - {#if basis.action.visible} - <div - class={`absolute top-0 right-0 flex flex-row h-full w-12 pr-4 justify-end items-center fade-in`} - > - {#if basis.action.loading} - <div class={`flex flex-row fade-in`}> - <LoadSymbol - basis={{ - dim: `glyph-send-button`, - blades: 8, - classes: `text-ly${layer}-gl el-re`, - }} - /> - </div> - {:else} - <button - class={`group fade-in-long`} - onclick={async () => { - if (basis.action?.callback) - await basis.action.callback(); - }} - > - <Glyph - basis={basis.action.glyph - ? { - dim: `md-`, - ...basis.action.glyph, - } - : { - key: `plus`, - classes: `text-ly${layer}-gl`, - dim: `md-`, - }} - /> - </button> - {/if} - </div> - {/if} - {/if} - </div> - </div> -</div> diff --git a/apps-lib-pwa/src/lib/components/trellis/trellis-line.svelte b/apps-lib-pwa/src/lib/components/trellis/trellis-line.svelte @@ -1,57 +0,0 @@ -<script lang="ts"> - import { fmt_trellis } from "$lib/utils/app"; - import type { ThemeLayer } from "@radroots/themes"; - import type { CallbackPromiseGeneric } from "@radroots/utils"; - import type { Snippet } from "svelte"; - import LoadSymbol from "../lib/load-symbol.svelte"; - - let { - loading = false, - layer, - callback, - hide_border_b, - hide_border_t, - children, - el_end, - }: { - loading?: boolean; - layer: ThemeLayer; - callback?: CallbackPromiseGeneric<MouseEvent>; - hide_border_b: boolean; - hide_border_t: boolean; - children: Snippet; - el_end?: Snippet; - } = $props(); -</script> - -<button - class={`flex flex-row flex-grow overflow-hidden`} - onclick={async (ev) => { - if (callback) await callback(ev); - }} -> - <div - class={`${fmt_trellis(hide_border_b, hide_border_t)} flex flex-row h-full w-full justify-center items-center border-t-line border-ly${layer}-edge el-re`} - > - {#if loading} - <div - class={`flex flex-row h-full w-full justify-center items-center`} - > - <LoadSymbol basis={{ dim: `sm` }} /> - </div> - {:else} - <div - class={`relative group flex flex-row h-line w-full pr-[2px] justify-between items-center el-re`} - > - <div - class={`flex flex-row h-full w-trellis_display justify-between items-center`} - > - {@render children()} - </div> - {#if el_end} - {@render el_end()} - {/if} - </div> - {/if} - </div> -</button> diff --git a/apps-lib-pwa/src/lib/components/trellis/trellis-offset.svelte b/apps-lib-pwa/src/lib/components/trellis/trellis-offset.svelte @@ -1,72 +0,0 @@ -<script lang="ts"> - import type { - ITrellisBasisOffset, - ITrellisBasisOffsetMod, - } from "$lib/types/components/trellis"; - import { Flex, fmt_cl, Glyph } from "@radroots/apps-lib"; - import type { ThemeLayer } from "@radroots/themes"; - import GlyphCircle from "../lib/glyph-circle.svelte"; - import LoadSymbol from "../lib/load-symbol.svelte"; - - let { - basis = undefined, - layer, - }: { - basis?: ITrellisBasisOffset; - layer: ThemeLayer; - } = $props(); - - const mod: ITrellisBasisOffsetMod = $derived(basis?.mod ? basis.mod : `sm`); -</script> - -<div class={`flex flex-row h-full`}> - {#if mod === `sm`} - <div class={`${fmt_cl(``)} flex flex-row h-full w-[22px]`}> - <Flex /> - </div> - {:else if mod === `glyph`} - <div class={`flex flex-row pr-[2px]`}> - <div class={`${fmt_cl(``)} flex flex-row h-full w-trellisOffset`}> - <Flex /> - </div> - </div> - {:else if typeof mod === `object`} - <div - class={`flex flex-row h-full min-w-[20px] w-trellisOffset justify-center items-center pr-3`} - > - <button - class={`fade-in pl-2 translate-x-[3px] translate-y-[1px]`} - onclick={async (ev) => { - if (mod.loading) return; - else if (typeof basis !== `boolean` && basis?.callback) - await basis.callback(ev); - }} - > - {#if mod.loading} - <LoadSymbol basis={{ blades: 8, dim: `xs` }} /> - {:else if `glyph` in mod} - <Glyph - basis={{ - classes: mod.glyph.classes - ? mod.glyph.classes - : `text-ly${layer}-gl`, - ...mod.glyph, - }} - /> - {:else if `glyph_circle` in mod} - <GlyphCircle - basis={{ - classes_wrap: mod.glyph_circle?.classes_wrap, - glyph: { - classes: mod.glyph_circle?.glyph?.classes - ? mod.glyph_circle?.glyph?.classes - : `text-ly${layer}-gl`, - ...mod.glyph_circle?.glyph, - }, - }} - /> - {/if} - </button> - </div> - {/if} -</div> diff --git a/apps-lib-pwa/src/lib/components/trellis/trellis-row-display-value.svelte b/apps-lib-pwa/src/lib/components/trellis/trellis-row-display-value.svelte @@ -1,44 +0,0 @@ -<script lang="ts"> - import type { ITrellisKindDisplayValue } from "$lib/types/components/trellis"; - import { get_label_classes_kind } from "$lib/utils/app"; - import { Glyph, fmt_cl } from "@radroots/apps-lib"; - import type { ThemeLayer } from "@radroots/themes"; - - let { - basis, - layer, - hide_active, - }: { - basis: ITrellisKindDisplayValue; - layer: ThemeLayer; - hide_active: boolean; - } = $props(); -</script> - -<button - class={`z-10 flex flex-grow justify-end`} - onclick={async (ev) => { - ev.stopPropagation(); - if (basis.callback) await basis.callback(ev); - }} -> - {#if `icon` in basis} - <Glyph - basis={{ - classes: - basis.icon.classes || - `${get_label_classes_kind(layer, `shade`, hide_active)}`, - key: basis.icon.key, - dim: `sm`, - }} - /> - {:else if basis.label} - {#if `value` in basis.label} - <p - class={`${fmt_cl(basis.label.classes)} font-sans text-line_d_e line-clamp-1 text-ly0-gl-label el-re`} - > - {basis.label.value} - </p> - {/if} - {/if} -</button> diff --git a/apps-lib-pwa/src/lib/components/trellis/trellis-row-label.svelte b/apps-lib-pwa/src/lib/components/trellis/trellis-row-label.svelte @@ -1,63 +0,0 @@ -<script lang="ts"> - import { get_label_classes_kind } from "$lib/utils/app"; - import { type ILabelTupFields, fmt_cl } from "@radroots/apps-lib"; - import type { ThemeLayer } from "@radroots/themes"; - import GlyphButton from "../buttons/glyph-button.svelte"; - - let { - basis, - layer, - hide_active, - }: { - basis: ILabelTupFields; - layer: ThemeLayer; - hide_active: boolean; - } = $props(); -</script> - -<div class={`flex flex-row h-full items-center justify-between`}> - {#if basis.left && basis.left.length} - <div class={`flex flex-row h-full items-center truncate`}> - {#each basis.left as title_l} - <div - class={`${fmt_cl(title_l.classes_wrap)} flex flex-row h-full items-center ${get_label_classes_kind(layer, undefined, hide_active)} ${title_l.hide_truncate ? `` : `truncate`}`} - > - {#if `glyph` in title_l} - <div - class={`flex flex-row justify-start items-center pr-2`} - > - <GlyphButton basis={{ ...title_l.glyph }} /> - </div> - {:else if `value` in title_l} - <p - class={`${fmt_cl(title_l.classes)} font-sans text-line_d ${title_l.hide_truncate ? `` : `truncate`} el-re`} - > - {title_l.value || ``} - </p> - {/if} - </div> - {/each} - </div> - {/if} - {#if basis.right && basis.right.length} - <div - class={`flex flex-row h-full w-content items-center justify-end pr-4`} - > - {#each basis.right.reverse() as title_r} - <div - class={`${fmt_cl(title_r.classes_wrap)} flex flex-row h-full gap-1 items-center ${title_r.hide_truncate ? `` : `truncate`}`} - > - {#if `glyph` in title_r} - <GlyphButton basis={{ ...title_r.glyph }} /> - {:else if `value` in title_r} - <p - class={`${fmt_cl(title_r.classes)} font-sans text-line_d text-ly${layer}-gl_d ${title_r.hide_truncate ? `` : `truncate`} el-re`} - > - {title_r.value || ``} - </p> - {/if} - </div> - {/each} - </div> - {/if} -</div> diff --git a/apps-lib-pwa/src/lib/components/trellis/trellis-select.svelte b/apps-lib-pwa/src/lib/components/trellis/trellis-select.svelte @@ -1,65 +0,0 @@ -<script lang="ts"> - import type { ITrellisBasisSelect } from "$lib/types/components/trellis"; - import type { ThemeLayer } from "@radroots/themes"; - import LoadSymbol from "../lib/load-symbol.svelte"; - import SelectMenu from "../lib/select-menu.svelte"; - import TrellisEnd from "./trellis-end.svelte"; - import TrellisLine from "./trellis-line.svelte"; - import TrellisRowDisplayValue from "./trellis-row-display-value.svelte"; - import TrellisRowLabel from "./trellis-row-label.svelte"; - - let { - basis, - layer, - hide_active, - hide_border_b, - hide_border_t, - }: { - basis: ITrellisBasisSelect; - layer: ThemeLayer; - hide_active: boolean; - hide_border_b: boolean; - hide_border_t: boolean; - } = $props(); - - const loading = $derived( - typeof basis?.loading === `boolean` ? basis.loading : false, - ); - - const value = $derived(basis.el.value); -</script> - -<TrellisLine - {layer} - {loading} - {hide_border_b} - {hide_border_t} - callback={basis.callback} -> - <TrellisRowLabel basis={basis.label} {layer} {hide_active} /> - {#if basis.display} - <div class={`flex flex-row pr-3 justify-center items-end`}> - <SelectMenu {value} basis={basis.el}> - {#if basis.display.loading} - <div - class={`flex flex-row h-full w-full justify-end items-center`} - > - <LoadSymbol basis={{ dim: `sm` }} /> - </div> - {:else} - <TrellisRowDisplayValue - basis={{ ...basis.display }} - {layer} - {hide_active} - /> - {/if} - </SelectMenu> - </div> - {/if} - - {#snippet el_end()} - {#if basis.end} - <TrellisEnd basis={basis.end} {layer} {hide_active} /> - {/if} - {/snippet} -</TrellisLine> diff --git a/apps-lib-pwa/src/lib/components/trellis/trellis-title.svelte b/apps-lib-pwa/src/lib/components/trellis/trellis-title.svelte @@ -1,69 +0,0 @@ -<script lang="ts"> - import type { ITrellisTitle } from "$lib/types/components/trellis"; - import { Flex, fmt_cl, Glyph } from "@radroots/apps-lib"; - import type { ThemeLayer } from "@radroots/themes"; - import LabelSwap from "../lib/label-swap.svelte"; - - let { - basis, - layer = 0, - }: { - basis: ITrellisTitle; - layer: ThemeLayer; - } = $props(); - - const mod = $derived(basis?.mod ? basis.mod : `sm`); -</script> - -<div - class={`${fmt_cl(basis.classes)} flex flex-row h-[24px] w-full pl-[2px] gap-1 items-center`} -> - <button - class={`flex flex-row h-full w-max items-center gap-1 ${mod === `glyph` ? `pl-[36px]` : mod === `sm` ? `pl-[16px]` : ``}`} - onclick={async () => { - if (basis && basis.callback) await basis.callback(); - }} - > - {#if basis.value === true} - <Flex /> - {:else} - <p - class={`font-sans text-trellis_ti text-ly${layer}-gl-label uppercase`} - > - {basis.value || ``} - </p> - {/if} - </button> - {#if basis.link} - <button - class={`${fmt_cl(basis.link.classes)} group flex flex-row h-full w-max items-center`} - onclick={async () => { - if (basis.link && basis.link.callback) - await basis.link.callback(); - }} - > - {#if basis.link.label} - {#if `swap` in basis.link.label} - <LabelSwap basis={basis.link.label} /> - {:else if `value` in basis.link.label} - <p - class={`${fmt_cl(basis.link.label.classes)} font-sans text-trellis_ti uppercase fade-in`} - > - {basis.link.label.value || ``} - </p> - {/if} - {/if} - {#if basis.link.glyph} - <div class={`flex flex-row w-max`}> - <Glyph - basis={{ - ...basis.link.glyph, - dim: `xs-`, - classes: `${fmt_cl(basis.link.glyph.classes)} fade-in`, - }} - /> - </div> - {/if} - </button> - {/if} -</div> diff --git a/apps-lib-pwa/src/lib/components/trellis/trellis-touch.svelte b/apps-lib-pwa/src/lib/components/trellis/trellis-touch.svelte @@ -1,40 +0,0 @@ -<script lang="ts"> - import type { ITrellisBasisTouch } from "$lib/types/components/trellis"; - import type { ThemeLayer } from "@radroots/themes"; - import TrellisEnd from "./trellis-end.svelte"; - import TrellisLine from "./trellis-line.svelte"; - import TrellisRowDisplayValue from "./trellis-row-display-value.svelte"; - import TrellisRowLabel from "./trellis-row-label.svelte"; - - let { - basis, - layer, - hide_active, - hide_border_b, - hide_border_t, - }: { - basis: ITrellisBasisTouch; - layer: ThemeLayer; - hide_active: boolean; - hide_border_b: boolean; - hide_border_t: boolean; - } = $props(); -</script> - -<TrellisLine {layer} {hide_border_b} {hide_border_t} callback={basis.callback}> - <TrellisRowLabel basis={basis.label} {layer} {hide_active} /> - {#if basis.display} - <TrellisRowDisplayValue - basis={{ - ...basis.display, - }} - {layer} - {hide_active} - /> - {/if} - {#snippet el_end()} - {#if basis.end} - <TrellisEnd basis={basis.end} {layer} {hide_active} /> - {/if} - {/snippet} -</TrellisLine> diff --git a/apps-lib-pwa/src/lib/components/trellis/trellis.svelte b/apps-lib-pwa/src/lib/components/trellis/trellis.svelte @@ -1,149 +0,0 @@ -<script lang="ts"> - import { app_lo } from "$lib/stores/app"; - import type { ITrellis } from "$lib/types/components/trellis"; - import { fmt_cl, get_context, parse_layer } from "@radroots/apps-lib"; - import type { Snippet } from "svelte"; - import TrellisDefaultLabel from "./trellis-default-label.svelte"; - import TrellisInput from "./trellis-input.svelte"; - import TrellisOffset from "./trellis-offset.svelte"; - import TrellisSelect from "./trellis-select.svelte"; - import TrellisTitle from "./trellis-title.svelte"; - import TrellisTouch from "./trellis-touch.svelte"; - - const { ls } = get_context(`lib`); - - let { - basis, - el_default, - el_offset, - el_append, - }: { - basis: ITrellis; - el_default?: Snippet; - el_offset?: Snippet; - el_append?: Snippet; - } = $props(); - - const hide_border_t = $derived( - typeof basis.hide_border_top === `boolean` - ? basis.hide_border_top - : true, - ); - - const hide_border_b = $derived( - typeof basis.hide_border_bottom === `boolean` - ? basis.hide_border_bottom - : true, - ); - - const hide_rounded = $derived( - typeof basis.hide_rounded === `boolean` ? basis.hide_rounded : false, - ); - - const set_title_background = $derived( - typeof basis.set_title_background === `boolean` - ? basis.set_title_background - : false, - ); - - const set_default_background = $derived( - typeof basis.set_default_background === `boolean` - ? basis.set_default_background - : false, - ); -</script> - -<div - id={basis.id || ``} - class={`${fmt_cl(basis.classes)} flex flex-col`} - data-view={basis.view || ``} -> - <div - class={`relative flex flex-col h-auto w-lo_${$app_lo} gap-[3px] ${set_title_background ? `bg-ly${basis.layer}` : ``}`} - > - {#if basis.title && (!basis.default_el || (basis.default_el && basis.default_el.show_title))} - <TrellisTitle - basis={basis.title} - layer={parse_layer(basis.layer - 1)} - /> - {/if} - {#if basis.default_el} - <div - class={`flex flex-col h-auto w-full justify-center items-center`} - > - {#if el_default} - {@render el_default()} - {:else if basis.default_el} - <TrellisDefaultLabel - layer={parse_layer(basis.layer - 1)} - labels={basis.default_el.labels - ? basis.default_el.labels - : [ - { - label: `${$ls(`common.no_items_to_display`)}.`, - }, - ]} - /> - {/if} - </div> - {:else if basis.list} - <div class={`flex flex-col w-full justify-center items-center`}> - {#each basis.list as li} - {#if li} - <div - class={`${li.hide_field ? `hidden` : ``} group flex flex-row h-full w-full justify-end items-center bg-ly${basis.layer} ${li.full_rounded ? `rounded-touch` : ``} ${hide_rounded ? `` : `first:rounded-t-2xl last:rounded-b-2xl`} ${!li.hide_active ? `active:bg-ly${basis.layer}_a` : ``} el-re`} - > - <div - class={`flex flex-row h-full w-full gap-1 items-center overflow-y-hidden`} - > - {#if !basis.hide_offset} - <TrellisOffset - basis={li.offset} - layer={basis.layer} - /> - {/if} - {#if el_offset} - {@render el_offset()} - {/if} - {#if `touch` in li && li.touch} - <TrellisTouch - basis={li.touch} - layer={basis.layer} - {hide_border_b} - {hide_border_t} - hide_active={!!li.hide_active} - /> - {:else if `input` in li && li.input} - <TrellisInput - basis={li.input} - layer={basis.layer} - {hide_border_b} - {hide_border_t} - /> - {:else if `select` in li && li.select} - <TrellisSelect - basis={li.select} - layer={basis.layer} - {hide_border_b} - {hide_border_t} - hide_active={!!li.hide_active} - /> - {/if} - </div> - </div> - {/if} - {/each} - </div> - {/if} - </div> - {#if el_append} - <div - class={`flex flex-col w-full ${set_default_background ? `bg-ly${basis.layer}` : ``}`} - > - {@render el_append()} - </div> - {/if} -</div> -<div - class={`hidden group-first:border-t-0 group-first:border-t-line group-first:border-b-0 group-first:border-b-line`} -></div> diff --git a/apps-lib-pwa/src/lib/features/farm/farms-add-casli-detail.svelte b/apps-lib-pwa/src/lib/features/farm/farms-add-casli-detail.svelte @@ -1,98 +0,0 @@ -<script lang="ts"> - import FormLineLedger from "$lib/components/forms/form-line-ledger.svelte"; - import { CarouselItem, get_context } from "@radroots/apps-lib"; - import { area_units, form_fields } from "@radroots/utils"; - - const { ls } = get_context(`lib`); - - let { - val_farmname = $bindable(``), - val_farmaddress = $bindable(``), - val_farmarea = $bindable(``), - val_farmarea_unit = $bindable(``), - val_farmcontact = $bindable(``), - farm_geop_lat, - farm_geop_lng, - }: { - val_farmname: string; - val_farmaddress: string; - val_farmarea: string; - val_farmarea_unit: string; - val_farmcontact: string; - farm_geop_lat: string; - farm_geop_lng: string; - } = $props(); -</script> - -<CarouselItem> - <div - class={`flex flex-col h-[100vh] w-full px-6 pt-2 gap-4 justify-start items-center`} - > - <FormLineLedger - bind:value={val_farmaddress} - basis={{ - id: `farm_location`, - label: `${$ls(`common.farm_location`)}`, - input: { - placeholder: `${$ls(`icu.enter_*`, { value: `${$ls(`common.farm_location`)}`.toLowerCase() })}`, - }, - }} - /> - - <FormLineLedger - basis={{ - id: `farm_coordinates`, - label: `${$ls(`common.farm_coordinates`)}`, - display_value: - farm_geop_lat && farm_geop_lng - ? `${farm_geop_lat}, ${farm_geop_lng}` - : undefined, - input: - farm_geop_lat && farm_geop_lng - ? undefined - : { - placeholder: `${$ls(`icu.enter_*`, { value: `${$ls(`common.farm_coordinates`)}`.toLowerCase() })}`, - }, - }} - /> - <FormLineLedger - bind:value={val_farmname} - basis={{ - id: `farm_name`, - label: `${$ls(`common.farm_name`)}`, - input: { - placeholder: `${$ls(`icu.enter_*`, { value: `${$ls(`common.farm_name`)}`.toLowerCase() })}`, - }, - }} - /> - <FormLineLedger - bind:value={val_farmarea} - bind:value_label_sel={val_farmarea_unit} - basis={{ - id: `farm_size`, - label: `${$ls(`common.farm_size`)}`, - label_select: { - label: `${$ls(`units.area.${val_farmarea_unit}_ab`)}`, - entries: area_units.map((i) => ({ - value: i, - label: `${$ls(`units.area.${i}`)}`, - })), - }, - input: { - placeholder: `${`${$ls(`icu.enter_*`, { value: `${$ls(`common.farm_size`)}`.toLowerCase() })}`} ${`${$ls(`units.area.${val_farmarea_unit}_pl`)}`.toLowerCase()}`, - field: form_fields.farm_size, - }, - }} - /> - <FormLineLedger - bind:value={val_farmcontact} - basis={{ - id: `farm_contact`, - label: `${$ls(`common.farm_contact`)}`, - input: { - placeholder: `${$ls(`icu.enter_*`, { value: `${$ls(`common.contact_name`)}`.toLowerCase() })}`, - }, - }} - /> - </div> -</CarouselItem> diff --git a/apps-lib-pwa/src/lib/features/farm/farms-add-casli-map.svelte b/apps-lib-pwa/src/lib/features/farm/farms-add-casli-map.svelte @@ -1,94 +0,0 @@ -<script lang="ts"> - import WrapBorder from "$lib/components/lib/wrap-border.svelte"; - import MapMarkerArea from "$lib/components/map/map-marker-area.svelte"; - import Map from "$lib/components/map/map.svelte"; - import { app_lo } from "$lib/stores/app"; - import { focus_map_marker } from "$lib/utils/map"; - import { - CarouselItem, - Fade, - geop_is_valid, - get_context, - } from "@radroots/apps-lib"; - import { - handle_err, - type GeocoderReverseResult, - type GeolocationPoint, - } from "@radroots/utils"; - import { onMount } from "svelte"; - - const { lc_geop_current, lc_geocode } = get_context(`lib`); - - let { - map_geoc = $bindable(undefined), - map_geop = $bindable(undefined), - farm_geop_lat, - farm_geop_lng, - }: { - map_geoc: GeocoderReverseResult | undefined; - map_geop: GeolocationPoint | undefined; - farm_geop_lat: string; - farm_geop_lng: string; - } = $props(); - - let map: maplibregl.Map | undefined = $state(undefined); - - const is_valid_geop = $derived(geop_is_valid(map_geop)); - - onMount(async () => { - try { - const geop = await lc_geop_current(); - if (!geop) return; - map_geop = { ...geop }; - const geoc = await lc_geocode(geop); - if (!geoc) return; - map_geoc = geoc; - if (map && map_geop) map.setCenter([map_geop.lng, map_geop.lat]); - focus_map_marker(); - } catch (e) { - handle_err(e, `on_mount`); - } - }); -</script> - -<CarouselItem> - <div - class={`flex flex-col h-[100vh] w-full px-6 gap-4 justify-start items-center`} - > - <WrapBorder basis={{ classes: `h-lo_view_main_${$app_lo}` }}> - <Map bind:map> - {#if map_geop} - <MapMarkerArea - bind:map_geop - bind:map_geoc - basis={{ - show_display: true, - }} - /> - {/if} - </Map> - </WrapBorder> - {#if is_valid_geop} - <Fade> - <div - class={`flex flex-col w-full gap-1 justify-center items-center`} - > - <div - class={`flex flex-row w-full gap-2 justify-center items-center`} - > - <p - class={`font-sans font-[500] text-ly0-gl tracking-tightest`} - > - {farm_geop_lat} - </p> - <p - class={`font-sans font-[500] text-ly0-gl tracking-tightest`} - > - {farm_geop_lng} - </p> - </div> - </div> - </Fade> - {/if} - </div> -</CarouselItem> diff --git a/apps-lib-pwa/src/lib/features/farm/farms-display-li-el.svelte b/apps-lib-pwa/src/lib/features/farm/farms-display-li-el.svelte @@ -1,109 +0,0 @@ -<script lang="ts"> - import MapMarkerArea from "$lib/components/map/map-marker-area.svelte"; - import Map from "$lib/components/map/map.svelte"; - import type { FarmExtended } from "$lib/views/farms/farm"; - import { get_context } from "@radroots/apps-lib"; - import { - fmt_geolocation_address, - geol_lat_fmt, - geol_lng_fmt, - parse_geol_point_tup, - parse_tup_geop_point, - type CallbackPromiseGeneric, - type GeolocationPointTuple, - } from "@radroots/utils"; - import { onMount } from "svelte"; - - const { ls, locale } = get_context(`lib`); - - let { - basis, - on_handle_farm_view, - }: { - basis: FarmExtended; - on_handle_farm_view: CallbackPromiseGeneric<string>; - } = $props(); - - let map: maplibregl.Map | undefined = $state(undefined); - let map_center: GeolocationPointTuple = $state([0, 0]); - - onMount(async () => { - if (basis.location?.point) - map_center = parse_geol_point_tup(basis.location.point); - if (map) map.setCenter(map_center); - }); - - const map_geop = $derived(parse_tup_geop_point(map_center)); - - const farm_addr_fmt = $derived( - basis.location?.address - ? fmt_geolocation_address(basis.location.address) - : ``, - ); - - const farm_geop_lat = $derived( - basis.location?.point - ? geol_lat_fmt(basis.location.point.lat, `dms`, $locale, 3) - : ``, - ); - - const farm_geop_lng = $derived( - basis.location?.point - ? geol_lng_fmt(basis.location.point.lng, `dms`, $locale, 3) - : ``, - ); -</script> - -<button - class={`z-10 relative flex flex-col w-full p-4 gap-3 justify-start items-center bg-ly1 ly1-active-raise-less ly1-active-ring rounded-3xl el-re`} - onclick={async () => { - if (basis.farm.id) await on_handle_farm_view(basis.farm.id); - }} -> - <div class={`flex flex-col w-full gap-2 justify-center items-center`}> - <div class={`flex flex-row w-full justify-between items-center`}> - <p class={`font-sans font-[500] text-3xl text-ly0-gl`}> - {basis.farm.name} - </p> - - <div - class={`flex flex-row h-6 px-2 py-1 justify-center items-center bg-lime-400 rounded-lg`} - > - <p class={`font-sans font-[700] text-white`}> - {`${$ls(`common.farm`)}`} - </p> - </div> - </div> - <div class={`flex flex-col w-full justify-center items-center`}> - <div class={`flex flex-row w-full justify-start items-center`}> - <p class={`font-sans font-[500] text-lg text-ly0-gl`}> - {farm_addr_fmt} - </p> - </div> - <div class={`flex flex-row w-full justify-start items-center`}> - <p class={`font-sans font-[500] text-lg text-ly0-gl`}> - {farm_geop_lat && farm_geop_lng - ? `${farm_geop_lat}, ${farm_geop_lng}` - : ``} - </p> - </div> - </div> - </div> - <div - class={`flex flex-col h-[16rem] w-full justify-center items-center rounded-2xl overflow-hidden`} - > - <Map - bind:map - basis={{ - interactive: false, - }} - > - <MapMarkerArea - {map_geop} - basis={{ - no_drag: true, - }} - /> - </Map> - </div> -</button> diff --git a/apps-lib-pwa/src/lib/features/farm/farms-products-review-card.svelte b/apps-lib-pwa/src/lib/features/farm/farms-products-review-card.svelte @@ -1,124 +0,0 @@ -<script lang="ts"> - import { app_lo } from "$lib/stores/app"; - import type { IViewFarmsProductsAddSubmitPayload } from "$lib/types/views"; - import { get_context, Glyph, ImagePath, symbols } from "@radroots/apps-lib"; - import { - parse_currency_marker, - parse_geocode_address, - } from "@radroots/utils"; - - const { ls, locale } = get_context(`lib`); - - let { - basis, - }: { - basis: { - data: IViewFarmsProductsAddSubmitPayload | undefined; - }; - } = $props(); - - //@todo -</script> - -<div - class={`flex flex-col h-[20rem] w-lo_line_entry_${$app_lo} justify-start items-start rounded-touch bg-ly1 overflow-hidden`} -> - <div class={`flex flex-row h-[10rem] w-full justify-center items-center`}> - {#if basis.data?.photos.length} - <ImagePath - basis={{ - path: basis.data.photos[0], - }} - /> - {:else} - <div - class={`flex flex-row h-full w-full justify-center items-center bg-ly2`} - > - <div class={`flex flex-col justify-start items-center`}> - <Glyph - basis={{ - classes: `text-ly0-gl`, - dim: `sm`, - key: `image-broken`, - }} - /> - <p class={`font-sans font-[400] text-sm text-ly0-gl`}> - {`No photo`} - </p> - </div> - </div> - {/if} - </div> - <div - class={`flex flex-col h-[10rem] w-full px-3 py-2 justify-start items-center`} - > - {#if basis.data} - {@const data_geoc_address = parse_geocode_address( - basis.data.geocode_result, - )} - <div class={`flex flex-row w-full justify-between items-center`}> - <div class={`flex flex-row gap-1 justify-start items-center`}> - <p - class={`font-sans font-[600] text-xl text-th-black capitalize`} - > - {basis.data.product} - </p> - </div> - <div - class={`flex flex-row gap-[2px] justify-start items-center`} - > - <p class={`font-sans font-[600] text-xl text-th-black`}> - {`${parse_currency_marker($locale, basis.data.price_currency)}${basis.data.price_amount}`} - </p> - <p class={`font-sans font-[600] text-xl text-th-black`}> - {`/`} - </p> - <p class={`font-sans font-[600] text-xl text-th-black`}> - {`${$ls(`units.mass.unit.${basis.data.price_quantity_unit}_ab`)}`} - </p> - </div> - </div> - <div class={`flex flex-row w-full justify-between items-center`}> - <div class={`flex flex-row gap-1 justify-start items-center`}> - <p - class={`font-sans font-[600] text-lg text-ly1-gl capitalize`} - > - {basis.data.process} - </p> - <p class={`font-sans font-[600] text-xl text-ly1-gl`}> - {symbols.bullet} - </p> - <p class={`font-sans font-[600] text-lg text-ly1-gl`}> - {`${basis.data.quantity_amount} ${$ls(`units.mass.unit.${basis.data.quantity_unit}_ab`)} ${basis.data.quantity_label}`} - </p> - </div> - </div> - <div class={`flex flex-row w-full justify-start items-center`}> - <p - class={`font-sans font-[400] text-sm text-th-black capitalize line-clamp-2 overflow-hidden text-ellipsis`} - > - {basis.data.description} - </p> - </div> - {#if data_geoc_address} - <div - class={`flex flex-row w-full pt-2 justify-between items-center`} - > - <div - class={`flex flex-row gap-1 justify-start items-center`} - > - <p class={`font-sans font-[600] text-th-black`}> - {`${data_geoc_address.primary}, ${data_geoc_address.admin}`} - </p> - <p class={`font-sans font-[600] text-th-black`}> - {symbols.bullet} - </p> - <p class={`font-sans font-[600] text-th-black`}> - {`${data_geoc_address.country}`} - </p> - </div> - </div> - {/if} - {/if} - </div> -</div> diff --git a/apps-lib-pwa/src/lib/index.ts b/apps-lib-pwa/src/lib/index.ts @@ -1,73 +1,10 @@ -export * from "./client/keystore-nostr.js" -export * from "./stores/app.js" -export * from "./stores/nostr.js" -export * from "./styles/lib.js" -export * from "./types/app.js" -export * from "./types/components.js" -export * from "./types/components/trellis.js" -export * from "./types/views.js" -export * from "./utils/app.js" -export * from "./utils/context.js" -export * from "./utils/map.js" -export * from "./utils/schemas/farm.js" -export * from "./utils/schemas/location-gcs.js" -export * from "./views/farms/farm.js" -export * from "./views/profile/types.js" -export { default as ButtonLabelDashed } from "./components/buttons/button-label-dashed.svelte" -export { default as ButtonLayout } from "./components/buttons/button-layout.svelte" -export { default as ButtonLayoutPair } from "./components/buttons/button-layout-pair.svelte" -export { default as ButtonRoundNav } from "./components/buttons/button-round-nav.svelte" -export { default as ButtonSimple } from "./components/buttons/button-simple.svelte" -export { default as Css } from "./components/lib/css.svelte" -export { default as EntryLine } from "./components/forms/entry-line.svelte" -export { default as EntryWrap } from "./components/forms/entry-wrap.svelte" -export { default as Farms } from "./views/farms/farms.svelte" -export { default as FarmsAdd } from "./views/farms/farms-add.svelte" -export { default as FarmsAddCasliDetail } from "./features/farm/farms-add-casli-detail.svelte" -export { default as FarmsAddCasliMap } from "./features/farm/farms-add-casli-map.svelte" -export { default as FarmsDetails } from "./views/farms/farms-details.svelte" -export { default as FarmsDisplayLiEl } from "./features/farm/farms-display-li-el.svelte" -export { default as FarmsProductsReviewCard } from "./features/farm/farms-products-review-card.svelte" -export { default as FloatPage } from "./components/lib/float-page.svelte" -export { default as FormLineLedger } from "./components/forms/form-line-ledger.svelte" -export { default as FormLineLedgerLabelSelectLabel } from "./components/forms/form-line-ledger-label-select-label.svelte" -export { default as FormLineLedgerSelect } from "./components/forms/form-line-ledger-select.svelte" -export { default as GlyphButton } from "./components/buttons/glyph-button.svelte" -export { default as GlyphButtonSimple } from "./components/buttons/glyph-button-simple.svelte" -export { default as GlyphCircle } from "./components/lib/glyph-circle.svelte" -export { default as Home } from "./views/home.svelte" -export { default as ImageUploadAddPhoto } from "./components/lib/image-upload-add-photo.svelte" -export { default as InputPwa } from "./components/lib/input-pwa.svelte" -export { default as InputValue } from "./components/lib/input-value.svelte" -export { default as LabelSwap } from "./components/lib/label-swap.svelte" -export { default as LayoutBottomButton } from "./components/layouts/layout-bottom-button.svelte" -export { default as LayoutPage } from "./components/layouts/layout-page.svelte" -export { default as LayoutTrellis } from "./components/layouts/layout-trellis.svelte" -export { default as LayoutView } from "./components/layouts/layout-view.svelte" -export { default as LayoutWindow } from "./components/layouts/layout-window.svelte" -export { default as LoadSymbol } from "./components/lib/load-symbol.svelte" -export { default as LogoCircle } from "./components/lib/logo-circle.svelte" -export { default as LogoCircleSm } from "./components/lib/logo-circle-sm.svelte" -export { default as LogoLetters } from "./components/lib/logo-letters.svelte" -export { default as Map } from "./components/map/map.svelte" -export { default as MapMarkerArea } from "./components/map/map-marker-area.svelte" -export { default as MapMarkerAreaDisplay } from "./components/map/map-marker-area-display.svelte" -export { default as NavigationTabs } from "./components/navigation/navigation-tabs.svelte" -export { default as PageHeader } from "./components/navigation/page-header.svelte" -export { default as PageToolbar } from "./components/navigation/page-toolbar.svelte" -export { default as Profile } from "./views/profile/profile.svelte" -export { default as SelectMenu } from "./components/lib/select-menu.svelte" -export { default as SelectPwa } from "./components/lib/select-pwa.svelte" -export { default as Settings } from "./views/settings.svelte" -export { default as Trellis } from "./components/trellis/trellis.svelte" -export { default as TrellisDefaultLabel } from "./components/trellis/trellis-default-label.svelte" -export { default as TrellisEnd } from "./components/trellis/trellis-end.svelte" -export { default as TrellisInput } from "./components/trellis/trellis-input.svelte" -export { default as TrellisLine } from "./components/trellis/trellis-line.svelte" -export { default as TrellisOffset } from "./components/trellis/trellis-offset.svelte" -export { default as TrellisRowDisplayValue } from "./components/trellis/trellis-row-display-value.svelte" -export { default as TrellisRowLabel } from "./components/trellis/trellis-row-label.svelte" -export { default as TrellisSelect } from "./components/trellis/trellis-select.svelte" -export { default as TrellisTitle } from "./components/trellis/trellis-title.svelte" -export { default as TrellisTouch } from "./components/trellis/trellis-touch.svelte" -export { default as WrapBorder } from "./components/lib/wrap-border.svelte" +export { default as ButtonLayoutPair } from "./components/button/button-layout-pair.svelte"; +export { default as ButtonLayout } from "./components/button/button-layout.svelte"; +export { default as EntryLine } from "./components/form/entry-line.svelte"; +export { default as EntryWrap } from "./components/form/entry-wrap.svelte"; +export { default as LayoutWindow } from "./components/layout/layout-window.svelte"; +export { default as Css } from "./components/lib/css.svelte"; +export { default as InputValue } from "./components/lib/input-value.svelte"; +export { default as LoadSymbol } from "./components/lib/load-symbol.svelte"; +export { default as LogoCircle } from "./components/lib/logo-circle.svelte"; +export { default as SelectMenu } from "./components/lib/select-menu.svelte"; diff --git a/apps-lib-pwa/src/lib/stores/nostr.ts b/apps-lib-pwa/src/lib/stores/nostr.ts @@ -1,16 +0,0 @@ -import { writable } from "svelte/store"; - -export const nostr_ndk_configured = writable(false); - -export const nostr_sync_prevent = writable(false); -export const nostr_sync_attempts = writable(0); -export const nostr_sync_attempts_max = writable(8); -export const nostr_sync_stop = writable(true); - -export const nostr_poll_relays_prevent = writable(false); -export const nostr_poll_relays_attempts = writable(0); -export const nostr_poll_relays_attempts_max = writable(0); -export const nostr_poll_relays_stop = writable(true); - -export const nostr_relays_connected = writable<string[]>([]); - diff --git a/apps-lib-pwa/src/lib/types/app.ts b/apps-lib-pwa/src/lib/types/app.ts @@ -1,3 +1,6 @@ +import type { TangleDatabaseBackup } from "@radroots/tangle-client"; +import type { IdbClientConfig } from "@radroots/utils"; + export type AppConfigRole = `farmer` | `personal` export type AppLayoutKeyIOS = `ios0` | `ios1`; @@ -26,3 +29,32 @@ export type AppWidthsResponsiveIOS = AppLayoutIOS<AppLayoutKeyWidth>; export type AppWidthsResponsiveWeb = AppLayoutWeb<AppLayoutKeyWidth>; export type LabelFieldKind = `link` | `on` | `shade`; + +export type BackupVersions = { + app: string; + tangle_sql: string; + backup_format: string; +}; + +export type ExportedAppState = { + backup_version: string; + exported_at: string; + versions: BackupVersions; + datastore: { + config: IdbClientConfig; + entries: Record<string, unknown>; + }; + nostr_keystore: { + config: IdbClientConfig; + keys: { + public_key: string; + secret_key: string; + }[]; + }; + database: { + store_key: string; + backup: TangleDatabaseBackup; + }; +}; + +export type ImportableAppState = ExportedAppState; diff --git a/apps-lib-pwa/src/lib/types/components.ts b/apps-lib-pwa/src/lib/types/components.ts @@ -1,33 +0,0 @@ -import type { CallbackRoute, GeometryScreenPositionHorizontal, ICb, ICbOpt, IDisabledOpt, IGlyph, IGlyphKey, ILoadingOpt, ILyOpt } from "@radroots/apps-lib"; -import type { CallbackPromise } from "@radroots/utils"; - -export type IButtonSimple = ILyOpt & { - label: string; - callback: CallbackPromise; - allow_propogation?: boolean; -}; - -export type IPageHeader<T extends string> = { - label: string; - callback_route?: CallbackRoute<T>; -}; - -export type IPageToolbar<T extends string> = ICbOpt & { - header?: IPageHeader<T>; -}; - -export type IMapMarkerArea = { - show_display?: boolean; - no_drag?: boolean; -} - -export type IGlyphCircle = { - classes_wrap: string; - glyph: IGlyph -}; - -export type IFloatPage = { - posx: Omit<GeometryScreenPositionHorizontal, "center">; -}; - -export type IButtonNavRound = ICb & IDisabledOpt & ILoadingOpt & IGlyphKey; diff --git a/apps-lib-pwa/src/lib/types/components/trellis.ts b/apps-lib-pwa/src/lib/types/components/trellis.ts @@ -1,123 +0,0 @@ -import type { GlyphKey, ICbGOpt, ICbOpt, IClOpt, IGl, IGlOpt, IGlyph, IInput, ILabel, ILabelOpt, ILabelTup, ILoadingOpt, ILy, ISelect } from "@radroots/apps-lib"; -import type { CallbackPromise } from "@radroots/utils"; -import type { IGlyphCircle } from "../components"; - -export type ITrellis = ILy & - IClOpt & - ITrellisStyles & { - id?: string; - view?: string; - title?: ITrellisTitle; - description?: ITrellisDescription; - default_el?: ITrellisDefault; - list?: (ITrellisKind | undefined)[]; - hide_offset?: true; - }; - -export type ITrellisStyles = { - hide_rounded?: boolean; - hide_border_top?: boolean; - hide_border_bottom?: boolean; - set_title_background?: boolean; - set_default_background?: boolean; -}; - -export type ITrellisTitle = ICbOpt & - IClOpt & { - mod?: ITrellisBasisOffsetMod, - value: string | true; - link?: ICbOpt & - IClOpt & - IGlOpt & ILabelOpt; - }; - -export type ITrellisDescription = string | true; - -export type ITrellisBasisOffsetModKey = 'sm' | 'glyph'; -export type ITrellisBasisOffsetMod = ITrellisBasisOffsetModKey | (({ glyph: IGlyph } | { glyph_circle: IGlyphCircle }) & { - loading?: boolean; -}); - -export type ITrellisDefault = { - labels?: ITrellisDefaultLabel[]; - show_title?: boolean; -}; - -export type ITrellisDefaultLabel = ICbOpt & { - label: string; - classes?: string; -}; - -export type ITrellisKind = ( - | ITrellisKindTouch - | ITrellisKindInput - | ITrellisKindSelect -); - -export type ITrellisBasis = { - loading?: boolean; - hide_active?: boolean; - hide_field?: boolean; - offset?: ITrellisBasisOffset; - full_rounded?: boolean; -}; - -export type ITrellisBasisOffset = ICbGOpt<MouseEvent> & - IClOpt & { - mod?: ITrellisBasisOffsetMod; - classes?: string; - hide_space?: boolean; - hide_offset?: boolean; - }; - -export type ITrellisKindDisplay = { - display?: ITrellisKindDisplayValue; -} -export type ITrellisKindDisplayValue = ICbGOpt<MouseEvent> & ILoadingOpt & - (ITrellisKindDisplayValueIcon | ILabel); - - -export type ITrellisKindDisplayValueIcon = { - icon: { - classes?: string; - key: GlyphKey; - }; -}; -export type ITrellisKindTouch = ITrellisBasis & { - touch: ITrellisBasisTouch; -}; - -export type ITrellisBasisTouch = ICbGOpt<MouseEvent> & - ILabelTup & ITrellisKindDisplay & { - end?: ITrellisBasisTouchEnd; - }; - -export type ITrellisKindInput = ITrellisBasis & { - input: ITrellisBasisInput; -}; - -export type ITrellisBasisInput = { - basis: IInput<string>; - line_label?: { - classes?: string; - value: string; - }; - action?: { - visible: boolean; - loading?: boolean; - callback?: CallbackPromise; - glyph?: IGlyph - }; -}; - -export type ITrellisKindSelect = ITrellisBasis & { - select: ITrellisBasisSelect; -}; - -export type ITrellisBasisSelect = ICbGOpt<MouseEvent> & - ILabelTup & ITrellisKindDisplay & ILoadingOpt & { - end?: ITrellisBasisTouchEnd; - el: ISelect & { value: string; }; - }; - -export type ITrellisBasisTouchEnd = ICbGOpt<MouseEvent> & IGl; -\ No newline at end of file diff --git a/apps-lib-pwa/src/lib/types/views.ts b/apps-lib-pwa/src/lib/types/views.ts @@ -1,43 +0,0 @@ -import type { CallbackPromise, GeocoderReverseResult, GeolocationPoint } from "@radroots/utils"; -import type { FarmExtended } from "../views/farms/farm"; - -export type IViewBasis<T extends object> = { - kv_init_prevent?: boolean; - on_mount?: CallbackPromise; - on_destroy?: CallbackPromise; -} & T; - -export type IViewHomeData = {}; - -export type IViewFarmsData = { - list: FarmExtended[]; -}; - -export type IViewFarmsDetailsData = FarmExtended; - -export type IViewFarmsProductsAddData = FarmExtended; - -export type IViewFarmsProductsAddSubmitPayload = { - product: string; - process: string; - description: string; - price_amount: number; - price_currency: string; - price_quantity_unit: string; - photos: string[]; - quantity_amount: number; - quantity_unit: string; - quantity_label: string; - geolocation_point: GeolocationPoint; - geocode_result: GeocoderReverseResult; -}; - -export type IViewFarmsAddSubmission = { - farm_name: string; - farm_area?: number; - farm_area_unit?: string; - farm_contact_name?: string; - geolocation_point: GeolocationPoint; - geocode_result: GeocoderReverseResult; -}; - diff --git a/apps-lib-pwa/src/lib/utils/schemas/farm.ts b/apps-lib-pwa/src/lib/utils/schemas/farm.ts @@ -1,28 +0,0 @@ -import { dev } from "$app/environment"; -import type { IViewFarmsAddSubmission, IViewFarmsProductsAddSubmitPayload } from "$lib/types/views"; -import { form_fields, schema_geocode_result, schema_geolocation_point, util_rxp, zf_numf_pos, zf_numi_pos, zf_price } from "@radroots/utils"; -import { z } from "zod"; - -export const schema_view_farms_add_submission: z.ZodSchema<IViewFarmsAddSubmission> = z.object({ - farm_name: z.string().regex(form_fields.farm_name.validate), - farm_area: zf_numf_pos.optional(), - farm_area_unit: z.string().regex(form_fields.area_unit.validate).optional(), - farm_contact_name: z.string().regex(form_fields.contact_name.validate).optional(), - geolocation_point: schema_geolocation_point, - geocode_result: schema_geocode_result, -}); - -export const schema_view_farms_products_add_submission: z.ZodSchema<IViewFarmsProductsAddSubmitPayload> = z.object({ - product: z.string().regex(form_fields.product_key.validate), - process: z.string().regex(form_fields.product_process.validate), - description: z.string().regex(form_fields.product_description.validate), - price_amount: zf_price, - price_currency: z.string().regex(form_fields.price_currency.validate), - price_quantity_unit: z.string().regex(form_fields.quantity_unit.validate), - photos: z.array(z.string().regex(dev ? util_rxp.url_image_upload_dev : util_rxp.url_image_upload)), - quantity_amount: zf_numi_pos, - quantity_unit: z.string().regex(form_fields.quantity_unit.validate), - quantity_label: z.string().regex(form_fields.quantity_label.validate), - geolocation_point: schema_geolocation_point, - geocode_result: schema_geocode_result, -}); -\ No newline at end of file diff --git a/apps-lib-pwa/src/lib/utils/schemas/location-gcs.ts b/apps-lib-pwa/src/lib/utils/schemas/location-gcs.ts @@ -1,22 +0,0 @@ -import type { LocationGcs } from "@radroots/tangle-schema-bindings"; -import type { LocationBasis } from "@radroots/utils"; - -export const location_gcs_to_location_basis = ({ - id, - lat, - lng, - gc_name: primary, - gc_admin1_name: admin, - gc_country_id: country, -}: LocationGcs): LocationBasis => ({ - id, - point: { - lat, - lng, - }, - address: primary && admin && country ? { - primary, - admin, - country, - } : undefined -}); -\ No newline at end of file diff --git a/apps-lib-pwa/src/lib/styles/lib.ts b/apps-lib-pwa/src/lib/utils/styles.ts diff --git a/apps-lib-pwa/src/lib/views/farms/farm.ts b/apps-lib-pwa/src/lib/views/farms/farm.ts @@ -1,14 +0,0 @@ -import type { Farm } from "@radroots/tangle-schema-bindings"; -import type { LocationBasis } from "@radroots/utils"; - -export type FarmExtended = { - farm: Farm; - location?: LocationBasis; - lots?: FarmLotBasis[]; -}; - - -export type FarmLotBasis = { - id: string; - location?: LocationBasis; -}; -\ No newline at end of file diff --git a/apps-lib-pwa/src/lib/views/farms/farms-add.svelte b/apps-lib-pwa/src/lib/views/farms/farms-add.svelte @@ -1,223 +0,0 @@ -<script lang="ts"> - import ButtonLayoutPair from "$lib/components/buttons/button-layout-pair.svelte"; - import LayoutBottomButton from "$lib/components/layouts/layout-bottom-button.svelte"; - import LayoutView from "$lib/components/layouts/layout-view.svelte"; - import PageToolbar from "$lib/components/navigation/page-toolbar.svelte"; - import FarmsAddCasliDetail from "$lib/features/farm/farms-add-casli-detail.svelte"; - import FarmsAddCasliMap from "$lib/features/farm/farms-add-casli-map.svelte"; - import { app_platform } from "$lib/stores/app"; - import type { IViewFarmsAddSubmission } from "$lib/types/views"; - import { focus_map_marker } from "$lib/utils/map"; - import { schema_view_farms_add_submission } from "$lib/utils/schemas/farm"; - import { - Carousel, - casl_dec, - casl_i, - casl_inc, - casl_init, - el_id, - fmt_id, - geop_init, - geop_is_valid, - get_context, - type CallbackRoute, - } from "@radroots/apps-lib"; - import { - geol_lat_fmt, - geol_lng_fmt, - handle_err, - parse_float, - parse_geocode_address, - type CallbackPromiseGeneric, - type GeocoderReverseResult, - type GeolocationAddress, - type GeolocationPoint, - } from "@radroots/utils"; - import { onMount } from "svelte"; - - const { ls, locale, lc_gui_alert, lc_geop_current, lc_geocode } = - get_context(`lib`); - - let { - basis, - }: { - basis: { - callback_route?: CallbackRoute<string>; - on_submit: CallbackPromiseGeneric<{ - payload: IViewFarmsAddSubmission; - }>; - }; - } = $props(); - - let map_geop: GeolocationPoint = $state(geop_init()); - let map_geoc: GeocoderReverseResult | undefined = $state(undefined); - - let val_farmname = $state(``); - let val_farmaddress = $state(``); - let val_farmcontact = $state(``); - let val_farmarea = $state(``); - let val_farmarea_unit = $state(`ac`); - - const disabled_submit = $derived($casl_i === 1 && !val_farmname); - - onMount(async () => { - try { - casl_init(0, 2); - } catch (e) { - handle_err(e, `on_mount`); - } - }); - - const farm_geop_lat = $derived( - geop_is_valid(map_geop) - ? geol_lat_fmt(map_geop.lat, `dms`, $locale, 3) - : ``, - ); - - const farm_geop_lng = $derived( - geop_is_valid(map_geop) - ? geol_lng_fmt(map_geop.lng, `dms`, $locale, 3) - : ``, - ); - - const farm_geolocation_address: GeolocationAddress | undefined = $derived( - parse_geocode_address(map_geoc), - ); - - $effect(() => { - if (farm_geolocation_address) - val_farmaddress = `${farm_geolocation_address.primary}, ${farm_geolocation_address.admin}, ${farm_geolocation_address.country}`; - }); - - const handle_enter_location = async (): Promise<void> => { - map_geoc = undefined; - map_geop = geop_init(); - val_farmaddress = ``; - await handle_continue(); - el_id(fmt_id(`farm_location`))?.focus(); - }; - - const handle_continue_1 = async (): Promise<void> => { - if (!map_geop || !map_geoc) - return void lc_gui_alert(`No farm location provided.`); //@todo - const farms_add_submission = schema_view_farms_add_submission.safeParse( - { - farm_name: val_farmname, - farm_area: val_farmarea ? parse_float(val_farmarea) : undefined, - farm_area_unit: - val_farmarea && val_farmarea_unit - ? val_farmarea_unit - : undefined, - farm_contact_name: val_farmcontact - ? val_farmcontact - : undefined, - geolocation_point: map_geop, - geocode_result: map_geoc, - } satisfies IViewFarmsAddSubmission, - ); - - if (!farms_add_submission.success) { - return void lc_gui_alert( - `Request invalid: ${farms_add_submission.error}`, - ); //@todo - } - await basis.on_submit({ payload: farms_add_submission.data }); - }; - - const handle_continue = async (): Promise<void> => { - switch ($casl_i) { - case 1: - return await handle_continue_1(); - default: - await casl_inc(); - } - }; - - const handle_back = async (): Promise<void> => { - switch ($casl_i) { - case 1: { - if (!geop_is_valid(map_geop)) { - const geop_cur = await lc_geop_current(); - if (geop_cur) { - map_geop = geop_cur; - const geoc_cur = await lc_geocode(geop_cur); - if (geoc_cur) map_geoc = geoc_cur; - focus_map_marker(); - } - } - } - default: - return await casl_dec(); - } - }; -</script> - -<LayoutView> - <PageToolbar - basis={{ - header: { - label: `${$ls(`common.farms`)} / ${`${$ls(`common.add`)}`}`, - callback_route: basis.callback_route, - }, - }} - > - {#snippet header_option()} - <!-- @todo {#if $casl_i === 0} - <button - class={`flex flex-row justify-center items-center`} - onclick={async () => { - await handle_enter_location(); - }} - > - <p - class={`font-sans font-[600] text-[18px] text-ly0-gl-hl`} - > - {`${$ls(`common.enter_location`)}`} - </p> - <Glyph - basis={{ - classes: `text-ly0-gl-hl`, - dim: `md`, - key: `caret-right`, - }} - /> - </button> - {/if}--> - {/snippet} - </PageToolbar> - <Carousel> - <FarmsAddCasliMap - bind:map_geop - bind:map_geoc - {farm_geop_lat} - {farm_geop_lng} - /> - <FarmsAddCasliDetail - bind:val_farmname - bind:val_farmaddress - bind:val_farmcontact - bind:val_farmarea - bind:val_farmarea_unit - {farm_geop_lat} - {farm_geop_lng} - /> - </Carousel> -</LayoutView> -{#if $app_platform?.browser !== `safari`} - <LayoutBottomButton> - <ButtonLayoutPair - basis={{ - continue: { - label: `${$ls(`common.continue`)}`, - disabled: disabled_submit, - callback: handle_continue, - }, - back: { - label: `${$ls(`common.back`)}`, - visible: $casl_i > 0, - callback: handle_back, - }, - }} - /> - </LayoutBottomButton> -{/if} diff --git a/apps-lib-pwa/src/lib/views/farms/farms-details.svelte b/apps-lib-pwa/src/lib/views/farms/farms-details.svelte @@ -1,247 +0,0 @@ -<script lang="ts"> - import ButtonSimple from "$lib/components/buttons/button-simple.svelte"; - import LayoutPage from "$lib/components/layouts/layout-page.svelte"; - import LayoutView from "$lib/components/layouts/layout-view.svelte"; - import MapMarkerArea from "$lib/components/map/map-marker-area.svelte"; - import PageToolbar from "$lib/components/navigation/page-toolbar.svelte"; - import type { IViewBasis, IViewFarmsDetailsData } from "$lib/types/views"; - import { - Flex, - get_context, - Glyph, - type CallbackRoute, - } from "@radroots/apps-lib"; - import { - fmt_geolocation_address, - geol_lat_fmt, - geol_lng_fmt, - handle_err, - parse_geol_point_tup, - parse_tup_geop_point, - type CallbackPromiseGeneric, - type GeolocationPointTuple, - } from "@radroots/utils"; - import { onDestroy, onMount } from "svelte"; - import Map from "../../components/map/map.svelte"; - - const { ls, locale } = get_context(`lib`); - - let { - basis, - }: { - basis: IViewBasis<{ - data: IViewFarmsDetailsData; - callback_route?: CallbackRoute<string>; - on_handle_farm_lot_add: CallbackPromiseGeneric<string>; - on_handle_farm_products_view: CallbackPromiseGeneric<string>; - on_handle_farm_orders_view: CallbackPromiseGeneric<string>; - }>; - } = $props(); - - let map: maplibregl.Map | undefined = $state(undefined); - let map_center: GeolocationPointTuple = $state([0, 0]); - - onMount(async () => { - try { - if (basis.on_mount) await basis.on_mount(); - if (basis.data?.location) - map_center = parse_geol_point_tup(basis.data?.location.point); - if (map) { - map.setCenter(map_center); - map.setZoom(11); - } - } catch (e) { - handle_err(e, `on_mount`); - } - }); - - onDestroy(async () => { - try { - if (basis.on_destroy) await basis.on_destroy(); - } catch (e) { - handle_err(e, `on_destroy`); - } - }); - - const map_geop = $derived(parse_tup_geop_point(map_center)); - - const farm_addr_fmt = $derived( - basis.data?.location?.address - ? fmt_geolocation_address(basis.data?.location.address) - : ``, - ); - - const farm_geop_lat = $derived( - basis.data?.location?.point - ? geol_lat_fmt(basis.data?.location.point.lat, `dms`, $locale, 3) - : ``, - ); - - const farm_geop_lng = $derived( - basis.data?.location?.point - ? geol_lng_fmt(basis.data?.location.point.lng, `dms`, $locale, 3) - : ``, - ); -</script> - -<LayoutView> - <PageToolbar - basis={{ - header: { - label: `${$ls(`common.farms`)}${basis.data?.farm.name ? ` / ${basis.data?.farm.name}` : ``}`, - callback_route: basis.callback_route, - }, - }} - /> - <LayoutPage> - <div - class={`flex flex-row h-[12rem] w-full justify-start items-center`} - > - <div - class={`flex flex-col basis-1/2 h-full p-4 gap-2 justify-start items-center`} - > - <div class={`flex flex-col w-full justify-start items-center`}> - <div - class={`flex flex-row w-full justify-start items-center`} - > - <p class={`font-sans font-[500] text-lg text-ly0-gl`}> - {farm_addr_fmt} - </p> - </div> - <div - class={`flex flex-row w-full justify-start items-center`} - > - <p - class={`font-sans font-[500] text-lg text-ly0-gl tracking-tight`} - > - {farm_geop_lat && farm_geop_lng - ? `${farm_geop_lat}, ${farm_geop_lng}` - : ``} - </p> - </div> - </div> - </div> - <div - class={`flex flex-col basis-1/2 h-full justify-start items-center`} - > - <div - class={`flex flex-col h-full w-full p-4 gap-4 justify-start items-center bg-ly1 rounded-2xl`} - > - <p class={`font-sans font-[500] text-sm text-ly0-gl`}> - {`Farm Info`} - </p> - <div - class={`flex flex-col w-full gap-1 justify-start items-center`} - > - <div - class={`flex flex-row w-full gap-4 justify-between items-center`} - > - <p class={`font-sans font-[400] text-ly0-gl`}> - {`Farm Size:`} - </p> - - {#if basis.data?.farm.area && basis.data?.farm.area_unit} - <p class={`font-sans font-[400] text-ly0-gl`}> - {`${basis.data?.farm.area} ${basis.data?.farm.area_unit}`} - </p> - {:else} - <div - class={`flex flex-row gap-line justify-start items-center`} - > - <p - class={`font-sans font-[400] text-ly0-gl_pl`} - > - {`Add`} - </p> - <Glyph - basis={{ - classes: `text-ly0-gl_pl`, - dim: `xs`, - key: `caret-right`, - }} - /> - </div> - {/if} - </div> - <div - class={`flex flex-row w-full gap-4 justify-between items-center`} - > - <p class={`font-sans font-[400] text-ly0-gl`}> - {`Farm Lots:`} - </p> - <p class={`font-sans font-[400] text-ly0-gl`}> - {`${basis.data?.lots?.length || 0}`} - </p> - </div> - <div - class={`flex flex-row w-full gap-4 justify-between items-center`} - > - <p class={`font-sans font-[400] text-ly0-gl`}> - {`Products:`} - </p> - <p class={`font-sans font-[400] text-ly0-gl`}> - {`${0}`} - </p> - </div> - <div - class={`flex flex-row w-full gap-4 justify-between items-center`} - > - <p class={`font-sans font-[400] text-ly0-gl`}> - {`Orders:`} - </p> - <p class={`font-sans font-[400] text-ly0-gl`}> - {`${0}`} - </p> - </div> - </div> - </div> - </div> - </div> - <div class={`flex flex-col w-full gap-3 justify-center items-center`}> - <ButtonSimple - basis={{ - label: `View Products`, - callback: async () => { - if (basis.data?.farm.id) - await basis.on_handle_farm_products_view( - basis.data?.farm.id, - ); - }, - }} - /> - <ButtonSimple - basis={{ - label: `View Orders`, - callback: async () => { - if (basis.data?.farm.id) - await basis.on_handle_farm_orders_view( - basis.data?.farm.id, - ); - }, - }} - /> - </div> - <div - class={`flex flex-col flex-shrink-0 h-[16rem] w-full justify-center items-center rounded-2xl overflow-hidden`} - > - <Map - bind:map - basis={{ - interactive: false, - }} - > - <MapMarkerArea - {map_geop} - basis={{ - no_drag: true, - }} - /> - </Map> - </div> - <div - class={`flex flex-col h-[12rem] w-full justify-center items-center`} - > - <Flex /> - </div> - </LayoutPage> -</LayoutView> diff --git a/apps-lib-pwa/src/lib/views/farms/farms.svelte b/apps-lib-pwa/src/lib/views/farms/farms.svelte @@ -1,84 +0,0 @@ -<script lang="ts"> - import ButtonLabelDashed from "$lib/components/buttons/button-label-dashed.svelte"; - import GlyphButtonSimple from "$lib/components/buttons/glyph-button-simple.svelte"; - import LayoutPage from "$lib/components/layouts/layout-page.svelte"; - import LayoutView from "$lib/components/layouts/layout-view.svelte"; - import PageToolbar from "$lib/components/navigation/page-toolbar.svelte"; - import FarmsDisplayLiEl from "$lib/features/farm/farms-display-li-el.svelte"; - import type { IViewBasis, IViewFarmsData } from "$lib/types/views"; - import { Fade, get_context, idb_init_page, type CallbackRoute } from "@radroots/apps-lib"; - import { - handle_err, - type CallbackPromise, - type CallbackPromiseGeneric, - } from "@radroots/utils"; - import { onMount } from "svelte"; - - const { ls } = get_context(`lib`); - - let { - basis, - }: { - basis: IViewBasis<{ - data?: IViewFarmsData; - callback_route?: CallbackRoute<string>; - on_handle_farm_add: CallbackPromise; - on_handle_farm_view: CallbackPromiseGeneric<string>; - }>; - } = $props(); - - onMount(async () => { - try { - if (!basis.kv_init_prevent) await idb_init_page(); - } catch (e) { - handle_err(e, `on_mount`); - } - }); -</script> - -<LayoutView> - <PageToolbar - basis={{ - header: { - label: `${$ls(`common.farms`)}`, - callback_route: basis.callback_route, - }, - }} - > - {#snippet header_option()} - {#if basis.data?.list.length} - <Fade> - <GlyphButtonSimple - basis={{ - label: `${$ls(`icu.add_*`, { value: `${$ls(`common.farm`)}` })}`, - callback: async () => { - await basis.on_handle_farm_add(); - }, - }} - /> - </Fade> - {/if} - {/snippet} - </PageToolbar> - <LayoutPage> - {#if basis.data} - {#if basis.data?.list.length} - {#each basis.data?.list || [] as li} - <FarmsDisplayLiEl - basis={li} - on_handle_farm_view={basis.on_handle_farm_view} - /> - {/each} - {:else} - <ButtonLabelDashed - basis={{ - label: `Add farm`, - callback: async () => { - await basis.on_handle_farm_add(); - }, - }} - /> - {/if} - {/if} - </LayoutPage> -</LayoutView> diff --git a/apps-lib-pwa/src/lib/views/home.svelte b/apps-lib-pwa/src/lib/views/home.svelte @@ -1,56 +0,0 @@ -<script lang="ts"> - import ButtonSimple from "$lib/components/buttons/button-simple.svelte"; - import LayoutPage from "$lib/components/layouts/layout-page.svelte"; - import LayoutView from "$lib/components/layouts/layout-view.svelte"; - import NavigationTabs from "$lib/components/navigation/navigation-tabs.svelte"; - import PageToolbar from "$lib/components/navigation/page-toolbar.svelte"; - import type { IViewBasis, IViewHomeData } from "$lib/types/views"; - import { get_context, idb_init_page } from "@radroots/apps-lib"; - - import { handle_err, type CallbackPromise } from "@radroots/utils"; - import { onMount } from "svelte"; - - const { ls } = get_context(`lib`); - - let { - basis, - }: { - basis: IViewBasis<{ - data?: IViewHomeData; - on_handle_farms: CallbackPromise; - on_handle_products: CallbackPromise; - }>; - } = $props(); - - onMount(async () => { - try { - if (!basis.kv_init_prevent) await idb_init_page(); - } catch (e) { - handle_err(e, `on_mount`); - } - }); -</script> - -{#if basis.data} - {@const { data: basis_data } = basis} - <LayoutView> - <PageToolbar - basis={{ - header: { - label: `${$ls(`common.general`)}`, - }, - }} - /> - <LayoutPage> - <ButtonSimple - basis={{ - label: `${$ls(`common.farms`)}`, - callback: async () => { - await basis.on_handle_farms(); - }, - }} - /> - </LayoutPage> - </LayoutView> - <NavigationTabs /> -{/if} diff --git a/apps-lib-pwa/src/lib/views/profile/profile.svelte b/apps-lib-pwa/src/lib/views/profile/profile.svelte @@ -1,305 +0,0 @@ -<script lang="ts"> - import ButtonRoundNav from "$lib/components/buttons/button-round-nav.svelte"; - import FloatPage from "$lib/components/lib/float-page.svelte"; - import ImageUploadAddPhoto from "$lib/components/lib/image-upload-add-photo.svelte"; - import SelectMenu from "$lib/components/lib/select-menu.svelte"; - import NavigationTabs from "$lib/components/navigation/navigation-tabs.svelte"; - import type { IViewBasis } from "$lib/types/views"; - import { - get_context, - Glyph, - idb_init_page, - ImagePath, - symbols, - type IViewOnDestroy, - } from "@radroots/apps-lib"; - import { - handle_err, - type CallbackPromise, - type CallbackPromiseGeneric, - } from "@radroots/utils"; - import { onDestroy, onMount } from "svelte"; - import type { IViewProfileData, ViewProfileEditFieldKey } from "./types"; - - const { ls } = get_context(`lib`); - - let { - basis, - photo_path = $bindable(``), - }: { - basis: IViewBasis<{ - data?: IViewProfileData; - loading_photo_upload: boolean; - loading_photo_upload_open: boolean; - on_handle_back: CallbackPromiseGeneric<{ - is_photo_existing: boolean; - }>; - on_handle_photo_options: CallbackPromise; - on_handle_edit_profile_field: CallbackPromiseGeneric<{ - field: ViewProfileEditFieldKey; - }>; - }> & - IViewOnDestroy<{ public_key: string }>; - photo_path: string; - } = $props(); - - type ViewDisplay = `photos` | `following` | `followers`; - let view_display: ViewDisplay = $state(`photos`); - - let val_sel_options_button = $state(``); - - onMount(async () => { - try { - if (!basis.kv_init_prevent) await idb_init_page(); - } catch (e) { - handle_err(e, `on_mount`); - } - }); - - onDestroy(async () => { - try { - if (basis.data?.profile.public_key) - await basis.on_destroy({ - public_key: basis.data?.profile.public_key, - }); - } catch (e) { - handle_err(e, `on_destroy`); - } - }); - - const photo_overlay_visible = $derived( - !!(basis.data?.profile.picture || photo_path), - ); - - const classes_photo_overlay_glyph = $derived( - photo_overlay_visible ? `text-white` : `text-ly0-gl`, - ); - - const classes_photo_overlay_glyph_opt = $derived( - photo_overlay_visible ? `text-gray-300` : `text-ly0-gl`, - ); - - const classes_photo_overlay_glyph_opt_selected = $derived( - photo_overlay_visible ? `text-white` : `text-ly1-gl_d`, - ); -</script> - -{#if basis.data} - <div - class={`relative flex flex-col min-h-[525px] h-[525px] w-full justify-center items-center bg-ly2 fade-in`} - > - <FloatPage - basis={{ - posx: `left`, - }} - > - <ButtonRoundNav - basis={{ - glyph: `arrow-left`, - loading: basis.loading_photo_upload, - callback: async () => { - await basis.on_handle_back({ - is_photo_existing: photo_overlay_visible, - }); - }, - }} - /> - </FloatPage> - <FloatPage - basis={{ - posx: `right`, - }} - > - <SelectMenu - bind:value={val_sel_options_button} - basis={{ - layer: 0, - options: [ - { - entries: [ - { - value: `*add-new`, - label: `Add new photo`, - }, - ], - }, - ], - }} - > - <ButtonRoundNav - basis={{ - glyph: `images-square`, - callback: basis.on_handle_photo_options, - }} - /> - </SelectMenu> - </FloatPage> - {#if basis.data?.profile.picture || photo_path} - {@const img_path = photo_path || basis.data?.profile.picture || ``} - <ImagePath basis={{ path: img_path }} /> - {:else} - <div - class={`flex flex-row justify-start items-center -translate-y-8`} - > - <ImageUploadAddPhoto - bind:photo_path - basis={{ - loading: basis.loading_photo_upload_open, - }} - /> - </div> - {/if} - <div - class={`absolute bottom-0 left-0 flex flex-col h-[calc(100%-100%/1.618)] w-full px-6 gap-2 justify-end items-center`} - > - <div - class={`flex flex-col w-full gap-[2px] justify-center items-center`} - > - <div - class={`flex flex-row h-10 w-full justify-start items-center`} - > - <button - class={`group flex flex-row justify-center items-center`} - onclick={async () => { - await basis.on_handle_edit_profile_field({ - field: `display_name`, - }); - }} - > - <p - class={`font-sansd font-[600] text-[2rem] ${classes_photo_overlay_glyph} ${basis.data?.profile.name ? `` : `capitalize opacity-active`} el-re`} - > - {#if basis.data?.profile.display_name} - {`${basis.data?.profile.display_name}`} - {:else if basis.data?.profile.name} - {`${basis.data?.profile.display_name || basis.data?.profile.name || ``}`} - {:else} - {`+ ${`${$ls(`icu.add_*`, { value: `${$ls(`common.profile_name`)}` })}`}`} - {/if} - </p> - </button> - </div> - <div - class={`flex flex-row w-full gap-[6px] justify-start items-center`} - > - <button - class={`group flex flex-row justify-center items-center`} - onclick={async () => { - await basis.on_handle_edit_profile_field({ - field: `name`, - }); - }} - > - <p - class={`font-sansd font-[600] text-[1.1rem] ${classes_photo_overlay_glyph} ${basis.data?.profile.name ? `` : `capitalize opacity-active`} el-re`} - > - {#if basis.data?.profile.name} - {`@${basis.data?.profile.name}`} - {:else} - {`+ ${`${$ls(`icu.add_*`, { value: `${$ls(`common.username`)}` })}`}`} - {/if} - </p> - </button> - <p - class={`font-sans font-[400] ${classes_photo_overlay_glyph}`} - > - {symbols.bullet} - </p> - <button - class={`flex flex-row justify-center items-center`} - onclick={async () => { - alert(`@todo!`); - }} - > - <Glyph - basis={{ - classes: `${classes_photo_overlay_glyph}`, - dim: `xs`, - - key: `link-simple`, - }} - /> - </button> - </div> - <div class={`flex flex-row w-full justify-start items-center`}> - <button - class={`group flex flex-row justify-center items-center`} - onclick={async () => { - await basis.on_handle_edit_profile_field({ - field: `about`, - }); - }} - > - <p - class={`font-sansd font-[400] text-[1.1rem] ${classes_photo_overlay_glyph} ${basis.data?.profile.about ? `` : `capitalize opacity-active`}`} - > - {#if basis.data?.profile.about} - {`${basis.data?.profile.about}`} - {:else} - {`+ ${`${$ls(`icu.add_*`, { value: `${$ls(`common.bio`)}` })}`}`} - {/if} - </p> - </button> - </div> - </div> - <div - class={`flex flex-row w-full pt-2 pb-6 gap-2 justify-start items-center`} - > - <button - class={`flex flex-row justify-center items-center`} - onclick={async () => { - view_display = `photos`; - }} - > - <p - class={`font-sans text-[1.1rem] font-[600] capitalize ${view_display === `photos` ? classes_photo_overlay_glyph_opt_selected : classes_photo_overlay_glyph_opt} el-re`} - > - {`${$ls(`common.photos`)}`} - </p> - </button> - <button - class={`flex flex-row justify-center items-center`} - onclick={async () => { - view_display = `following`; - }} - > - <p - class={`font-sans text-[1.1rem] font-[600] capitalize ${view_display === `following` ? classes_photo_overlay_glyph_opt_selected : classes_photo_overlay_glyph_opt} el-re`} - > - {`${$ls(`common.following`)}`} - </p> - </button> - <button - class={`flex flex-row justify-center items-center`} - onclick={async () => { - view_display = `followers`; - }} - > - <p - class={`font-sans text-[1.1rem] font-[600] capitalize ${view_display === `followers` ? classes_photo_overlay_glyph_opt_selected : classes_photo_overlay_glyph_opt} el-re`} - > - {`${$ls(`common.followers`)}`} - </p> - </button> - </div> - </div> - </div> - <div - class={`flex flex-col w-full min-h-[500px] justify-start items-center`} - > - {#if view_display === `photos`} - <p class={`font-sans font-[400] text-ly0-gl`}> - {view_display} - </p> - {:else if view_display === `following`} - <p class={`font-sans font-[400] text-ly0-gl`}> - {view_display} - </p> - {:else if view_display === `followers`} - <p class={`font-sans font-[400] text-ly0-gl`}> - {view_display} - </p> - {/if} - </div> - <NavigationTabs /> -{/if} diff --git a/apps-lib-pwa/src/lib/views/profile/types.ts b/apps-lib-pwa/src/lib/views/profile/types.ts @@ -1,12 +0,0 @@ -import type { NostrProfile } from "@radroots/tangle-schema-bindings"; - -export type IViewProfileData = { - profile: NostrProfile -}; - -export type ViewProfileEditFieldKey = `name` | `display_name` | `about`; - -export type IViewProfileEditData = { - public_key: string; - field: ViewProfileEditFieldKey; -}; diff --git a/apps-lib-pwa/src/lib/views/settings.svelte b/apps-lib-pwa/src/lib/views/settings.svelte @@ -1,109 +0,0 @@ -<script lang="ts"> - import LayoutTrellis from "$lib/components/layouts/layout-trellis.svelte"; - import LayoutView from "$lib/components/layouts/layout-view.svelte"; - import PageToolbar from "$lib/components/navigation/page-toolbar.svelte"; - import Trellis from "$lib/components/trellis/trellis.svelte"; - import type { ITrellisKind } from "$lib/types/components/trellis"; - import type { IViewBasis } from "$lib/types/views"; - import { - get_context, - idb_init_page, - symbols, - theme_mode, - } from "@radroots/apps-lib"; - import { handle_err } from "@radroots/utils"; - import { onMount } from "svelte"; - - const { ls, lc_color_mode } = get_context(`lib`); - - let { - basis, - }: { - basis: IViewBasis<{ - trellis_2?: (ITrellisKind | undefined)[]; - }>; - } = $props(); - - onMount(async () => { - try { - if (!basis.kv_init_prevent) await idb_init_page(); - } catch (e) { - handle_err(e, `on_mount`); - } - }); -</script> - -<LayoutView> - <PageToolbar - basis={{ - header: { - label: `${$ls(`common.settings`)}`, - }, - }} - /> - <LayoutTrellis> - <Trellis - basis={{ - layer: 1, - title: { - value: `Appearance`, - }, - list: [ - { - hide_active: true, - select: { - label: { - left: [ - { - value: `${$ls(`common.color_mode`)}`, - classes: `capitalize`, - }, - ], - }, - display: { - label: { - value: `${$theme_mode}`, - classes: `capitalize`, - }, - }, - el: { - value: $theme_mode, - options: [ - { - entries: [ - { - value: symbols.bullet, - label: `${$ls(`icu.choose_*`, { value: `${$ls(`common.color_mode`)}`.toLowerCase() })}`, - disabled: true, - }, - { - value: `light`, - label: `${$ls(`common.light`)}`, - }, - { - value: `dark`, - label: `${$ls(`common.dark`)}`, - }, - ], - }, - ], - callback: lc_color_mode, - }, - end: { - glyph: { - key: `caret-right`, - }, - }, - }, - }, - ], - }} - /> - <Trellis - basis={{ - layer: 1, - list: basis.trellis_2, - }} - /> - </LayoutTrellis> -</LayoutView>