web


git clone https://radroots.dev/git/web.git
Log | Files | Refs | Submodules | README | LICENSE

commit 05d32fdf7db5cc1996251545a46dc1e71aad71c4
parent 35d043c59c5467b5117cf5df8ae5964b3186a525
Author: triesap <137732411+triesap@users.noreply.github.com>
Date:   Tue, 29 Apr 2025 04:58:57 +0000

Add lib context to root layout. Add `/farms/products/add`, edit farms routes. Refactor callback utils. Add/edit styles, utils.

Diffstat:
Mapp/.env.example | 1+
Mapp/src/lib/locale/i18n.ts | 2+-
Mapp/src/lib/util/callback.ts | 100+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Mapp/src/lib/util/routes.ts | 2++
Mapp/src/routes/(app)/+page.svelte | 10++++------
Mapp/src/routes/(app)/farms/+page.svelte | 25+++++++++----------------
Mapp/src/routes/(app)/farms/add/+page.svelte | 15++-------------
Mapp/src/routes/(app)/farms/details/+page.svelte | 26+++++++++-----------------
Aapp/src/routes/(app)/farms/products/add/+page.svelte | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mapp/src/routes/(app)/profile/+page.svelte | 41++++++++++-------------------------------
Mapp/src/routes/(app)/profile/edit/+page.svelte | 11+++++------
Mapp/src/routes/+layout.svelte | 25+++++++++++++++++++++++++
Mapp/tailwind.config.ts | 3++-
Mcrates/tangle/icons/icon.icns | 0
14 files changed, 202 insertions(+), 136 deletions(-)

diff --git a/app/.env.example b/app/.env.example @@ -1,5 +1,6 @@ PUBLIC_NOSTR_RELAY_DEFAULTS= PUBLIC_RADROOTS_RELAY_URL= +PUBLIC_RADROOTS_UPLOAD_IMAGES_URL= PUBLIC_RADROOTS_URL= VITE_PUBLIC_IDB_NAME= VITE_PUBLIC_NDK_CACHE_NAME= diff --git a/app/src/lib/locale/i18n.ts b/app/src/lib/locale/i18n.ts @@ -10,7 +10,7 @@ const i18n = i18n_conf<Locale>({ default_locale: `en`, translations, loaders: [ - ...locale_keys.map((locale) => [`common`, `countries`, `error`, `eula`, `icu`, `notification`, `units`].map(key => ({ + ...locale_keys.map((locale) => [`common`, `countries`, `error`, `eula`, `icu`, `notification`, `products`, `units`].map(key => ({ locale, key, loader: async () => (await import(`../../../../packages/locales/src/messages/${locale}/${key}.json`)).default diff --git a/app/src/lib/util/callback.ts b/app/src/lib/util/callback.ts @@ -1,55 +1,65 @@ -import { ls } from "$lib/locale/i18n"; -import { get_store, handle_err } from "@radroots/lib-app"; -import type { GeocoderReverseResult, GeolocationPoint, IClientGeolocationPosition } from "@radroots/util"; -import { geoc, geol, gui } from "."; - -export const lc_gui_alert = async (message: string): Promise<boolean> => { - try { - return await gui.alert(message); - } catch (e) { - await handle_err(e, `lc_gui_alert`); - return false; - } +import { app_thc, type LocalCallbackColorMode, type LocalCallbackGeocode, type LocalCallbackGeocodeCurrent, type LocalCallbackGuiAlert, type LocalCallbackGuiConfirm, type LocalCallbackImgBin, type LocalCallbackPhotosAddMultiple, type LocalCallbackPhotosUpload } from "@radroots/lib-app"; +import { parse_color_mode } from "@radroots/theme"; +import { throw_err } from "@radroots/util"; +import { fs, geoc, geol, gui, http } from "."; + +export const lc_gui_alert: LocalCallbackGuiAlert = async (message) => { + return await gui.alert(message); }; -export const lc_gui_confirm = async (opts: string | { message: string; ok?: string; cancel?: string }): Promise<boolean> => { - try { - return await gui.confirm({ - message: typeof opts === `string` ? opts : opts.message, - ok: typeof opts === `string` ? undefined : opts.ok, - cancel: typeof opts === `string` ? undefined : opts.cancel, - }); - } catch (e) { - await handle_err(e, `lc_gui_alert`); - return false; - } +export const lc_gui_confirm: LocalCallbackGuiConfirm = async (opts) => { + return await gui.confirm({ + message: typeof opts === `string` ? opts : opts.message, + ok: typeof opts === `string` ? undefined : opts.ok, + cancel: typeof opts === `string` ? undefined : opts.cancel, + }); }; -export const lc_geocode = async (geoc_p: GeolocationPoint): Promise<GeocoderReverseResult | undefined> => { - try { - await geoc.connect(); - const geoc_res = await geoc.reverse(geoc_p); - if ( - `results` in geoc_res && - geoc_res.results.length > 0 - ) - return geoc_res.results[0]; - } catch (e) { - await handle_err(e, `lc_geocode`); - } +export const lc_geocode: LocalCallbackGeocode = async (geoc_p) => { + await geoc.connect(); + const geoc_res = await geoc.reverse(geoc_p); + if (`err` in geoc_res) throw_err(geoc_res); + return geoc_res.results[0] || undefined; }; -export const lc_geop_current = async (show_alert: boolean | string = false): Promise<IClientGeolocationPosition | undefined> => { - const $ls = get_store(ls); +export const lc_geop_current: LocalCallbackGeocodeCurrent = async () => { const geop = await geol.current(); - if (`err` in geop) { - if (show_alert) { - await gui.alert( - typeof show_alert === `string` ? show_alert : - `${$ls(`icu.failure_*`, { value: `${$ls(`icu.reading_*`, { value: `${$ls(`common.geocode`)}`.toLowerCase() })}` })}`, - ) + if (`err` in geop) throw_err(geop); + return geop; +}; + +export const lc_photos_add: LocalCallbackPhotosAddMultiple = async () => { + const photo_paths_open = await gui.open_photos(); + if (!photo_paths_open) return; + if (photo_paths_open.results) return photo_paths_open.results; +}; + +export const lc_img_bin: LocalCallbackImgBin = async (file_path) => { + const data = await fs.read_bin(file_path); + return data; +}; + +export const lc_color_mode: LocalCallbackColorMode = async ({ value }) => { + if (value) app_thc.set(parse_color_mode(value)); +}; + +export const lc_photos_upload: LocalCallbackPhotosUpload = async ({ url, path }) => { + const data_bin = await lc_img_bin(path); + if (!data_bin) return; + const res = await http.fetch({ + url, + method: `put`, + headers: { + "Content-Type": `image/jpeg`, + }, + data_bin, + }); + if (`err` in res) throw_err(res); + else if (res.data && res.data.res_base && res.data.res_path && res.data.file_ext) { + return { + base_url: res.data.res_base, + file_hash: res.data.res_path, + file_ext: res.data.file_ext } - return undefined } - return geop; }; \ No newline at end of file diff --git a/app/src/lib/util/routes.ts b/app/src/lib/util/routes.ts @@ -3,6 +3,7 @@ export type NavigationRoute = | "/farms" | "/farms/add" | "/farms/details" + | "/farms/products/add" | "/profile" | "/profile/edit" | "/init"; @@ -13,6 +14,7 @@ export function parse_route(route: string): NavigationRoute { case "/farms": case "/farms/add": case "/farms/details": + case "/farms/products/add": case "/profile": case "/profile/edit": case "/init": diff --git a/app/src/routes/(app)/+page.svelte b/app/src/routes/(app)/+page.svelte @@ -1,5 +1,4 @@ <script lang="ts"> - import { ls } from "$lib/locale/i18n"; import { route } from "$lib/util"; import { handle_err, Home, type IViewHomeData } from "@radroots/lib-app"; @@ -7,20 +6,19 @@ </script> <Home - {ls} basis={{ data, - lc_handle_farms: async () => { + on_handle_farms: async () => { try { await route(`/farms`); } catch (e) { - await handle_err(e, `lc_handle_farms`); + await handle_err(e, `on_handle_farms`); } }, - lc_handle_products: async () => { + on_handle_products: async () => { try { } catch (e) { - await handle_err(e, `lc_handle_products`); + await handle_err(e, `on_handle_products`); } }, }} diff --git a/app/src/routes/(app)/farms/+page.svelte b/app/src/routes/(app)/farms/+page.svelte @@ -1,14 +1,10 @@ <script lang="ts"> - import { locale, ls } from "$lib/locale/i18n"; import { db, route } from "$lib/util"; - import { lc_geocode } from "$lib/util/callback"; + import { Farms, handle_err, type IViewFarmsData } from "@radroots/lib-app"; import { - Farms, - handle_err, - type FarmBasis, - type IViewFarmsData, - } from "@radroots/lib-app"; - import { location_gcs_to_location_basis } from "@radroots/util"; + location_gcs_to_location_basis, + type FarmExtended, + } from "@radroots/util"; import { onMount } from "svelte"; type LoadData = IViewFarmsData | undefined; @@ -44,7 +40,7 @@ tb_loc_gcs.results[0], ) : undefined, - } satisfies FarmBasis; + } satisfies FarmExtended; }), )) || [] : [], @@ -56,24 +52,21 @@ </script> <Farms - {ls} - {locale} basis={{ data, callback_route: { route: `/` }, - lc_geocode, - lc_handle_farm_add: async () => { + on_handle_farm_add: async () => { try { await route(`/farms/add`); } catch (e) { - await handle_err(e, `lc_handle_farm_add`); + await handle_err(e, `on_handle_farm_add`); } }, - lc_handle_farm_view: async (farm_id) => { + on_handle_farm_view: async (farm_id) => { try { await route(`/farms/details`, [[`id`, farm_id]]); } catch (e) { - await handle_err(e, `lc_handle_farm_view`); + await handle_err(e, `on_handle_farm_view`); } }, }} diff --git a/app/src/routes/(app)/farms/add/+page.svelte b/app/src/routes/(app)/farms/add/+page.svelte @@ -1,25 +1,14 @@ <script> - import { locale, ls } from "$lib/locale/i18n"; import { db, route } from "$lib/util"; - import { - lc_geocode, - lc_geop_current, - lc_gui_alert, - } from "$lib/util/callback"; import { model_location_gcs_create } from "$lib/util/model/location-gcs"; import { FarmsAdd, handle_err } from "@radroots/lib-app"; import { throw_err } from "@radroots/util"; </script> <FarmsAdd - {ls} - {locale} basis={{ callback_route: { route: `/farms` }, - lc_gui_alert, - lc_geocode, - lc_geop_current, - lc_submit: async ({ data_s }) => { + on_submit: async ({ data_s }) => { try { console.log(JSON.stringify(data_s, null, 4), `data_s`); @@ -53,7 +42,7 @@ if (`err` in farm_location_set) throw_err(farm_location_set); await route(`/farms`); } catch (e) { - await handle_err(e, `lc_submit`); + await handle_err(e, `on_submit`); } }, }} diff --git a/app/src/routes/(app)/farms/details/+page.svelte b/app/src/routes/(app)/farms/details/+page.svelte @@ -1,7 +1,5 @@ <script lang="ts"> - import { locale, ls } from "$lib/locale/i18n"; import { db, route } from "$lib/util"; - import { lc_geocode } from "$lib/util/callback"; import { FarmsDetails, handle_err, @@ -44,34 +42,28 @@ {#if data} <FarmsDetails - {ls} - {locale} basis={{ data, callback_route: { route: `/farms` }, - lc_geocode, - lc_handle_farm_lot_add: async (farm_id) => { + on_handle_farm_lot_add: async (farm_id) => { try { - // await route(`/farms/lots/add`, { farm_id }); + // await route(`/farms/lots/add`, [[`id`, farm_id]]); } catch (e) { - await handle_err(e, `lc_handle_farm_lot_add`); + await handle_err(e, `on_handle_farm_lot_add`); } }, - lc_handle_farm_products_view: async (farm_id) => { + on_handle_farm_products_view: async (farm_id) => { try { - /* - if (data?.farm_lots?.every((i) => !i.farm_lot_products?.length)) - await route(`/farms/products/add`, { farm_id }); - else - */ + // @todo + await route(`/farms/products/add`, [[`id`, farm_id]]); } catch (e) { - await handle_err(e, `lc_handle_farm_products_view`); + await handle_err(e, `on_handle_farm_products_view`); } }, - lc_handle_farm_orders_view: async (farm_id) => { + on_handle_farm_orders_view: async (farm_id) => { try { } catch (e) { - await handle_err(e, `lc_handle_farm_orders_view`); + await handle_err(e, `on_handle_farm_orders_view`); } }, }} diff --git a/app/src/routes/(app)/farms/products/add/+page.svelte b/app/src/routes/(app)/farms/products/add/+page.svelte @@ -0,0 +1,77 @@ +<script lang="ts"> + import { db, route } from "$lib/util"; + import { + FarmsProductsAdd, + handle_err, + qp_id, + type IViewFarmsProductsAddData, + } from "@radroots/lib-app"; + import { location_gcs_to_location_basis } from "@radroots/util"; + import { onMount } from "svelte"; + + type LoadData = IViewFarmsProductsAddData | undefined; + let data: LoadData = $state(undefined); + + onMount(async () => { + data = await load_data(); + }); + + const load_data = async (): Promise<LoadData> => { + try { + const tb_farm = await db.farm_read({ id: $qp_id || `` }); + if (`err` in tb_farm) return void route(`/farms`); + console.log(JSON.stringify(tb_farm, null, 4), `tb_farm`); + const tb_farm_location = await db.location_gcs_read_list({ + table: [`on_farm`, { id: tb_farm.result.id }], + }); + return { + farm: { + ...tb_farm.result, + }, + location: + `results` in tb_farm_location && tb_farm_location.results[0] + ? location_gcs_to_location_basis( + tb_farm_location.results[0], + ) + : undefined, + } satisfies LoadData; + } catch (e) { + await handle_err(e, `load_data`); + } + }; +</script> + +{#if data} + <FarmsProductsAdd + basis={{ + data, + on_handle_farm_lot_add: async () => { + try { + } catch (e) { + await handle_err(e, `on_handle_farm_lot_add`); + } + }, + on_handle_photo_envelope_edit: async () => { + try { + } catch (e) { + await handle_err(e, `on_handle_photo_envelope_edit`); + } + }, + on_handle_tradepr_key_toggle: async () => { + try { + return ``; + } catch (e) { + await handle_err(e, `on_handle_tradepr_key_toggle`); + return ``; + } + }, + on_submit: async ({ payload, farm_id, geolocation_id }) => { + try { + console.log(JSON.stringify(payload, null, 4), `payload`); + } catch (e) { + await handle_err(e, `on_submit`); + } + }, + }} + /> +{/if} diff --git a/app/src/routes/(app)/profile/+page.svelte b/app/src/routes/(app)/profile/+page.svelte @@ -29,7 +29,7 @@ data = { ...tb_nostr_profile.result }; await nostr_sync.metadata({ metadata: tb_nostr_profile.result, - }); // leave off await + }); // no await return; } return void (await route(`/`)); @@ -41,12 +41,11 @@ <Profile bind:photo_path - {ls} basis={{ data, loading_photo_upload, loading_photo_upload_open, - lc_on_destroy: async () => { + on_destroy: async () => { try { const tb_nostrprofile = await db.nostr_profile_read({ public_key: $ndk_user?.pubkey, @@ -54,12 +53,12 @@ if (`err` in tb_nostrprofile) throw_err(tb_nostrprofile); //@todo await nostr_sync.metadata({ metadata: tb_nostrprofile.result, - }); // leave off await + }); // no await } catch (e) { - await handle_err(e, `lc_on_destroy`); + await handle_err(e, `on_destroy`); } }, - lc_handle_back: async ({ is_photo_existing }) => { + on_handle_back: async ({ is_photo_existing }) => { try { const public_key = $ndk_user?.pubkey; if (!photo_path || !public_key) return void (await route(`/`)); @@ -118,12 +117,12 @@ throw_err(tb_nostr_profile_update); await route(`/`); } catch (e) { - await handle_err(e, `lc_handle_back`); + await handle_err(e, `on_handle_back`); } finally { loading_photo_upload = false; } }, - lc_handle_edit_profile_field: async ({ field }) => { + on_handle_edit_profile_field: async ({ field }) => { try { if (field === `name`) { const confirm = await gui.confirm({ @@ -138,33 +137,13 @@ [`field`, field], ]); } catch (e) { - await handle_err(e, `lc_handle_edit_profile_field`); + await handle_err(e, `on_handle_edit_profile_field`); } }, - lc_handle_photo_add: async () => { + on_handle_photo_options: async () => { try { - loading_photo_upload_open = true; - const photo_paths_open = await gui.open_photos(); - if (!photo_paths_open) return; - const photo_path_add = photo_paths_open.results[0]; - if (photo_path_add) return photo_path_add; } catch (e) { - await handle_err(e, `lc_handle_photo_add`); - } finally { - loading_photo_upload_open = false; - } - }, - lc_handle_photo_options: async () => { - try { - } catch (e) { - await handle_err(e, `lc_handle_photo_options`); - } - }, - lc_fs_read_bin: async (file_path) => { - try { - return await fs.read_bin(file_path); - } catch (e) { - await handle_err(e, `lc_fs_read_bin`); + await handle_err(e, `on_handle_photo_options`); } }, }} diff --git a/app/src/routes/(app)/profile/edit/+page.svelte b/app/src/routes/(app)/profile/edit/+page.svelte @@ -55,10 +55,9 @@ <ProfileEdit bind:val_field - {ls} basis={{ data, - lc_handle_back: async ({ field, public_key }) => { + on_handle_back: async ({ field, public_key }) => { try { if (val_field_init === val_field) return void (await route(`/profile`)); @@ -86,16 +85,16 @@ if (`err` in tb_nostr_profile) throw_err(tb_nostr_profile); nostr_sync.metadata({ metadata: tb_nostr_profile.result, - }); // leave off await + }); // no await await route(`/profile`); } catch (e) { - await handle_err(e, `lc_handle_back`); + await handle_err(e, `on_handle_back`); } }, - lc_handle_input: async () => { + on_handle_input: async () => { try { } catch (e) { - await handle_err(e, `lc_handle_input`); + await handle_err(e, `on_handle_input`); } }, }} diff --git a/app/src/routes/+layout.svelte b/app/src/routes/+layout.svelte @@ -1,9 +1,21 @@ <script lang="ts"> + import { locale, ls } from "$lib/locale/i18n"; + import { + lc_color_mode, + lc_geocode, + lc_geop_current, + lc_gui_alert, + lc_gui_confirm, + lc_img_bin, + lc_photos_add, + lc_photos_upload, + } from "$lib/util/callback"; import { app_lo, app_th, app_thc, LayoutWindow, + set_context, theme_set, win_h, } from "@radroots/lib-app"; @@ -15,6 +27,19 @@ let { children }: LayoutProps = $props(); + set_context(`lib`, { + ls, + locale, + lc_color_mode, + lc_gui_alert, + lc_gui_confirm, + lc_geocode, + lc_geop_current, + lc_img_bin, + lc_photos_add, + lc_photos_upload, + }); + app_thc.subscribe((_app_thc) => theme_set(parse_theme_key($app_th), parse_color_mode(_app_thc)), ); diff --git a/app/tailwind.config.ts b/app/tailwind.config.ts @@ -32,11 +32,12 @@ const widths_responsive: Record<AppWidthsResponsiveIOS, string> = { lo_ios1: `345px`, lo_textdesc_ios0: `312px`, lo_textdesc_ios1: `312px`, + lo_line_entry_ios0: `349px`, + lo_line_entry_ios1: `378px`, }; const widths: Record<string, string> = { ...widths_responsive, - trellis_line: `349px`, trellis_value: `180px`, trellis_display: `286px`, }; diff --git a/crates/tangle/icons/icon.icns b/crates/tangle/icons/icon.icns Binary files differ.