web_lib

Common web application libraries
git clone https://radroots.dev/git/web_lib.git
Log | Files | Refs | LICENSE

commit 51990034df4ba965ce650e13fc9436b52cadffd1
parent 7c399af546a873d7b9d209e4050c3f107a96d283
Author: triesap <137732411+triesap@users.noreply.github.com>
Date:   Sun, 27 Apr 2025 20:34:39 +0000

apps-lib: edit farms add view

Diffstat:
Mapps-lib/src/lib/components/button/button-layout-pair.svelte | 2+-
Mapps-lib/src/lib/components/form/form-entry-price-quantity.svelte | 4++--
Mapps-lib/src/lib/components/form/form-entry-price.svelte | 2+-
Mapps-lib/src/lib/components/form/form-entry-quantity.svelte | 2+-
Mapps-lib/src/lib/components/form/form-line-ledger.svelte | 4++--
Mapps-lib/src/lib/components/lib/input.svelte | 26++++++++++----------------
Mapps-lib/src/lib/components/navigation/page-toolbar.svelte | 50++++++++++++++++++++++++++------------------------
Mapps-lib/src/lib/features/farm/farms-add-casli-detail.svelte | 30++++++++++++++++++++++++++----
Mapps-lib/src/lib/features/farm/farms-add-casli-map.svelte | 38+++++++++++++++++++++++---------------
Mapps-lib/src/lib/features/farm/farms-products-review-card.svelte | 4++--
Mapps-lib/src/lib/types/view/farm.ts | 6+++---
Mapps-lib/src/lib/util/lib.ts | 13++++++++++++-
Mapps-lib/src/lib/util/validation/farm.ts | 6+++---
Mapps-lib/src/lib/view/farms-add.svelte | 105++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
14 files changed, 179 insertions(+), 113 deletions(-)

diff --git a/apps-lib/src/lib/components/button/button-layout-pair.svelte b/apps-lib/src/lib/components/button/button-layout-pair.svelte @@ -26,7 +26,7 @@ </script> <div - class={`${fmt_cl(basis.classes)} flex flex-col gap-1 justify-center items-center ${basis?.back?.visible ? `-translate-y-1` : ``}`} + class={`${fmt_cl(basis.classes)} flex flex-col gap-1 justify-center items-center ${basis?.back?.visible ? `-translate-y-8` : ``} el-re`} > <ButtonLayout basis={{ diff --git a/apps-lib/src/lib/components/form/form-entry-price-quantity.svelte b/apps-lib/src/lib/components/form/form-entry-price-quantity.svelte @@ -44,7 +44,7 @@ <LayoutTrellisLine basis={{ label: { - value: `${$ls(`icu.*_price`, { value: `${$ls(`common.product`)}` })} (${val_sel_currency}/${`${$ls(`measurement.mass.unit.${val_sel_qty_unit}_ab`)}`})`, + value: `${$ls(`icu.*_price`, { value: `${$ls(`common.product`)}` })} (${val_sel_currency}/${`${$ls(`units.mass.unit.${val_sel_qty_unit}_ab`)}`})`, }, }} > @@ -109,7 +109,7 @@ { entries: mass_units.map((i) => ({ value: i, - label: `${$ls(`measurement.mass.unit.${i}_ab`)}`.toLowerCase(), + label: `${$ls(`units.mass.unit.${i}_ab`)}`.toLowerCase(), })), }, ], diff --git a/apps-lib/src/lib/components/form/form-entry-price.svelte b/apps-lib/src/lib/components/form/form-entry-price.svelte @@ -114,7 +114,7 @@ { entries: mass_units.map((i) => ({ value: i, - label: `${$ls(`measurement.mass.unit.${i}_ab`)}`.toLowerCase(), + label: `${$ls(`units.mass.unit.${i}_ab`)}`.toLowerCase(), })), }, ], diff --git a/apps-lib/src/lib/components/form/form-entry-quantity.svelte b/apps-lib/src/lib/components/form/form-entry-quantity.svelte @@ -74,7 +74,7 @@ { entries: mass_units.map((i) => ({ value: i, - label: `${$ls(`measurement.mass.unit.${i}_ab`)}`.toLowerCase(), + label: `${$ls(`units.mass.unit.${i}_ab`)}`.toLowerCase(), })), }, ], diff --git a/apps-lib/src/lib/components/form/form-line-ledger.svelte b/apps-lib/src/lib/components/form/form-line-ledger.svelte @@ -72,7 +72,7 @@ class={`flex flex-row h-12 w-full justify-start items-center border-y-line border-layer-0-surface-edge`} > {#if basis.display_value} - <p class={`font-sans font-[400] text-layer-0-glyph text-form_base`}> + <p class={`font-sans font-[400] text-layer-1-glyph text-form_base`}> {basis.display_value} </p> {:else if basis.input} @@ -82,7 +82,7 @@ id: id ? fmt_id(id) : undefined, layer: 0, classes: `h-10 placeholder:text-[1.1rem]`, - field: basis.input.field, + field: basis.input.field || undefined, placeholder: basis.input.placeholder || ``, callback_keydown: basis.input.callback_keydown, }} diff --git a/apps-lib/src/lib/components/lib/input.svelte b/apps-lib/src/lib/components/lib/input.svelte @@ -24,20 +24,14 @@ : `bg-layer-${layer}-surface text-layer-${layer}-glyph_d placeholder:text-layer-${layer}-glyph_pl caret-layer-${layer}-glyph`, ); - let value_local = $state(value); - 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_local - ) { - value_local = kv_val; + if (kv_val !== null && kv_val !== undefined && kv_val !== value) { + value = kv_val; } else if (kv_val === null || kv_val === undefined) { - value_local = ``; + value = ``; await idb.set(id, ``); } } catch (e) { @@ -48,7 +42,7 @@ const sync_to_idb = async (): Promise<void> => { if (!browser || !idb || !id) return; try { - await idb.set(id, value_local || ``); + await idb.set(id, value || ``); } catch (e) { handle_err(e, `input_idb_sync`); } @@ -75,14 +69,14 @@ const handle_on_input = async (): Promise<void> => { try { - let val_cur = value_local; + let val_cur = value; let pass = true; if (basis?.field) { - val_cur = value_constrain(basis.field.charset, val_cur); - if (val_cur !== value_local) { - value_local = val_cur; + val_cur = value_constrain(basis.field?.charset, val_cur); + if (val_cur !== value) { + value = val_cur; } - pass = basis.field.validate.test(val_cur); + pass = basis.field?.validate.test(val_cur); } if (basis?.callback) { await basis.callback({ value: val_cur, pass }); @@ -95,7 +89,7 @@ <input bind:this={el} - bind:value={value_local} + bind:value disabled={!!basis.disabled} oninput={handle_on_input} onblur={async ({ currentTarget: el }) => { diff --git a/apps-lib/src/lib/components/navigation/page-toolbar.svelte b/apps-lib/src/lib/components/navigation/page-toolbar.svelte @@ -23,31 +23,33 @@ <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`} > - <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-layer-0-glyph`, - dim: `lg`, - - key: `gear`, + <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`); }} - /> - </button> + > + <Glyph + basis={{ + classes: `text-layer-0-glyph`, + dim: `lg`, + + key: `gear`, + }} + /> + </button> + </div> </div> {#if basis?.header} <PageHeader basis={basis.header}> diff --git a/apps-lib/src/lib/features/farm/farms-add-casli-detail.svelte b/apps-lib/src/lib/features/farm/farms-add-casli-detail.svelte @@ -8,6 +8,7 @@ let { val_farmname = $bindable(``), + val_farmaddress = $bindable(``), val_farmarea = $bindable(``), val_farmarea_unit = $bindable(``), val_farmcontact = $bindable(``), @@ -16,6 +17,7 @@ ls, }: { val_farmname: string; + val_farmaddress: string; val_farmarea: string; val_farmarea_unit: string; val_farmcontact: string; @@ -30,10 +32,30 @@ 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`)}`, - display_value: `${farm_geop_lat}, ${farm_geop_lng}`, + 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 @@ -53,14 +75,14 @@ id: `farm_size`, label: `${$ls(`common.farm_size`)}`, label_select: { - label: `${$ls(`measurement.area.${val_farmarea_unit}_ab`)}`, + label: `${$ls(`units.area.${val_farmarea_unit}_ab`)}`, entries: area_units.map((i) => ({ value: i, - label: `${$ls(`measurement.area.${i}`)}`, + label: `${$ls(`units.area.${i}`)}`, })), }, input: { - placeholder: `${`${$ls(`icu.enter_*`, { value: `${$ls(`common.farm_size`)}`.toLowerCase() })}`} ${`${$ls(`measurement.area.${val_farmarea_unit}_pl`)}`.toLowerCase()}`, + placeholder: `${`${$ls(`icu.enter_*`, { value: `${$ls(`common.farm_size`)}`.toLowerCase() })}`} ${`${$ls(`units.area.${val_farmarea_unit}_pl`)}`.toLowerCase()}`, field: form_fields.farm_size, }, }} diff --git a/apps-lib/src/lib/features/farm/farms-add-casli-map.svelte b/apps-lib/src/lib/features/farm/farms-add-casli-map.svelte @@ -1,10 +1,13 @@ <script lang="ts"> + import Fade from "$lib/components/lib/fade.svelte"; import { CarouselItem, Map, MapMarkerArea, WrapBorder, app_lo, + focus_map_marker, + geop_is_valid, handle_err, type LcGeocodeCallback, type LcGeocodeCurrentCallback, @@ -34,6 +37,8 @@ let map: maplibregl.Map | undefined = $state(undefined); + const is_valid_geop = $derived(geop_is_valid(map_geop)); + onMount(async () => { try { const geop = await basis.lc_geop_current(); @@ -43,6 +48,7 @@ if (!geoc) return; map_geoc = geoc; if (map) map.setCenter([map_geop.lng, map_geop.lat]); + focus_map_marker(); } catch (e) { handle_err(e, `on_mount`); } @@ -67,25 +73,27 @@ {/if} </Map> </WrapBorder> - {#if map_geop} - <div - class={`flex flex-col w-full gap-1 justify-center items-center`} - > + {#if is_valid_geop} + <Fade> <div - class={`flex flex-row w-full gap-2 justify-center items-center`} + class={`flex flex-col w-full gap-1 justify-center items-center`} > - <p - class={`font-sans font-[500] text-layer-0-glyph tracking-tightest`} - > - {farm_geop_lat} - </p> - <p - class={`font-sans font-[500] text-layer-0-glyph tracking-tightest`} + <div + class={`flex flex-row w-full gap-2 justify-center items-center`} > - {farm_geop_lng} - </p> + <p + class={`font-sans font-[500] text-layer-0-glyph tracking-tightest`} + > + {farm_geop_lat} + </p> + <p + class={`font-sans font-[500] text-layer-0-glyph tracking-tightest`} + > + {farm_geop_lng} + </p> + </div> </div> - </div> + </Fade> {/if} </div> </CarouselItem> diff --git a/apps-lib/src/lib/features/farm/farms-products-review-card.svelte b/apps-lib/src/lib/features/farm/farms-products-review-card.svelte @@ -76,7 +76,7 @@ {`/`} </p> <p class={`font-sans font-[600] text-xl text-th-black`}> - {`${$ls(`measurement.mass.unit.${basis.data.price_quantity_unit}_ab`)}`} + {`${$ls(`units.mass.unit.${basis.data.price_quantity_unit}_ab`)}`} </p> </div> </div> @@ -95,7 +95,7 @@ <p class={`font-sans font-[600] text-lg text-layer-1-glyph`} > - {`${basis.data.quantity_amount} ${$ls(`measurement.mass.unit.${basis.data.quantity_unit}_ab`)} ${basis.data.quantity_label}`} + {`${basis.data.quantity_amount} ${$ls(`units.mass.unit.${basis.data.quantity_unit}_ab`)} ${basis.data.quantity_label}`} </p> </div> </div> diff --git a/apps-lib/src/lib/types/view/farm.ts b/apps-lib/src/lib/types/view/farm.ts @@ -30,9 +30,9 @@ export type IViewFarmsProductsAddSubmission = { export type IViewFarmsAddSubmission = { farm_name: string; - farm_area: number; - farm_area_unit: string; - farm_contact_name: string; + farm_area?: number; + farm_area_unit?: string; + farm_contact_name?: string; geolocation_point: GeolocationPoint; geolocation_address: GeolocationAddress; }; diff --git a/apps-lib/src/lib/util/lib.ts b/apps-lib/src/lib/util/lib.ts @@ -3,7 +3,7 @@ import { goto } from "$app/navigation"; import { page } from "$app/state"; import { win_h, win_w, type CallbackRoute, type NavigationRouteParamKey } from "$root"; import type { ColorMode, ThemeKey } from "@radroots/theme"; -import { encode_route, fmt_geometry_point_coords, fmt_price, parse_currency_marker, type GeometryPoint, type IErrorCatchCallback } from "@radroots/util"; +import { encode_route, fmt_geometry_point_coords, fmt_price, parse_currency_marker, type GeolocationPoint, type GeometryPoint, type IErrorCatchCallback } from "@radroots/util"; import { get } from "svelte/store"; export const get_store = get; @@ -85,4 +85,15 @@ export const window_set = (): void => { if (!browser) return; win_h.set(window.innerHeight); win_w.set(window.innerWidth); +}; + +export const geop_is_valid = (point?: GeolocationPoint): boolean => { + if (!point) return false; + return !(point.lat === 0 && point.lng === 0); +}; +export const geop_init = (): GeolocationPoint => ({ lat: 0, lng: 0 }); + +export const focus_map_marker = (): void => { + const el = document.querySelector(".maplibregl-marker"); + if (el instanceof HTMLElement) el.click(); }; \ No newline at end of file diff --git a/apps-lib/src/lib/util/validation/farm.ts b/apps-lib/src/lib/util/validation/farm.ts @@ -4,9 +4,9 @@ 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, - farm_area_unit: z.string().regex(form_fields.area_unit.validate), - farm_contact_name: z.string().regex(form_fields.contact_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, geolocation_address: schema_geolocation_address, }); \ No newline at end of file diff --git a/apps-lib/src/lib/view/farms-add.svelte b/apps-lib/src/lib/view/farms-add.svelte @@ -1,6 +1,5 @@ <script lang="ts"> import LayoutBottomButton from "$lib/components/layout/layout-bottom-button.svelte"; - import Fade from "$lib/components/lib/fade.svelte"; import { schema_view_farms_add_submission } from "$lib/util/validation/farm"; import { app_platform, @@ -12,6 +11,10 @@ casl_init, FarmsAddCasliDetail, FarmsAddCasliMap, + fmt_id, + focus_map_marker, + geop_init, + geop_is_valid, Glyph, handle_err, LayoutView, @@ -23,6 +26,7 @@ type LcGuiAlertCallback, } from "$root"; import { + el_id, geol_lat_fmt, geol_lng_fmt, parse_float, @@ -56,10 +60,11 @@ let loading = $state(false); - let map_geop: GeolocationPoint = $state({ lat: 0, lng: 0 }); + 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`); @@ -75,18 +80,37 @@ }); const farm_geop_lat = $derived( - map_geop ? geol_lat_fmt(map_geop.lat, `dms`, $locale, 3) : ``, + geop_is_valid(map_geop) + ? geol_lat_fmt(map_geop.lat, `dms`, $locale, 3) + : ``, ); const farm_geop_lng = $derived( - map_geop ? geol_lng_fmt(map_geop.lng, `dms`, $locale, 3) : ``, + 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_0 = async (): Promise<void> => { + console.log(JSON.stringify(map_geop, null, 4), `map_geop`); + console.log(JSON.stringify(map_geoc, null, 4), `map_geoc`); await casl_inc(); }; @@ -98,9 +122,14 @@ const farms_add_submission = schema_view_farms_add_submission.safeParse( { farm_name: val_farmname, - farm_area: parse_float(val_farmarea), - farm_area_unit: val_farmarea_unit, - farm_contact_name: val_farmcontact, + 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, geolocation_address: farm_geolocation_address, } satisfies IViewFarmsAddSubmission, @@ -127,6 +156,17 @@ const handle_back = async (): Promise<void> => { switch ($casl_i) { + case 1: { + if (!geop_is_valid(map_geop)) { + const geop_cur = await basis.lc_geop_current(); + if (geop_cur) { + map_geop = geop_cur; + const geoc_cur = await basis.lc_geocode(geop_cur); + if (geoc_cur) map_geoc = geoc_cur; + focus_map_marker(); + } + } + } default: return await casl_dec(); } @@ -143,39 +183,27 @@ }} > {#snippet header_option()} - {#if $casl_i > 0} - <Fade> - <button - class={`flex flex-row pr-3 justify-center items-center`} - onclick={async () => { - await handle_back(); - }} + {#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-layer-0-glyph-hl`} > - <p - class={`font-sans font-[600] text-lg text-layer-0-glyph`} - > - {`${$ls(`common.back`)}`} - </p> - </button> - </Fade> + {`${$ls(`common.enter_location`)}`} + </p> + <Glyph + basis={{ + classes: `text-layer-0-glyph-hl`, + dim: `md`, + key: `caret-right`, + }} + /> + </button> {/if} - <button - class={`flex flex-row justify-center items-center`} - onclick={async () => { - await handle_continue(); - }} - > - <p class={`font-sans font-[600] text-lg text-layer-0-glyph-hl`}> - {`${$ls(`common.details`)}`} - </p> - <Glyph - basis={{ - classes: `text-layer-0-glyph-hl`, - dim: `md`, - key: `caret-right`, - }} - /> - </button> {/snippet} </PageToolbar> <Carousel> @@ -191,6 +219,7 @@ /> <FarmsAddCasliDetail bind:val_farmname + bind:val_farmaddress bind:val_farmcontact bind:val_farmarea bind:val_farmarea_unit