app

Local-first trade for farms and co-ops
git clone https://radroots.dev/git/app.git
Log | Files | Refs | README | LICENSE

commit 905dac171b07f5d1ce767fc0cd697f386f3224d0
parent 2fda9fa019f0c650bed20950ab8d2370950325f0
Author: triesap <137732411+triesap@users.noreply.github.com>
Date:   Wed, 11 Sep 2024 17:23:29 +0000

Edit `/models/trade-product/add`, edit components, edit utils

Diffstat:
Msrc/lib/components/layout-trellis-line.svelte | 2+-
Msrc/lib/utils/trade_product.ts | 8+++-----
Msrc/routes/(app)/models/trade-product/add/+page.svelte | 212++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
3 files changed, 172 insertions(+), 50 deletions(-)

diff --git a/src/lib/components/layout-trellis-line.svelte b/src/lib/components/layout-trellis-line.svelte @@ -30,7 +30,7 @@ }} > <p - class={`${fmt_cl(basis.notify.label.classes)} font-sans font-[400] uppercase text-layer-2-glyph text-sm`} + class={`${fmt_cl(basis.notify.label.classes)} font-sans font-[600] uppercase text-layer-2-glyph/80 text-xs`} > {basis.notify.label.value} </p> diff --git a/src/lib/utils/trade_product.ts b/src/lib/utils/trade_product.ts @@ -5,18 +5,16 @@ export const trade_product_kv_vals = async (kv_pref: string): Promise<TradeProdu try { const vals = { ...trade_product_form_vals - } + }; for (const [k, field] of Object.entries( trade_product_form_fields, )) { const field_k = parse_trade_product_form_keys(k); if (!field_k) continue; - const field_id = `${kv_pref}-${field_k}` - let field_val = ``; - field_val = await kv.get(field_id); + const field_id = `${kv_pref}-${field_k}`; + const field_val = await kv.get(field_id); if (field_val) vals[field_k] = field_val; - //@todo add validation } return vals; diff --git a/src/routes/(app)/models/trade-product/add/+page.svelte b/src/routes/(app)/models/trade-product/add/+page.svelte @@ -1,5 +1,4 @@ <script lang="ts"> - import { goto } from "$app/navigation"; import { lc } from "$lib/client"; import LayoutTrellisLine from "$lib/components/layout-trellis-line.svelte"; import LayoutTrellis from "$lib/components/layout-trellis.svelte"; @@ -20,12 +19,15 @@ InputSelect, kv, Nav, + NotifyGlyph, sleep, t, } from "@radroots/svelte-lib"; import { + fiat_currencies, fmt_trade_quantity_val, parse_trade_key, + parse_trade_mass_tuple, trade_keys, trade_quantities, type TradeKey, @@ -34,6 +36,8 @@ const trade_key_default: TradeKey = `coffee`; + let el_trellis_wrap_1: HTMLElement | null; + let loading_submit = false; let loading_location = false; @@ -43,16 +47,21 @@ let sel_location_gcs_id = ``; let ls_location_gcs: LocationGcs[] = []; - let sel_price_qty_amt = ``; + let sel_qty_tup = ``; let sel_price_qty_unit = ``; - let show_sel_price_qty_amt_other = false; + let show_sel_qty_tup_other = false; + + let sel_price_currency = ``; + let show_sel_price_currency = false; + + let sel_qty_unit = ``; $: sel_key_parsed = parse_trade_key(sel_key); $: ls_trade_product_quantities = sel_key_parsed ? trade_quantities[sel_key_parsed] : trade_quantities[trade_key_default]; - $: sel_price_qty_amt = sel_key_parsed + $: sel_qty_tup = sel_key_parsed ? fmt_trade_quantity_val(trade_quantities[sel_key_parsed][0]) : fmt_trade_quantity_val(trade_quantities[trade_key_default][0]); @@ -61,15 +70,45 @@ sel_location_gcs_id = ls_location_gcs[0].id; } } - onMount(async () => { - try { - } catch (e) { - } finally { + + $: { + if (sel_location_gcs_id) { + (async () => { + try { + await kv.set( + fmt_id(`location_gcs_id`), + sel_location_gcs_id, + ); + } catch (e) { + console.log(`e `, e); + } + })(); } - }); + } + + $: { + if (sel_qty_tup) { + (async () => { + try { + const tup = parse_trade_mass_tuple(sel_qty_tup); + console.log(`tup `, tup); + if (tup) { + await kv.set(fmt_id(`qty_amt`), tup[0].toString()); + await kv.set(fmt_id(`qty_unit`), tup[1]); + await kv.set(fmt_id(`qty_label`), tup[2]); + } + } catch (e) { + console.log(`e `, e); + } + })(); + } + } onMount(async () => { try { + sel_price_currency = "usd"; + sel_price_qty_unit = "kg"; + sel_qty_unit = "kg"; await fetch_models_location_gcs(); } catch (e) { } finally { @@ -89,23 +128,23 @@ } }; - const toggle_show_price_qty_amt_other = async ( + const toggle_show_qty_amt_other = async ( visible: boolean, ): Promise<void> => { try { - show_sel_price_qty_amt_other = visible; + show_sel_qty_tup_other = visible; if (visible) { sel_price_qty_unit = mass_units[0]; - await kv.set(fmt_id(`price_qty_amt`), ``); + await kv.set(fmt_id(`qty_amt`), ``); } else { - sel_price_qty_amt = sel_key_parsed + sel_qty_tup = sel_key_parsed ? fmt_trade_quantity_val( trade_quantities[sel_key_parsed][0], ) : ``; } } catch (e) { - console.log(`(error) toggle_show_price_qty_amt_other `, e); + console.log(`(error) toggle_show_qty_amt_other `, e); } }; @@ -136,25 +175,23 @@ try { loading_submit = true; - const location_gcs_id = await kv.get(fmt_id(`location_gcs_id`)); - if (!location_gcs_id || typeof location_gcs_id !== `string`) { - await lc.dialog.alert(`The product location is missing.`); - return; - } - const location_gcs_res = await lc.db.location_gcs_get({ - id: location_gcs_id, + id: sel_location_gcs_id, }); if (typeof location_gcs_res === `string`) { - await lc.dialog.alert( - `There was an error finding the selected location`, - ); - await goto(`/`); + await lc.dialog.alert(`The product location is missing.`); return; } const vals = await trade_product_kv_vals(fmt_id()); + if (!vals) { + alert(`@todo!`); + return; + } + if (!vals.year) vals.year = new Date().getFullYear().toString(); + if (!vals.price_qty_amt) vals.price_qty_amt = `1`; + console.log(JSON.stringify(vals, null, 4), `vals`); await sleep(1000); @@ -177,7 +214,6 @@ ? { classes: `w-full justify-end`, label: { - classes: `text-xs font-[600]`, value: `Show Options`, }, callback: async () => { @@ -251,7 +287,7 @@ })), { value: `add-new`, - label: `${$t(`common.add_new_location`)}`, + label: `${$t(`common.add_current_location`)}`, }, ] : [ @@ -263,10 +299,11 @@ }, { value: `add-new`, - label: `${$t(`common.add_new_location`)}`, + label: `${$t(`common.add_current_location`)}`, }, ], callback: async (val) => { + console.log(`val `, val); if (val === `add-new`) { sel_location_gcs_id = ``; await add_model_location_gcs(); @@ -280,15 +317,14 @@ label: { value: `Quantity`, }, - notify: show_sel_price_qty_amt_other + notify: show_sel_qty_tup_other ? { classes: `w-full justify-end`, label: { - classes: `text-xs font-[600]`, value: `Show Options`, }, callback: async () => { - await toggle_show_price_qty_amt_other(false); + await toggle_show_qty_amt_other(false); }, } : undefined, @@ -297,22 +333,22 @@ <div class={`relative flex flex-row w-full gap-3 justify-between items-center h-form_line bg-layer-1-surface text-layer-1-glyph/70 rounded-2xl transition-all`} > - {#if show_sel_price_qty_amt_other} + {#if show_sel_qty_tup_other} <div class={`relative flex flex-row w-full justify-center items-center`} > <InputForm basis={{ - id: fmt_id(`price_qty_amt`), + id: fmt_id(`qty_amt`), layer: false, sync: true, placeholder: `Enter number of ${$t(`trade.quantity.mass_unit.${sel_price_qty_unit}_ab`, { default: sel_price_qty_unit })} per order`, field: { charset: - trade_product_form_fields.price_qty_amt + trade_product_form_fields.qty_amt .charset, validate: - trade_product_form_fields.price_qty_amt + trade_product_form_fields.qty_amt .validation, validate_keypress: true, }, @@ -322,10 +358,10 @@ class={`absolute top-0 right-0 flex flex-row h-full gap-2 justify-center items-center`} > <InputSelect - bind:value={sel_price_qty_unit} + bind:value={sel_qty_unit} basis={{ - id: fmt_id(`price_qty_unit`), - classes: `w-16 text-layer-1-glyph/70 font-[500]`, + id: fmt_id(`qty_unit`), + classes: `w-[3.5rem] text-layer-1-glyph/70 font-[500]`, layer: false, sync: true, options: mass_units.map((i) => ({ @@ -338,14 +374,12 @@ </div> {:else} <InputSelect - bind:value={sel_price_qty_amt} + bind:value={sel_qty_tup} basis={{ - id: fmt_id(`price_qty_tup`), - sync: true, options: [ ...ls_trade_product_quantities.map((i) => ({ - value: `${i.qty_amt}-${i.qty_unit}`, - label: `${i.qty_amt} ${i.qty_unit}${i.label ? ` ${i.label}` : ``}`, + value: fmt_trade_quantity_val(i), + label: `${i.mass} ${$t(`trade.quantity.mass_unit.${i.mass_unit}_ab`, { default: i.mass_unit })} ${i.label}`, })), { value: `other`, @@ -354,7 +388,7 @@ ], callback: async (val) => { if (val === `other`) { - await toggle_show_price_qty_amt_other(true); + await toggle_show_qty_amt_other(true); } }, }} @@ -362,6 +396,96 @@ {/if} </div> </LayoutTrellisLine> + <LayoutTrellisLine + basis={{ + label: { + value: `Price`, + }, + }} + > + <div + bind:this={el_trellis_wrap_1} + class={`relative flex flex-row w-full gap-3 justify-between items-center h-form_line bg-layer-1-surface text-layer-1-glyph/70 rounded-2xl transition-all`} + > + <InputForm + basis={{ + id: fmt_id(`price_amt`), + layer: false, + sync: true, + placeholder: `Enter price`, + field: { + charset: + trade_product_form_fields.price_amt.charset, + validate: + trade_product_form_fields.price_amt.validation, + validate_keypress: true, + }, + callback: async ({ val, pass }) => { + const lastchar = val[val.length - 1]; + const period_count = val.split(".").length - 1; + if ( + (pass && + lastchar !== `.` && + period_count < 2) || + val.length < 1 + ) { + el_trellis_wrap_1?.classList.remove( + `bg-layer-1-surface-err`, + ); + show_sel_price_currency = false; + } else { + el_trellis_wrap_1?.classList.add( + `bg-layer-1-surface-err`, + ); + show_sel_price_currency = true; + } + }, + }} + /> + <div + class={`flex flex-row gap-2 pr-4 justify-end items-center`} + > + <InputSelect + bind:value={sel_price_currency} + basis={{ + id: fmt_id(`price_currency`), + classes: `w-fit`, + layer: false, + hide_arrows: true, + sync: true, + options: fiat_currencies.map((i) => ({ + value: i, + label: `${$t(`trade.currency.${i}.symbol`, { default: i })}`, + })), + }} + /> + <p + class={`font-sans font-[500] text-layer-1-glyph/60 text-lg -translate-y-[1px]`} + > + {`/`} + </p> + <InputSelect + bind:value={sel_price_qty_unit} + basis={{ + id: fmt_id(`price_qty_unit`), + classes: `w-fit`, + layer: false, + hide_arrows: true, + sync: true, + options: mass_units.map((i) => ({ + value: i, + label: `${$t(`trade.quantity.mass_unit.${i}_ab`, { default: i })}`, + })), + }} + /> + </div> + {#if show_sel_price_currency} + <NotifyGlyph + basis={{ glyph: `warning-circle`, layer: 2 }} + /> + {/if} + </div> + </LayoutTrellisLine> </LayoutTrellis> </LayoutView> <Nav