commit 330790073795c580115b921006f9530d0b93d565 parent 5b5b105959c112b9c0dc5d7b9d420408f03aaa58 Author: triesap <137732411+triesap@users.noreply.github.com> Date: Wed, 13 Nov 2024 09:41:53 +0000 Edit `core` add `trade_product_location` model, `tauri` add model handlers, SQL up migration. Update `core` models, `tauri` SQL up migrations. Edit `/models/trade-product/add` add trellis elements, add map envelope, update handlers, add/edit styles. Edit routes. Remove locale defaults. Add/edit components, conf, utils, styles. Diffstat:
30 files changed, 1658 insertions(+), 298 deletions(-)
diff --git a/crates/core/src/models/mod.rs b/crates/core/src/models/mod.rs @@ -3,3 +3,4 @@ pub mod nostr_profile; pub mod nostr_profile_relay; pub mod nostr_relay; pub mod trade_product; +pub mod trade_product_location; diff --git a/crates/core/src/models/trade_product.rs b/crates/core/src/models/trade_product.rs @@ -19,7 +19,7 @@ pub struct TradeProduct { year: i32, qty_amt: i32, qty_unit: String, - qty_label: String, + qty_label: Option<String>, qty_avail: Option<i32>, price_amt: f64, price_currency: String, @@ -39,7 +39,7 @@ pub struct ITradeProductFields { pub year: String, pub qty_amt: String, pub qty_unit: String, - pub qty_label: String, + pub qty_label: Option<String>, pub qty_avail: Option<String>, pub price_amt: String, pub price_currency: String, diff --git a/crates/core/src/models/trade_product_location.rs b/crates/core/src/models/trade_product_location.rs @@ -0,0 +1,51 @@ +use crate::{ + error::ModelError, + models::trade_product::{trade_product_query_bind_values, TradeProductQueryBindValues}, + models::location_gcs::{location_gcs_query_bind_values, LocationGcsQueryBindValues}, +}; + +pub type ITradeProductLocationRelationResolve = bool; + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct ITradeProductLocationRelation { + pub trade_product: TradeProductQueryBindValues, + pub location_gcs: LocationGcsQueryBindValues, +} + +pub async fn lib_model_trade_product_location_set( + db: &sqlx::Pool<sqlx::Sqlite>, + opts: ITradeProductLocationRelation, +) -> Result<ITradeProductLocationRelationResolve, ModelError> { + let (bv_tp_k, bv_tp) = trade_product_query_bind_values(opts.trade_product); + let (bv_lg_k, bv_lg) = location_gcs_query_bind_values(opts.location_gcs); + let query_vals = vec![bv_tp, bv_lg]; + let query = format!("INSERT INTO trade_product_location (tb_tp_lg_0, tb_tp_lg_1) VALUES ((SELECT id FROM trade_product WHERE {} = ?1), (SELECT id FROM location_gcs WHERE {} = ?2));", bv_tp_k, bv_lg_k); + let mut query_builder = sqlx::query(&query); + for value in query_vals.iter() { + query_builder = query_builder.bind(value); + } + query_builder + .execute(db) + .await + .map_err(|e| ModelError::InvalidQuery(e.to_string()))?; + Ok(true) +} + +pub async fn lib_model_trade_product_location_unset( + db: &sqlx::Pool<sqlx::Sqlite>, + opts: ITradeProductLocationRelation, +) -> Result<ITradeProductLocationRelationResolve, ModelError> { + let (bv_tp_k, bv_tp) = trade_product_query_bind_values(opts.trade_product); + let (bv_lg_k, bv_lg) = location_gcs_query_bind_values(opts.location_gcs); + let query_vals = vec![bv_tp, bv_lg]; + let query = format!("DELETE FROM trade_product_location WHERE tb_tp_lg_0 = (SELECT id FROM nostr_profile WHERE {} = ?1) AND tb_tp_lg_1 = (SELECT id FROM nostr_relay WHERE {} = ?2);", bv_tp_k, bv_lg_k); + let mut query_builder = sqlx::query(&query); + for value in query_vals.iter() { + query_builder = query_builder.bind(value); + } + query_builder + .execute(db) + .await + .map_err(|e| ModelError::InvalidQuery(e.to_string()))?; + Ok(true) +} diff --git a/crates/tauri/migrations/0001_location_gcs.sql b/crates/tauri/migrations/0001_location_gcs.sql @@ -2,9 +2,9 @@ CREATE TABLE IF NOT EXISTS location_gcs ( id CHAR(36) PRIMARY KEY NOT NULL UNIQUE CHECK(length(id) = 36), created_at DATETIME NOT NULL CHECK(length(created_at) = 24), updated_at DATETIME NOT NULL CHECK(length(created_at) = 24), - lat FLOAT NOT NULL, - lng FLOAT NOT NULL, - geohash CHAR(12) NOT NULL UNIQUE, + lat REAL NOT NULL, + lng REAL NOT NULL, + geohash CHAR(12) UNIQUE CHECK(length(geohash) = 9), label TEXT, gc_id TEXT, gc_name TEXT, diff --git a/crates/tauri/migrations/0002_trade_product.sql b/crates/tauri/migrations/0002_trade_product.sql @@ -2,20 +2,20 @@ CREATE TABLE IF NOT EXISTS trade_product ( id CHAR(36) PRIMARY KEY NOT NULL UNIQUE CHECK(length(id) = 36), created_at DATETIME NOT NULL CHECK(length(created_at) = 24), updated_at DATETIME NOT NULL CHECK(length(created_at) = 24), - key TEXT, - title TEXT, - summary TEXT, - process TEXT, - lot TEXT, - profile TEXT, + key TEXT NOT NULL, + title TEXT NOT NULL, + summary TEXT NOT NULL, + process TEXT NOT NULL, + lot TEXT NOT NULL, + profile TEXT NOT NULL, year INTEGER NOT NULL, - qty_amt REAL, + qty_amt INTEGER NOT NULL, qty_unit CHAR(4) NOT NULL, qty_label TEXT, qty_avail INTEGER, price_amt REAL NOT NULL, price_currency CHAR(3) NOT NULL, - price_qty_amt REAL, + price_qty_amt INTEGER NOT NULL, price_qty_unit CHAR(4) NOT NULL, notes TEXT ); \ No newline at end of file diff --git a/crates/tauri/migrations/0006_trade_product_location.sql b/crates/tauri/migrations/0006_trade_product_location.sql @@ -0,0 +1,7 @@ +CREATE TABLE IF NOT EXISTS trade_product_location ( + tb_tp_lg_0 CHAR(36), + tb_tp_lg_1 CHAR(36), + FOREIGN KEY (tb_tp_lg_0) REFERENCES trade_product(id) ON DELETE CASCADE, + FOREIGN KEY (tb_tp_lg_1) REFERENCES location_gcs(id) ON DELETE CASCADE, + PRIMARY KEY (tb_tp_lg_0, tb_tp_lg_1) +); +\ No newline at end of file diff --git a/crates/tauri/src/lib.rs b/crates/tauri/src/lib.rs @@ -21,6 +21,9 @@ use models::{ model_trade_product_add, model_trade_product_delete, model_trade_product_get, model_trade_product_update, }, + trade_product_location::{ + model_trade_product_location_set, model_trade_product_location_unset, + }, }; use radroots::Radroots; use tauri::Manager; @@ -71,7 +74,9 @@ pub fn run() { model_nostr_relay_delete, model_nostr_relay_update, model_nostr_profile_relay_set, - model_nostr_profile_relay_unset + model_nostr_profile_relay_unset, + model_trade_product_location_set, + model_trade_product_location_unset ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); diff --git a/crates/tauri/src/models/mod.rs b/crates/tauri/src/models/mod.rs @@ -3,3 +3,4 @@ pub(crate) mod nostr_profile; pub(crate) mod nostr_profile_relay; pub(crate) mod nostr_relay; pub(crate) mod trade_product; +pub(crate) mod trade_product_location; diff --git a/crates/tauri/src/models/trade_product_location.rs b/crates/tauri/src/models/trade_product_location.rs @@ -0,0 +1,32 @@ +use crate::radroots::Radroots; +use radroots_core::{ + models::trade_product_location::{lib_model_trade_product_location_set, lib_model_trade_product_location_unset, ITradeProductLocationRelation, ITradeProductLocationRelationResolve}, +}; + +#[tauri::command] +pub async fn model_trade_product_location_set( + state: tauri::State<'_, Radroots>, + opts: ITradeProductLocationRelation, +) -> Result<ITradeProductLocationRelationResolve, String> { + match lib_model_trade_product_location_set(&state.db, opts).await { + Ok(result) => Ok(result), + Err(e) => { + println!("ERROR {}", e); + Err(e.to_string()) + } + } +} + +#[tauri::command] +pub async fn model_trade_product_location_unset( + state: tauri::State<'_, Radroots>, + opts: ITradeProductLocationRelation, +) -> Result<ITradeProductLocationRelationResolve, String> { + match lib_model_trade_product_location_unset(&state.db, opts).await { + Ok(result) => Ok(result), + Err(e) => { + println!("ERROR {}", e); + Err(e.to_string()) + } + } +} diff --git a/src/lib/components/image_upload_multi.svelte b/src/lib/components/image_upload_multi.svelte @@ -19,6 +19,10 @@ export let photo_paths: string[]; + export let basis: { + id: string; + }; + let photo_file_path_0: string; let photo_file_path_1: string; let photo_file_path_2: string; @@ -44,6 +48,10 @@ try { const photo_paths_select = await dialog.open_photos(); if (!photo_paths_select) return; + console.log( + `photo_paths_select.results[0] `, + photo_paths_select.results[0], + ); photo_paths = list_assign(photo_paths, photo_paths_select.results); } catch (e) { console.log(`(error) handle_photo_add `, e); @@ -78,8 +86,9 @@ }; </script> -<div class={`flex flex-col h-[13rem] w-full px-4 justify-center items-center`}> - <div +<div class={`flex flex-col w-full px-4 justify-start items-center`}> + <button + id={basis.id} class={`flex flex-row h-[11rem] w-[22rem] justify-center items-center bg-layer-1-surface rounded-[2rem] overflow-hidden`} > <button @@ -270,12 +279,14 @@ {/if} </button> </div> - </div> + </button> <div class={`flex flex-row h-8 w-${$app_layout} justify-start items-center`} > <div class={`flex flex-row w-[11rem] justify-center items-center`}> - <p class={`font-sans font-[500] text-sm text-layer-0-glyph`}> + <p + class={`font-sans font-[500] text-[0.9rem] text-layer-0-glyph/80 scale-y-[94%]`} + > {`${$t(`icu.primary_*`, { value: `${$t(`common.photo`)}` })}`} </p> </div> diff --git a/src/lib/components/map_point_select_envelope.svelte b/src/lib/components/map_point_select_envelope.svelte @@ -4,15 +4,16 @@ import type { GeocoderReverseResult } from "@radroots/geocoder"; import { app_thc, + envelope_tilt, envelope_visible, EnvelopeLower, - fmt_geol_latitude, - fmt_geol_longitude, + Glyph, t, type CallbackPromise, } from "@radroots/svelte-lib"; import { MapLibre, Marker } from "@radroots/svelte-maplibre"; import type { GeolocationCoordinatesPoint } from "@radroots/utils"; + import { onDestroy, onMount } from "svelte"; import MapMarkerDot from "./map_marker_dot.svelte"; import MapPopupPointGeolocation from "./map_popup_point_geolocation.svelte"; @@ -21,12 +22,29 @@ undefined; export let basis: { - visible: Boolean; + visible: boolean; close: CallbackPromise; }; + $: basis = basis; let map_point_center: GeolocationCoordinatesPoint = cfg.map.coords.default; + onMount(async () => { + try { + envelope_tilt.set(false); + } catch (e) { + } finally { + } + }); + + onDestroy(async () => { + try { + envelope_tilt.set(true); + } catch (e) { + } finally { + } + }); + $: envelope_visible.set(!!basis.visible); $: if ( @@ -107,17 +125,28 @@ </Marker> </MapLibre> <div - class={`absolute top-6 left-4 flex flex-col min-w-[180px] px-4 py-1 justify-start items-start bg-layer-1-surface rounded-xl shadow-md`} + class={`absolute top-16 left-0 flex flex-col w-full pt-1 justify-center items-center`} > - <p class={`font-sans font-[400] text-layer-0-glyph capitalize`}> - {`${`${$t(`common.current_location`)}`}:`} - </p> - <p class={`font-sans font-[400] text-layer-0-glyph`}> - {`${fmt_geol_latitude(map_point_select.lat, `dms`)}`} - </p> - <p class={`font-sans font-[400] text-layer-0-glyph`}> - {`${fmt_geol_longitude(map_point_select.lng, `dms`)}`} - </p> + <button + class={`group flex flex-row h-8 px-4 gap-2 justify-center items-center bg-layer-1-surface active:bg-layer-1-surface_a rounded-2xl shadow-md el-re`} + on:click={async () => { + await basis.close(); + }} + > + <Glyph + basis={{ + classes: `text-layer-0-glyph`, + dim: `xs`, + weight: `bold`, + key: `arrow-up`, + }} + /> + <p + class={`font-sans font-[400] text-layer-0-glyph text-[1rem] capitalize`} + > + {`${$t(`common.back`)}`} + </p> + </button> </div> {/if} </EnvelopeLower> diff --git a/src/lib/components/map_popup_point_geolocation.svelte b/src/lib/components/map_popup_point_geolocation.svelte @@ -1,11 +1,17 @@ <script lang="ts"> import type { GeocoderReverseResult } from "@radroots/geocoder"; + import { + fmt_geol_latitude, + fmt_geol_longitude, + Glyph, + } from "@radroots/svelte-lib"; import type { GeolocationCoordinatesPoint } from "@radroots/utils"; export let basis: { point: GeolocationCoordinatesPoint; geoc?: GeocoderReverseResult; }; + $: basis = basis; </script> <button @@ -13,20 +19,52 @@ on:click={async () => {}} > <div - class={`flex flex-col w-fit px-4 py-[0.6rem] gap-2 justify-start items-start bg-layer-1-surface round-40`} + class={`flex flex-col w-fit px-5 py-[0.7rem] gap-2 justify-start items-start bg-layer-1-surface round-20 shadow-lg`} > {#if basis.geoc} - <div class={`flex flex-col w-full gap-1 justify-start items-start`}> - <p - class={`font-circ font-[400] text-[1.1rem] scale-y-[92%] tracking-tight text-layer-2-glyph`} + <div class={`flex flex-col w-full gap-2 justify-start items-start`}> + <div + class={`flex flex-col w-full gap-1 justify-start items-start`} > - {basis.geoc.name} - </p> - <p - class={`font-circ font-[400] text-[1.1rem] scale-y-[92%] tracking-tight text-layer-2-glyph`} - > - {`${basis.geoc.admin1_name}, ${basis.geoc.country_name}`} - </p> + <div + class={`flex flex-row gap-1 justify-start items-center`} + > + <p + class={`font-sans font-[500] text-[1.05rem] text-layer-2-glyph`} + > + {basis.geoc.name} + </p> + <Glyph + basis={{ + classes: `text-layer-2-glyph -translate-y-[2px]`, + dim: `xs`, + weight: `bold`, + key: `map-pin-simple`, + }} + /> + </div> + <div + class={`flex flex-row w-full justify-start items-center`} + > + <p + class={`font-sans font-[500] text-[1rem] tracking-tight text-layer-2-glyph`} + > + {`${basis.geoc.admin1_name}, ${basis.geoc.country_name}`} + </p> + </div> + </div> + <div class={`flex flex-col w-full justify-start items-start`}> + <p + class={`font-sans font-[400] text-[0.9rem] text-layer-0-glyph`} + > + {`${fmt_geol_latitude(basis.point.lat, `dms`)}`} + </p> + <p + class={`font-sans font-[400] text-[0.9rem] text-layer-0-glyph`} + > + {`${fmt_geol_longitude(basis.point.lng, `dms`)}`} + </p> + </div> </div> {:else} <div class={`flex flex-row w-full justify-start items-center`}> diff --git a/src/lib/components/trade_field_display_el.svelte b/src/lib/components/trade_field_display_el.svelte @@ -0,0 +1,59 @@ +<script lang="ts"> + import { fmt_cl, Glyph, type IClOpt } from "@radroots/svelte-lib"; + + export let basis: { + visible: boolean; + label: string; + display: IClOpt & { + undef?: string; + value: string; + nostyle?: boolean; + hide?: boolean; + }; + arrow_visible?: boolean; + slot_before?: boolean; + }; + $: basis = basis; + + $: classes_undef = + basis.visible && `value` in basis.display && !basis.display.value + ? `opacity-60` + : ``; +</script> + +<div class={`flex flex-row h-6 w-full justify-between items-center`}> + <p + class={`font-sans font-[400] text-layer-1-glyph_d text-[1.05rem] capitalize`} + > + {basis.label} + </p> + {#if basis.visible} + <button + class={`flex flex-row max-w-[220px] gap-1 justify-center items-center`} + on:click={async () => {}} + > + {#if basis.slot_before} + <slot /> + {/if} + {#if !basis.display.hide} + <p + class={`${fmt_cl(basis.display.classes)} font-sans font-[400] text-[1.05rem] text-justify truncate text-layer-1-glyph_d ${classes_undef} ${basis.display.nostyle ? `` : `capitalize`}`} + > + {basis.display.value || basis.display.undef || ``} + </p> + {/if} + {#if !basis.slot_before} + <slot /> + {/if} + {#if basis.arrow_visible} + <Glyph + basis={{ + classes: `text-layer-0-glyph ${classes_undef} pt-1`, + dim: `xs`, + key: `caret-right`, + }} + /> + {/if} + </button> + {/if} +</div> diff --git a/src/lib/components/trade_field_display_kv.svelte b/src/lib/components/trade_field_display_kv.svelte @@ -0,0 +1,84 @@ +<script lang="ts"> + import { el_focus } from "$lib/utils/client"; + import { + fmt_cl, + fmt_id, + Glyph, + kv, + type CallbackPromise, + type IClOpt, + } from "@radroots/svelte-lib"; + + export let basis: IClOpt & { + visible: boolean; + label: string; + display: IClOpt & { + undef?: string; + nostyle?: boolean; + } & ( + | { + kv: string; + } + | { + value: string; + } + ); + + kv_wrap?: string; + handle_back: CallbackPromise; + }; + $: basis = basis; + + $: classes_undef = + basis.visible && + ((`kv` in basis.display && !kv.get(fmt_id(basis.display.kv))) || + (`value` in basis.display && !basis.display.value)) + ? `opacity-60` + : ``; +</script> + +<div + class={`${fmt_cl(basis.classes)} flex flex-row h-6 w-full justify-between items-start`} +> + <p + class={`font-sans font-[400] text-layer-1-glyph_d text-[1.05rem] capitalize`} + > + {basis.label} + </p> + {#if basis.visible} + <button + class={`flex flex-row max-w-[210px] gap-1 justify-end items-start`} + on:click={async () => { + await el_focus( + fmt_id( + basis.kv_wrap + ? basis.kv_wrap + : `kv` in basis.display + ? `${basis.display.kv}_wrap` + : ``, + ), + async () => await basis.handle_back(), + ); + }} + > + <p + class={`${fmt_cl(basis.display.classes)} font-sans font-[400] text-[1.05rem] text-justify truncate text-layer-1-glyph_d ${classes_undef} ${basis.display.nostyle ? `` : `capitalize`}`} + > + {#if `kv` in basis.display} + {#await kv.get(fmt_id(basis.display.kv)) then kv_val} + {kv_val || basis.display.undef || ``} + {/await} + {:else} + {basis.display.value || basis.display.undef || ``} + {/if} + </p> + <Glyph + basis={{ + classes: `text-layer-0-glyph ${classes_undef} pt-1`, + dim: `xs`, + key: `caret-right`, + }} + /> + </button> + {/if} +</div> diff --git a/src/lib/conf.ts b/src/lib/conf.ts @@ -16,8 +16,10 @@ export const ks = { nostr_publickey: `keys:nostr:`, } }; + export const ascii = { - bullet: '•' + bullet: '•', + dash: `—` } export const cfg = { @@ -37,9 +39,6 @@ export const cfg = { nostr_relay_poll_document: 3000, entry_focus: 2000, }, - num: { - str: (num: number) => num.toString(), - }, cmd: { layout_route: `*-route` }, diff --git a/src/lib/utils/client.ts b/src/lib/utils/client.ts @@ -1,5 +1,6 @@ import { db, keystore } from "$lib/client"; -import { app_notify, route, type NavigationRoute } from "@radroots/svelte-lib"; +import { app_notify, el_id, route, sleep, type NavigationRoute } from "@radroots/svelte-lib"; +import type { ThemeLayer } from "@radroots/theme"; import type { ErrorMessage } from "@radroots/utils"; export const keystore_reset = async (): Promise<ErrorMessage<string> | undefined> => { @@ -49,3 +50,16 @@ export const reset_device = async (): Promise<ErrorMessage<string> | undefined> console.log(`(error) reset_device `, e); } }; + +export const el_focus = async (id: string, callback: () => Promise<void>, layer: ThemeLayer = 1): Promise<void> => { + try { + const el = el_id(id); + el?.classList.add(`entry-layer-${layer}-highlight`); + el?.focus(); + await sleep(1200); + await callback(); + el?.classList.remove(`entry-layer-${layer}-highlight`); + } catch (e) { + console.log(`(error) el_focus `, e); + } +}; +\ No newline at end of file diff --git a/src/lib/utils/geocode.ts b/src/lib/utils/geocode.ts @@ -1,5 +1,6 @@ import { geoc } from "$lib/client"; import type { GeocoderReverseResult } from "@radroots/geocoder"; +import type { LocationGcs } from "@radroots/models"; import type { GeolocationCoordinatesPoint } from "@radroots/utils"; export const geoc_rev = async (point: GeolocationCoordinatesPoint): Promise<GeocoderReverseResult | undefined> => { @@ -10,4 +11,39 @@ export const geoc_rev = async (point: GeolocationCoordinatesPoint): Promise<Geoc } catch (e) { console.log(`(error) geoc_rev `, e); } +}; + +export const location_gcs_to_geoc = (opts: LocationGcs): GeocoderReverseResult | undefined => { + const { + gc_id: id, + gc_name: name, + gc_admin1_id: admin1_id, + gc_admin1_name: admin1_name, + gc_country_id: country_id, + gc_country_name: country_name, + lat: latitude, + lng: longitude, + } = opts; + if ( + (typeof id === `string` && id) && + (typeof name === `string` && name) && + (typeof admin1_id === `string` && admin1_id) && + (typeof admin1_name === `string` && admin1_name) && + (typeof country_id === `string` && country_id) && + (typeof country_name === `string` && country_name) && + (typeof latitude === `number`) && + (typeof longitude === `number`) + ) { + return { + id: Number(id), + name, + admin1_id, + admin1_name, + country_id, + country_name, + latitude, + longitude + } + } + return undefined; }; \ No newline at end of file diff --git a/src/lib/utils/kv.ts b/src/lib/utils/kv.ts @@ -13,10 +13,7 @@ export const kv_init_page = async (): Promise<void> => { export const kv_sync = async (list: [string, string][]): Promise<void> => { try { - for (const [key, val] of list) { - await kv.set(key, val); - // await sleep(50); - } + for (const [key, val] of list) await kv.set(key, val); } catch (e) { console.log(`(error) kv_sync `, e); } diff --git a/src/lib/utils/models.ts b/src/lib/utils/models.ts @@ -2,24 +2,24 @@ import { db, geoc } from "$lib/client"; import type { IClientGeolocationPosition } from "@radroots/client"; import type { GeocoderReverseResult } from "@radroots/geocoder"; import type { ILocationGcsAddResolve, LocationGcsFormFields } from "@radroots/models"; -import { err_msg, location_geohash } from "@radroots/utils"; +import { err_msg, location_geohash, type GeolocationCoordinatesPoint } from "@radroots/utils"; export const model_location_gcs_add_position = async (opts: { label?: string; - geo_loc: IClientGeolocationPosition; + geo_pos: IClientGeolocationPosition; }): Promise<ILocationGcsAddResolve<string>> => { try { - const { label, geo_loc } = opts; + const { label, geo_pos } = opts; const fields: LocationGcsFormFields = { - lat: geo_loc.lat.toString(), - lng: geo_loc.lng.toString(), - geohash: location_geohash(geo_loc), + lat: geo_pos.lat.toString(), + lng: geo_pos.lng.toString(), + geohash: location_geohash(geo_pos), } if (label) fields.label = label; const geoc_rev = await geoc.reverse({ point: { - lat: geo_loc.lat, - lng: geo_loc.lng + lat: geo_pos.lat, + lng: geo_pos.lng } }); if (`results` in geoc_rev && geoc_rev.results.length > 0) { @@ -42,13 +42,14 @@ export const model_location_gcs_add_position = async (opts: { export const model_location_gcs_add_geocode = async (opts: { label?: string; geo_code: GeocoderReverseResult; + point: GeolocationCoordinatesPoint; }): Promise<ILocationGcsAddResolve<string>> => { try { - const { label, geo_code } = opts; + const { label, geo_code, point } = opts; const fields: LocationGcsFormFields = { - lat: geo_code.latitude.toString(), - lng: geo_code.longitude.toString(), - geohash: location_geohash({ lat: geo_code.latitude, lng: geo_code.longitude }), + lat: point.lat.toString(), + lng: point.lng.toString(), + geohash: location_geohash(point), gc_id: geo_code.id.toString(), gc_name: geo_code.name, gc_admin1_id: geo_code.admin1_id.toString(), diff --git a/src/routes/(app)/+page.svelte b/src/routes/(app)/+page.svelte @@ -114,7 +114,7 @@ </p> </button> </div> - <div class={`flex flex-col pt-2 justify-center items-center`}> + <!--<div class={`flex flex-col pt-2 justify-center items-center`}> {#if tmp_show_no_profile} <button class={`relative flex flex-row h-24 w-${$app_layout} p-4 gap-4 justify-center items-center bg-layer-2-surface/60 round-20 touch-layer-1 touch-layer-1-raise-less el-re`} @@ -156,7 +156,7 @@ /> </button> {/if} - </div> + </div>--> <div class={`flex flex-col w-full gap-[2px] justify-start items-center`}> <div class={`flex flex-row w-full px-6 justify-center items-center`}> <TrellisTitle diff --git a/src/routes/(app)/models/location-gcs/+page.svelte b/src/routes/(app)/models/location-gcs/+page.svelte @@ -36,7 +36,7 @@ if (`err` in location_gcss) { app_notify.set(`${$t(`error.client.page.load`)}`); return; - } else if (location_gcss.results.length < 1) { + } else if (!location_gcss.results.length) { app_notify.set(`${$t(`error.client.page.load`)}`); return; } diff --git a/src/routes/(app)/models/nostr-profile/edit/field/+page.svelte b/src/routes/(app)/models/nostr-profile/edit/field/+page.svelte @@ -61,7 +61,7 @@ let val_field_valid = false; $: translated_field_key = ld?.field_key - ? `${$t(`model.nostr_profile.${ld?.field_key}`, { default: ld?.field_key?.replaceAll(`_`, ` `) })}`.toLowerCase() + ? `${$t(`models.nostr_profile.fields.${ld.field_key}.label`)}`.toLowerCase() : ``; $: if (el_input_loaded && el_input) { @@ -77,7 +77,7 @@ `${$t(`icu.error_loading_*`, { value: `${$t(`common.profile`)}` })}`, ); return; - } else if (nostr_profiles.results.length < 1) { + } else if (!nostr_profiles.results.length) { app_notify.set( `${$t(`icu.error_loading_*`, { value: `${$t(`common.page`)}` })}`, ); diff --git a/src/routes/(app)/models/nostr-profile/view/+page.svelte b/src/routes/(app)/models/nostr-profile/view/+page.svelte @@ -56,7 +56,7 @@ if (`err` in nostr_profiles) { app_notify.set(`${$t(`error.client.page.load`)}`); return; - } else if (nostr_profiles.results.length < 1) { + } else if (nostr_profiles.results) { app_notify.set(`${$t(`error.client.page.load`)}`); return; } diff --git a/src/routes/(app)/models/nostr-relay/view/+page.svelte b/src/routes/(app)/models/nostr-relay/view/+page.svelte @@ -40,7 +40,7 @@ if (`err` in nostr_relays) { app_notify.set(`${$t(`error.client.page.load`)}`); return; - } else if (nostr_relays.results.length < 1) { + } else if (!nostr_relays.results.length) { app_notify.set(`${$t(`error.client.page.load`)}`); return; } @@ -171,7 +171,7 @@ args: { layer: 1, title: { - value: `${$t(`model.nostr_relay.pubkey`)}`, + value: `${$t(`models.nostr_relay.fields.pubkey.label`)}`, }, list: [ { @@ -201,7 +201,7 @@ args: { layer: 1, title: { - value: `${$t(`model.nostr_relay.description`)}`, + value: `${$t(`models.nostr_relay.fields.description.label`)}`, }, list: [ { @@ -214,7 +214,7 @@ value: ld.nostr_relay .description || - `${$t(`icu.no_*_published`, { value: `${$t(`model.nostr_relay.description`)}`.toLowerCase() })}`, + `${$t(`icu.no_*_published`, { value: `${$t(`models.nostr_relay.fields.description.label`)}`.toLowerCase() })}`, }, ], }, @@ -229,7 +229,7 @@ args: { layer: 1, title: { - value: `${$t(`model.nostr_relay.software`)}`, + value: `${$t(`models.nostr_relay.fields.software.label`)}`, }, list: [ { @@ -241,7 +241,7 @@ classes: `text-layer-1-glyph`, value: ld.nostr_relay.software || - `${$t(`icu.no_*_published`, { value: `${$t(`model.nostr_relay.software`)}`.toLowerCase() })}`, + `${$t(`icu.no_*_published`, { value: `${$t(`models.fields.nostr_relay.software.label`)}`.toLowerCase() })}`, }, ], }, @@ -256,7 +256,7 @@ args: { layer: 1, title: { - value: `${$t(`model.nostr_relay.version`)}`, + value: `${$t(`models.nostr_relay.fields.version.label`)}`, }, list: [ { @@ -268,7 +268,7 @@ classes: `text-layer-1-glyph`, value: ld.nostr_relay.version || - `${$t(`icu.no_*_published`, { value: `${$t(`model.nostr_relay.version`)}`.toLowerCase() })}`, + `${$t(`icu.no_*_published`, { value: `${$t(`models.nostr_relay.fields.version.label`)}`.toLowerCase() })}`, }, ], }, @@ -283,7 +283,7 @@ args: { layer: 1, title: { - value: `${$t(`model.nostr_relay.supported_nips`)}`, + value: `${$t(`models.nostr_relay.fields.supported_nips.label`)}`, }, list: [ { @@ -296,7 +296,7 @@ value: ld.nostr_relay .supported_nips || - `${$t(`icu.no_*_published`, { value: `${$t(`supported_nips`)}`.toLowerCase() })}`, + `${$t(`icu.no_*_published`, { value: `${$t(`models.nostr_relay.fields.supported_nips.label`)}`.toLowerCase() })}`, }, ], }, diff --git a/src/routes/(app)/models/trade-product/+page.svelte b/src/routes/(app)/models/trade-product/+page.svelte @@ -31,14 +31,12 @@ const trade_products = await db.trade_product_get({ list: [`all`], }); - console.log(`trade_products `, trade_products); if (`err` in trade_products) { app_notify.set( `${$t(`icu.error_loading_*`, { value: `${$t(`common.page`)}` })}`, ); return; } - const data: LoadData = { trade_products: trade_products.results, }; diff --git a/src/routes/(app)/models/trade-product/add/+page.svelte b/src/routes/(app)/models/trade-product/add/+page.svelte @@ -1,36 +1,75 @@ <script lang="ts"> - import { dialog, geol } from "$lib/client"; + import { db, dialog, geol } from "$lib/client"; import ImageUploadMulti from "$lib/components/image_upload_multi.svelte"; import MapPointSelectEnvelope from "$lib/components/map_point_select_envelope.svelte"; - import { tradeproduct_init_kv } from "$lib/utils/trade_product"; + import TradeFieldDisplayEl from "$lib/components/trade_field_display_el.svelte"; + import TradeFieldDisplayKv from "$lib/components/trade_field_display_kv.svelte"; + import { ascii } from "$lib/conf"; + import { el_focus } from "$lib/utils/client"; + import { location_gcs_to_geoc } from "$lib/utils/geocode"; + import { kv_init_page } from "$lib/utils/kv"; + import { model_location_gcs_add_geocode } from "$lib/utils/models"; + import { + trade_product_fields_validate, + tradeproduct_init_kv, + tradeproduct_validate_fields, + } from "$lib/utils/trade_product"; import type { GeocoderReverseResult } from "@radroots/geocoder"; - import { trade_product_form_fields } from "@radroots/models"; import { + trade_product_form_fields, + type LocationGcs, + } from "@radroots/models"; + import { + app_layout, + carousel_dec, + carousel_inc, carousel_index, carousel_index_max, carousel_num, el_id, EntryLine, + EntryMultiline, EntrySelect, + EntryWrap, fmt_id, + fmt_price, + Glyph, + InputElement, + int_step, kv, layout_view_cover, LayoutTrellis, LayoutTrellisLine, LayoutView, + locale, Nav, + route, + SelectElement, t, view_effect, } from "@radroots/svelte-lib"; import { + fiat_currencies, + fmt_currency_price, + fmt_trade_quantity_tup, + mass_tf_u, + mass_units, + num_str, + parse_currency_marker, + parse_currency_price, parse_trade_key, + parse_trade_quantity_tup, + sum_currency_price, trade, trade_keys, + year_curr, + type CurrencyPrice, type GeolocationCoordinatesPoint, type TradeKey, + type TradeQuantity, } from "@radroots/utils"; import { onMount } from "svelte"; - import { fade } from "svelte/transition"; + import { writable } from "svelte/store"; type CarouselParam = { label_prev?: string; @@ -38,12 +77,12 @@ }; const page_param: { carousel: Record<View, Map<number, CarouselParam>>; - trade_product: { - key_default: TradeKey; + default: { + tradepr_key: TradeKey; }; } = { carousel: { - fl_1: new Map<number, CarouselParam>([ + c_1: new Map<number, CarouselParam>([ [ 0, { @@ -53,30 +92,24 @@ [ 1, { - label_next: `${$t(`common.location`)}`, + label_next: `${$t(`common.add`)}`, }, ], [ 2, { - label_next: `*`, - }, - ], - [ - 3, - { - label_next: `Post`, + label_next: ``, }, ], ]), }, - trade_product: { - key_default: `coffee`, + default: { + tradepr_key: `coffee`, }, }; - let view_init: View = `fl_1`; - type View = `fl_1`; + let view_init: View = `c_1`; + type View = `c_1`; let view: View = view_init; $: { view_effect<View>(view); @@ -84,48 +117,130 @@ let load_submit = false; - let tradeproduct_photo_paths: string[] = []; + let tradepr_photo_paths: string[] = []; - let tradeproduct_key_sel_toggle = false; - let tradeproduct_key_sel = ``; - $: tradeproduct_key_parsed = parse_trade_key(tradeproduct_key_sel); - $: tradeproduct_key_quantities_list = tradeproduct_key_parsed - ? trade.key[tradeproduct_key_parsed].quantity + let tradepr_key_sel_toggle = false; + let tradepr_key_sel = ``; + $: tradepr_key_parsed = parse_trade_key(tradepr_key_sel); + $: tradepr_key_quantities_list = tradepr_key_parsed + ? trade.key[tradepr_key_parsed].quantity : trade.default.quantity; - let tradeproduct_process_sel = ``; - let tradeproduct_process_sel_toggle = false; - $: tradeproduct_process_list = tradeproduct_key_parsed - ? trade.key[tradeproduct_key_parsed].process + let tradepr_process_sel = ``; + let tradepr_process_sel_toggle = false; + $: tradepr_process_list = tradepr_key_parsed + ? trade.key[tradepr_key_parsed].process : []; - let tradeproduct_location_sel = ``; - let tradeproduct_location_select_vis = false; - let tradeproduct_location_select_point: - | GeolocationCoordinatesPoint - | undefined = undefined; - let tradeproduct_location_select_geoc: GeocoderReverseResult | undefined = + const tradepr_lgc_sel = writable<string>(``); + let tradepr_lgc_sel_geoc: GeocoderReverseResult | undefined = undefined; + let tradepr_lgc_map_vis = false; + let tradepr_lgc_map_point: GeolocationCoordinatesPoint | undefined = undefined; + let tradepr_lgc_map_geoc: GeocoderReverseResult | undefined = undefined; + let tradepr_lgc_list: LocationGcs[] = []; + + let tradepr_price_amt_val = ``; + let tradepr_price_curr_sel = ``; + let tradepr_price_qty_unit_sel = ``; + + const tradepr_qty_tup_sel = writable<string>(``); + let tradepr_qty_tup_sel_toggle = false; + let tradepr_qty_unit_sel = ``; + const tradepr_qty_avail = writable<number>(1); + + let tradepr_parsed_quantity: TradeQuantity | undefined = undefined; onMount(async () => { try { - await handle_view(view_init); - layout_view_cover.set(false); - carousel_index.set(0); - carousel_index_max.set(page_param.carousel[view].size - 1); - await setup_tests(); + await init_page(); } catch (e) { } finally { } }); - const setup_tests = async (): Promise<void> => { + const init_page = async (): Promise<void> => { try { + await kv_init_page(); + await handle_view(view_init); + layout_view_cover.set(false); + carousel_index.set(0); + carousel_index_max.set(page_param.carousel[view].size - 1); + carousel_num.set(0); + tradepr_price_curr_sel = `eur`; + tradepr_price_qty_unit_sel = `kg`; + tradepr_qty_unit_sel = `kg`; + const location_gcs_get_ls = await db.location_gcs_get({ + list: [`all`], + }); + if (`results` in location_gcs_get_ls) + tradepr_lgc_list = location_gcs_get_ls.results; } catch (e) { - console.log(`(error) setup_tests `, e); + console.log(`(error) init_page `, e); } }; + let tradepr_cprice_amt: CurrencyPrice | undefined = undefined; + $: tradepr_cprice_amt = + tradepr_price_amt_val && tradepr_price_curr_sel + ? parse_currency_price( + $locale, + tradepr_price_curr_sel, + tradepr_price_amt_val, + ) + : undefined; + + let tradepr_cprice_total: CurrencyPrice | undefined = undefined; + $: tradepr_cprice_total = + tradepr_cprice_amt && tradepr_parsed_quantity + ? parse_currency_price( + $locale, + tradepr_cprice_amt.cur, + sum_currency_price(tradepr_cprice_amt) * + mass_tf_u( + tradepr_parsed_quantity?.mass_unit, + tradepr_price_qty_unit_sel, + tradepr_parsed_quantity?.mass, + ) * + $tradepr_qty_avail, + ) + : undefined; + + tradepr_qty_avail.subscribe(async (_tradepr_qty_avail) => { + if (_tradepr_qty_avail < 1) { + tradepr_qty_avail.set(Math.max(_tradepr_qty_avail, 1)); + return; + } + }); + + tradepr_qty_tup_sel.subscribe(async (_tradepr_qty_tup_sel) => { + tradepr_parsed_quantity = + parse_trade_quantity_tup(_tradepr_qty_tup_sel); + if (tradepr_parsed_quantity) { + await kv.set( + fmt_id(`qty_amt`), + num_str(tradepr_parsed_quantity.mass), + ); + await kv.set(fmt_id(`qty_unit`), tradepr_parsed_quantity.mass_unit); + await kv.set(fmt_id(`qty_label`), tradepr_parsed_quantity.label); + } + }); + + tradepr_lgc_sel.subscribe(async (_tradepr_lgc_sel) => { + if (!_tradepr_lgc_sel) return; + else if (_tradepr_lgc_sel.startsWith(`*`) && tradepr_lgc_map_geoc) { + tradepr_lgc_sel_geoc = tradepr_lgc_map_geoc; + } else { + const location_gcs_sel = await db.location_gcs_get_one({ + id: _tradepr_lgc_sel, + }); + if (`result` in location_gcs_sel) + tradepr_lgc_sel_geoc = location_gcs_to_geoc( + location_gcs_sel.result, + ); + } + }); + const handle_view = async (view_new: View): Promise<void> => { try { carousel_index.set(0); @@ -135,7 +250,7 @@ } }; - const handle_tradeproduct_key_toggle = async ( + const handle_tradepr_key_toggle = async ( vis_input: boolean, ): Promise<void> => { try { @@ -146,14 +261,14 @@ }); if (!confirm) return; } - tradeproduct_key_sel_toggle = vis_input; - if (vis_input) tradeproduct_key_sel = ``; + tradepr_key_sel_toggle = vis_input; + if (vis_input) tradepr_key_sel = ``; } catch (e) { - console.log(`(error) handle_tradeproduct_key_toggle `, e); + console.log(`(error) handle_tradepr_key_toggle `, e); } }; - const handle_tradeproduct_process_toggle = async ( + const handle_tradepr_process_toggle = async ( vis_input: boolean, ): Promise<void> => { try { @@ -164,33 +279,74 @@ }); if (!confirm) return; } - tradeproduct_process_sel_toggle = vis_input; - if (vis_input) tradeproduct_process_sel = ``; + tradepr_process_sel_toggle = vis_input; + if (vis_input) tradepr_process_sel = ``; + } catch (e) { + console.log(`(error) handle_tradepr_process_toggle `, e); + } + }; + + const handle_tradepr_qty_amt_toggle = async ( + vis_input: boolean, + ): Promise<void> => { + try { + if (vis_input) { + tradepr_qty_tup_sel.set(``); + } else { + const kv_curr = await kv.get(fmt_id(`qty_amt`)); + if (kv_curr) { + const kv_curr_unit = await kv.get(fmt_id(`qty_unit`)); + const confirm = await dialog.confirm({ + message: `${$t(`icu.the_current_entry_*_will_be_deleted`, { value: `${kv_curr}${kv_curr_unit ? ` ${kv_curr_unit}` : `${$t(`measurement.mass.unit.${kv_curr_unit}_ab`)}`}` })}. ${$t(`common.do_you_want_to_continue_q`)}`, + }); + if (!confirm) return; + await kv.delete(fmt_id(`qty_amt`)); + } + } + tradepr_qty_tup_sel_toggle = vis_input; } catch (e) { - console.log(`(error) handle_tradeproduct_process_toggle `, e); + console.log(`(error) handle_tradepr_qty_amt_toggle `, e); } }; - const handle_tradeproduct_location_sel_map_select = - async (): Promise<void> => { - try { - const geolc = await geol.current(); - if (`err` in geolc) return; //@todo - tradeproduct_location_select_vis = true; - tradeproduct_location_select_point = { - lat: geolc.lat, - lng: geolc.lng, - }; - } catch (e) { - console.log( - `(error) handle_tradeproduct_location_sel_map_select `, - e, + const handle_tradepr_lgc_sel_map = async (): Promise<void> => { + try { + const geolc = await geol.current(); + if (`err` in geolc) { + await dialog.alert( + `${$t(`icu.failure_*`, { value: `${$t(`icu.reading_*`, { value: `${$t(`common.geocode`)}`.toLowerCase() })}` })}`, ); + return; } - }; + tradepr_lgc_map_vis = true; + tradepr_lgc_map_point = { + lat: geolc.lat, + lng: geolc.lng, + }; + } catch (e) { + console.log(`(error) handle_tradepr_lgc_sel_map `, e); + } + }; - const handle_back = async (): Promise<void> => { + const handle_back = async (num?: number): Promise<void> => { try { + switch (view) { + case `c_1`: + { + switch ($carousel_index) { + default: + { + await carousel_dec(view); + } + break; + } + } + break; + } + if (num) { + carousel_num.set(Math.max(num, 0)); + carousel_index.set(Math.max($carousel_index - (num - 1), 0)); + } } catch (e) { console.log(`(error) handle_back `, e); } @@ -199,19 +355,49 @@ const handle_continue = async (): Promise<void> => { try { switch (view) { - case `fl_1`: + case `c_1`: { switch ($carousel_index) { case 0: { - console.log( - JSON.stringify( - tradeproduct_photo_paths, - null, - 4, - ), - `tradeproduct_photo_paths`, - ); + const validate_fields = + await tradeproduct_validate_fields({ + kv_pref: fmt_id(), + fields: [`title`, `key`, `process`], + }); + if (`err` in validate_fields) { + await dialog.alert( + `${$t(`icu.enter_the_*`, { value: `${$t(`models.trade_product.fields.${validate_fields.err}.label`)}`.toLowerCase() })}`, + ); + return; + } + if (!tradepr_photo_paths.length) { + await dialog.alert( + `${$t(`icu.a_*_is_required`, { value: `${$t(`common.photo`)}`.toLowerCase() })}`, + ); + return; + } + await carousel_inc(view); + } + break; + case 1: + { + const validate_fields = + await tradeproduct_validate_fields({ + kv_pref: fmt_id(), + fields: [ + `price_amt`, + `key`, + `process`, + ], + }); + if (`err` in validate_fields) { + await dialog.alert( + `${$t(`icu.enter_the_*`, { value: `${$t(`models.trade_product.fields.${validate_fields.err}.label`)}`.toLowerCase() })}`, + ); + return; + } + await carousel_inc(view); } break; } @@ -225,6 +411,102 @@ const submit = async (): Promise<void> => { try { + if (!tradepr_photo_paths.length) { + const confirm = await dialog.confirm({ + message: `${$t(`icu.a_*_is_required`, { value: `${$t(`common.photo`)}`.toLowerCase() })}`, + ok_label: `${$t(`icu.add_*`, { value: `${$t(`common.photo`)}` })}`, + }); + if (confirm) { + await el_focus( + fmt_id(`image-upload-multi`), + async () => await handle_back(2), + ); + } + return; + } + let location_gcs_id = ``; + const location_gcs_get_i = await db.location_gcs_get_one({ + id: $tradepr_lgc_sel, + }); + if (`result` in location_gcs_get_i) { + location_gcs_id = location_gcs_get_i.result.id; + } else { + if (tradepr_lgc_map_point && tradepr_lgc_map_geoc) { + const location_gcs_add_geocode = + await model_location_gcs_add_geocode({ + geo_code: tradepr_lgc_map_geoc, + point: tradepr_lgc_map_point, + }); + if ( + `err` in location_gcs_add_geocode || + `err_s` in location_gcs_add_geocode + ) { + await dialog.alert( + `err` in location_gcs_add_geocode + ? `${$t(`icu.the_*_is_incomplete`, { value: `${$t(`models.location_gcs.fields.${location_gcs_add_geocode.err}.label`)}`.toLowerCase() })}` + : `${$t(`${location_gcs_add_geocode.err_s[0]}`)}`, + ); + return; + } + location_gcs_id = location_gcs_add_geocode.id; + } + } + const location_gcs_get_c = await db.location_gcs_get_one({ + id: location_gcs_id, + }); + if (`err` in location_gcs_get_c) { + const confirm = await dialog.confirm({ + message: `${$t(`icu.a_*_is_required`, { value: `${$t(`common.location`)}`.toLowerCase() })}`, + ok_label: `${$t(`icu.add_*`, { value: `${$t(`common.location`)}` })}`, + }); + if (confirm) { + await el_focus( + fmt_id(`tradepr_location_wrap`), + async () => await handle_back(2), + ); + } + return; + } + const trade_product_fields = await trade_product_fields_validate({ + field_defaults: [ + [`price_qty_amt`, num_str(1)], + [`profile`, `natural`], + [`qty_avail`, num_str($tradepr_qty_avail)], + [`year`, year_curr()], + ], + }); + if (`err` in trade_product_fields) { + await dialog.alert( + `${$t(`icu.the_*_is_incomplete`, { value: `${$t(`models.trade_product.fields.${trade_product_fields.err}.label`)}`.toLowerCase() })}`, + ); + return; + } + const trade_product_add = + await db.trade_product_add(trade_product_fields); + if (`err` in trade_product_add || `err_s` in trade_product_add) { + await dialog.alert( + `err` in trade_product_add + ? `${$t(`icu.the_*_is_incomplete`, { value: `${$t(`models.trade_product.fields.${trade_product_add.err}.label`)}`.toLowerCase() })}` + : `${$t(`${trade_product_add.err_s[0]}`)}`, + ); + return; + } + const trade_product_location_set = + await db.trade_product_location_set({ + trade_product: { + id: trade_product_add.id, + }, + location_gcs: { + id: location_gcs_get_c.result.id, + }, + }); + if (`pass` in trade_product_location_set) { + route(`/models/nostr-relay/view`); + return; + } + await dialog.alert( + `${$t(`common.failure_to_process_the_request`)}`, + ); } catch (e) { console.log(`(error) submit `, e); } @@ -233,33 +515,68 @@ <LayoutView> <div - data-view={`fl_1`} + data-view={`c_1`} class={`flex flex-col h-full w-full justify-start items-center`} > <div - data-carousel-container={`fl_1`} + data-carousel-container={`c_1`} class={`carousel-container flex h-full w-full`} > <div - data-carousel-item={`fl_1`} + data-carousel-item={`c_1`} class={`carousel-item flex flex-col w-full justify-start items-center`} > <LayoutTrellis> <ImageUploadMulti - bind:photo_paths={tradeproduct_photo_paths} + bind:photo_paths={tradepr_photo_paths} + basis={{ + id: fmt_id(`image-upload-multi`), + }} /> <LayoutTrellisLine basis={{ label: { + value: `${$t(`icu.listing_*`, { value: `${$t(`common.title`)}` })}`, + }, + }} + > + <EntryLine + basis={{ + wrap: { + id: fmt_id(`title_wrap`), + layer: 1, + }, + el: { + id: fmt_id(`title`), + layer: 1, + sync: true, + classes: `fade-in-long`, + placeholder: `${$t(`icu.enter_*`, { value: `${$t(`common.title`)}`.toLowerCase() })}`, + field: { + charset: + trade_product_form_fields.title + .charset, + validate: + trade_product_form_fields.title + .validation, + validate_keypress: true, + }, + }, + }} + /> + </LayoutTrellisLine> + <LayoutTrellisLine + basis={{ + label: { value: `${$t(`common.product`)}`, }, - notify: tradeproduct_key_sel_toggle + notify: tradepr_key_sel_toggle ? { label: { value: `${$t(`common.close`)}`, }, callback: async () => { - await handle_tradeproduct_key_toggle( + await handle_tradepr_key_toggle( false, ); }, @@ -267,9 +584,9 @@ : undefined, }} > - {#if !tradeproduct_key_sel_toggle} + {#if !tradepr_key_sel_toggle} <EntrySelect - bind:value={tradeproduct_key_sel} + bind:value={tradepr_key_sel} basis={{ wrap: { id: fmt_id(`key_wrap`), @@ -289,7 +606,7 @@ }, ...trade_keys.map((i) => ({ value: i, - label: `${$t(`trade.product.key.${i}.name`, { default: i })}`, + label: `${$t(`trade.product.key.${i}.name`)}`, })), { value: ``, @@ -305,13 +622,13 @@ `entry-layer-1-highlight`, ); if (!opt.value) { - await handle_tradeproduct_key_toggle( + await handle_tradepr_key_toggle( true, ); - tradeproduct_key_sel = ``; - tradeproduct_process_sel = ``; + tradepr_key_sel = ``; + tradepr_process_sel = ``; } else { - tradeproduct_process_sel = ``; + tradepr_process_sel = ``; } }, }, @@ -347,47 +664,15 @@ <LayoutTrellisLine basis={{ label: { - value: `${$t(`common.lot`)}`, - }, - }} - > - <EntryLine - basis={{ - wrap: { - id: fmt_id(`lot_wrap`), - layer: 1, - }, - el: { - id: fmt_id(`lot`), - layer: 1, - sync: true, - classes: `fade-in-long`, - placeholder: `${$t(`icu.enter_the_*`, { value: `${$t(`icu.*_name`, { value: `${$t(`common.lot`)}` })}`.toLowerCase() })}`, - field: { - charset: - trade_product_form_fields.lot - .charset, - validate: - trade_product_form_fields.lot - .validation, - validate_keypress: true, - }, - }, - }} - /> - </LayoutTrellisLine> - <LayoutTrellisLine - basis={{ - label: { value: `${$t(`common.process`)}`, }, - notify: tradeproduct_process_sel_toggle + notify: tradepr_process_sel_toggle ? { label: { value: `${$t(`common.close`)}`, }, callback: async () => { - await handle_tradeproduct_process_toggle( + await handle_tradepr_process_toggle( false, ); }, @@ -395,9 +680,9 @@ : undefined, }} > - {#if !tradeproduct_process_sel_toggle} + {#if !tradepr_process_sel_toggle} <EntrySelect - bind:value={tradeproduct_process_sel} + bind:value={tradepr_process_sel} basis={{ wrap: { id: fmt_id(`process_wrap`), @@ -415,10 +700,10 @@ label: `${$t(`icu.choose_*`, { value: `${$t(`common.process`)}`.toLowerCase() })}`, disabled: true, }, - ...tradeproduct_process_list.map( + ...tradepr_process_list.map( (i) => ({ value: i, - label: `${$t(`trade.product.key.${tradeproduct_key_parsed}.process.${i}`)}`, + label: `${$t(`trade.product.key.${tradepr_key_parsed}.process.${i}`)}`, }), ), { @@ -435,7 +720,7 @@ `entry-layer-1-highlight`, ); if (!value) { - await handle_tradeproduct_process_toggle( + await handle_tradepr_process_toggle( true, ); } @@ -478,45 +763,57 @@ }} > <EntrySelect - bind:value={tradeproduct_location_sel} + bind:value={$tradepr_lgc_sel} basis={{ wrap: { - id: fmt_id(`tradeproduct_location_wrap`), + id: fmt_id(`tradepr_location_wrap`), layer: 1, }, el: { - id: fmt_id(`tradeproduct_location`), + id: fmt_id(`tradepr_location`), sync: true, layer: 1, options: [ { - entries: - tradeproduct_location_select_geoc - ? [ - { - value: `map-select`, - label: `${tradeproduct_location_select_geoc.name}, ${tradeproduct_location_select_geoc.admin1_name}, ${tradeproduct_location_select_geoc.country_id}`, - }, - { - value: `map-select`, - label: `Choose new location`, - }, - ] - : [ - { - value: ``, - label: `${$t(`icu.choose_*`, { value: `${$t(`common.location`)}`.toLowerCase() })}`, - disabled: true, - }, - { - value: `map-select`, - label: `Choose on map`, - }, - { - value: ``, - label: `Clear`, - }, - ], + entries: tradepr_lgc_map_geoc + ? [ + { + value: ``, + label: `${$t(`icu.choose_*`, { value: `${$t(`common.location`)}`.toLowerCase() })}`, + disabled: true, + }, + { + value: `*map`, + label: `${$t(`icu.choose_on_*`, { value: `${$t(`common.map`)}`.toLowerCase() })}`, + }, + { + value: `*geoc`, + label: `${tradepr_lgc_map_geoc.name}, ${tradepr_lgc_map_geoc.admin1_name}, ${tradepr_lgc_map_geoc.country_id}`, + }, + ...tradepr_lgc_list.map( + (i) => ({ + value: i.id, + label: `${i.gc_name}, ${i.gc_admin1_name}, ${i.gc_country_id}`, + }), + ), + ] + : [ + { + value: ``, + label: `${$t(`icu.choose_*`, { value: `${$t(`common.location`)}`.toLowerCase() })}`, + disabled: true, + }, + { + value: `*map`, + label: `${$t(`icu.choose_on_*`, { value: `${$t(`common.map`)}`.toLowerCase() })}`, + }, + ...tradepr_lgc_list.map( + (i) => ({ + value: i.id, + label: `${i.gc_name}, ${i.gc_admin1_name}, ${i.gc_country_id}`, + }), + ), + ], }, ], callback: async ({ value }) => { @@ -525,10 +822,8 @@ )?.classList.remove( `entry-layer-1-highlight`, ); - if (!value) { - //@todo - } else if (value === `map-select`) { - await handle_tradeproduct_location_sel_map_select(); + if (value === `*map`) { + await handle_tradepr_lgc_sel_map(); } }, }, @@ -537,68 +832,714 @@ </LayoutTrellisLine> </LayoutTrellis> </div> + <div + data-carousel-item={`c_1`} + class={`carousel-item flex flex-col w-full justify-start items-center`} + > + <LayoutTrellis> + <div + class={`flex flex-col w-full justify-center items-center`} + > + <div + class={`flex flex-col h-[11rem] w-${$app_layout} justify-start items-start bg-layer-1-surface rounded-[2rem] overflow-hidden`} + > + <div + class={`flex flex-row h-[2.5rem] w-full justify-center items-center`} + > + <p + class={`font-sans font-[400] text-[1.05rem] text-layer-1-glyph_d`} + > + {`${$t(`common.listing`)}`} + </p> + </div> + <div + class={`flex flex-col h-[8.5rem] w-full px-4 justify-start items-start`} + > + <div + class={`flex flex-col h-full w-full gap-[5px] justify-center items-center border-t-line border-layer-0-glyph_d`} + > + <TradeFieldDisplayKv + basis={{ + visible: $carousel_index === 1, + label: `${$t(`common.title`)}`, + display: { + kv: `title`, + undef: `${$t(`icu.no_*`, { value: `${$t(`common.title`)}`.toLowerCase() })}`, + }, + handle_back: async () => { + await handle_back(1); + }, + }} + /> + <TradeFieldDisplayKv + basis={{ + visible: $carousel_index === 1, + label: `${$t(`common.product`)}`, + display: { + kv: `key`, + undef: `${$t(`icu.no_*`, { value: `${$t(`common.product`)}`.toLowerCase() })}`, + }, + handle_back: async () => { + await handle_back(1); + }, + }} + /> + <TradeFieldDisplayKv + basis={{ + visible: $carousel_index === 1, + label: `${$t(`common.process`)}`, + display: { + kv: `process`, + undef: `${$t(`icu.no_*`, { value: `${$t(`common.process`)}`.toLowerCase() })}`, + }, + handle_back: async () => { + await handle_back(1); + }, + }} + /> + <TradeFieldDisplayKv + basis={{ + visible: $carousel_index === 1, + kv_wrap: `tradepr_location_wrap`, + label: `${$t(`common.location`)}`, + display: { + value: tradepr_lgc_sel_geoc + ? `${tradepr_lgc_sel_geoc.name}, ${tradepr_lgc_sel_geoc.admin1_name}, ${tradepr_lgc_sel_geoc.country_id}` + : ``, + undef: `${$t(`icu.no_*`, { value: `${$t(`common.location`)}`.toLowerCase() })}`, + }, + handle_back: async () => { + await handle_back(1); + }, + }} + /> + </div> + </div> + </div> + </div> + <LayoutTrellisLine + basis={{ + label: { + value: `${$t(`common.lot`)}`, + }, + }} + > + <EntryLine + basis={{ + wrap: { + id: fmt_id(`lot_wrap`), + layer: 1, + }, + el: { + id: fmt_id(`lot`), + layer: 1, + sync: true, + placeholder: `${$t(`icu.enter_the_*`, { value: `${$t(`icu.*_name`, { value: `${$t(`common.lot`)}` })}`.toLowerCase() })}`, + field: { + charset: + trade_product_form_fields.lot + .charset, + validate: + trade_product_form_fields.lot + .validation, + validate_keypress: true, + }, + }, + }} + /> + </LayoutTrellisLine> + <LayoutTrellisLine + basis={{ + label: { + value: `${$t(`icu.*_price`, { value: `${$t(`common.product`)}` })} (${tradepr_price_curr_sel}/${`${$t(`measurement.mass.unit.${tradepr_price_qty_unit_sel}_ab`)}`})`, + }, + }} + > + <EntryWrap + basis={{ + id: fmt_id(`price_wrap`), + layer: 1, + }} + > + <div + class={`flex flex-row justify-start pr-1 items-center`} + > + <SelectElement + bind:value={tradepr_price_curr_sel} + basis={{ + id: fmt_id(`price_currency`), + layer: 1, + sync: true, + classes: `w-fit font-sans font-[400] text-[1.1rem] ${tradepr_price_amt_val ? `text-layer-1-glyph_d` : `text-layer-1-glyph_pl`} el-re`, + options: [ + { + entries: fiat_currencies.map( + (i) => ({ + value: `${i}`, + label: parse_currency_marker( + $locale, + i, + ), + }), + ), + }, + ], + }} + /> + </div> + <InputElement + bind:value={tradepr_price_amt_val} + basis={{ + id: fmt_id(`price_amt`), + layer: 1, + sync: true, + placeholder: `${$t(`icu.enter_the_*`, { value: `${$t(`common.price`)}`.toLowerCase() })}`, + field: { + charset: + trade_product_form_fields.price_amt + .charset, + validate: + trade_product_form_fields.price_amt + .validation, + validate_keypress: true, + }, + callback: async ({ value, pass }) => { + const lastchar = + value[value.length - 1]; + const period_count = + value.split(".").length - 1; + if ( + (pass && + lastchar !== `.` && + period_count < 2) || + value.length < 1 + ) { + el_id( + fmt_id(`price_wrap`), + )?.classList.remove( + `entry-layer-1-highlight`, + ); + } else { + el_id( + fmt_id(`price_wrap`), + )?.classList.add( + `entry-layer-1-highlight`, + ); + } + }, + callback_blur: async ({ el }) => { + if (!el.value) return; + el.value = fmt_price( + tradepr_price_curr_sel, + el.value, + ).slice(1); //@todo fmt handles 'en' only + }, + }} + /> + <div + class={`flex flex-row gap-2 justify-end items-center`} + > + <p + class={`font-sans font-[400] text-[1.05rem] text-layer-1-glyph_d lowercase`} + > + {num_str(1)} + </p> + <SelectElement + bind:value={tradepr_price_qty_unit_sel} + basis={{ + id: fmt_id(`price_qty_unit`), + sync: true, + layer: 1, + classes: `w-fit font-sans font-[400] text-[1.05rem]`, + show_arrows: `r`, + options: [ + { + entries: mass_units.map( + (i) => ({ + value: i, + label: `${$t(`measurement.mass.unit.${i}_ab`)}`.toLowerCase(), + }), + ), + }, + ], + }} + /> + </div> + </EntryWrap> + </LayoutTrellisLine> + <LayoutTrellisLine + basis={{ + label: { + value: `${$t(`icu.*_quantity`, { value: `${$t(`common.order`)}` })}`, + }, + notify: tradepr_qty_tup_sel_toggle + ? { + label: { + value: `${$t(`common.close`)}`, + }, + callback: async () => { + await handle_tradepr_qty_amt_toggle( + false, + ); + }, + } + : undefined, + }} + > + {#if !tradepr_qty_tup_sel_toggle} + <EntrySelect + bind:value={$tradepr_qty_tup_sel} + basis={{ + wrap: { + id: fmt_id(`qty_wrap`), + layer: 1, + }, + el: { + layer: 1, + options: [ + { + entries: [ + { + value: ``, + label: `${$t(`icu.choose_*`, { value: `${$t(`common.quantity`)}`.toLowerCase() })}`, + disabled: true, + }, + ...tradepr_key_quantities_list.map( + (i) => ({ + value: fmt_trade_quantity_tup( + i, + ), + label: `${i.mass} ${$t(`measurement.mass.unit.${i.mass_unit}_ab`)} ${i.label}`, + }), + ), + { + value: ``, + label: `${$t(`common.other`)}`, + }, + ], + }, + ], + callback: async ({ value }) => { + el_id( + fmt_id(`qty_wrap`), + )?.classList.remove( + `entry-layer-1-highlight`, + ); + if (value === ``) { + await handle_tradepr_qty_amt_toggle( + true, + ); + } + }, + }, + }} + /> + {:else} + <EntryWrap + basis={{ + id: fmt_id(`qty_wrap`), + layer: 1, + }} + > + <InputElement + basis={{ + id: fmt_id(`qty_amt`), + sync: true, + layer: 1, + placeholder: `${$t(`icu.enter_*_per_order`, { value: `${$t(`measurement.mass.unit.${tradepr_qty_unit_sel}_ab`)}`.toLowerCase() })}`, + field: { + charset: + trade_product_form_fields + .qty_amt.charset, + validate: + trade_product_form_fields + .qty_amt.validation, + validate_keypress: true, + }, + }} + /> + <div + class={`flex flex-row gap-2 justify-end items-center`} + > + <SelectElement + bind:value={tradepr_qty_unit_sel} + basis={{ + id: fmt_id(`qty_unit`), + sync: true, + layer: 1, + classes: `w-fit font-sans font-[400] text-[1.05rem] text-layer-1-glyph_d`, + show_arrows: `r`, + options: [ + { + entries: mass_units.map( + (i) => ({ + value: i, + label: `${$t(`measurement.mass.unit.${i}_ab`)}`, + }), + ), + }, + ], + }} + /> + </div> + </EntryWrap> + {/if} + </LayoutTrellisLine> + <LayoutTrellisLine + basis={{ + label: { + value: `${$t(`common.description`)}`, + }, + }} + > + <EntryMultiline + basis={{ + wrap: { + id: fmt_id(`summary_wrap`), + }, + el: { + classes: `h-[7rem]`, + id: fmt_id(`summary`), + sync: true, + placeholder: `${$t(`icu.enter_the_*`, { value: `${$t(`icu.*_description`, { value: `${$t(`common.listing`)}` })}`.toLowerCase() })}`, + field: { + charset: + trade_product_form_fields.summary + .charset, + validate: + trade_product_form_fields.summary + .validation, + validate_keypress: true, + }, + }, + }} + /> + </LayoutTrellisLine> + </LayoutTrellis> + </div> + <div + data-carousel-item={`c_1`} + class={`carousel-item flex flex-col w-full justify-start items-center`} + > + <LayoutTrellis> + <div + class={`flex flex-col w-full justify-center items-center`} + > + <div + class={`flex flex-col h-auto w-${$app_layout} justify-start items-start bg-layer-1-surface rounded-[2rem] overflow-hidden`} + > + <div + class={`flex flex-row h-[3rem] w-full justify-center items-center`} + > + <p + class={`font-sans font-[400] text-[1.05rem] text-layer-1-glyph_d`} + > + {`${$t(`common.listing`)}`} + </p> + </div> + <div + class={`flex flex-col w-full px-4 justify-start items-center`} + > + <div + class={`flex flex-col h-auto w-full py-6 gap-[5px] justify-center items-start border-t-line border-layer-0-glyph_d`} + > + <TradeFieldDisplayKv + basis={{ + visible: $carousel_index === 2, + label: `${$t(`common.title`)}`, + display: { + kv: `title`, + undef: `${$t(`icu.no_*`, { value: `${$t(`common.title`)}`.toLowerCase() })}`, + }, + handle_back: async () => { + await handle_back(2); + }, + }} + /> + <TradeFieldDisplayKv + basis={{ + visible: $carousel_index === 2, + label: `${$t(`common.product`)}`, + display: { + kv: `key`, + undef: `${$t(`icu.no_*`, { value: `${$t(`common.product`)}`.toLowerCase() })}`, + }, + handle_back: async () => { + await handle_back(2); + }, + }} + /> + <TradeFieldDisplayKv + basis={{ + visible: $carousel_index === 2, + label: `${$t(`common.process`)}`, + display: { + kv: `process`, + undef: `${$t(`icu.no_*`, { value: `${$t(`common.process`)}`.toLowerCase() })}`, + }, + handle_back: async () => { + await handle_back(2); + }, + }} + /> + <TradeFieldDisplayKv + basis={{ + visible: $carousel_index === 2, + kv_wrap: `tradepr_location_wrap`, + label: `${$t(`common.location`)}`, + display: { + value: tradepr_lgc_sel_geoc + ? `${tradepr_lgc_sel_geoc.name}, ${tradepr_lgc_sel_geoc.admin1_name}, ${tradepr_lgc_sel_geoc.country_id}` + : ``, + undef: `${$t(`icu.no_*`, { value: `${$t(`common.location`)}`.toLowerCase() })}`, + }, + handle_back: async () => { + await handle_back(2); + }, + }} + /> + <TradeFieldDisplayKv + basis={{ + visible: $carousel_index === 2, + label: `${$t(`common.lot`)}`, + display: { + kv: `lot`, + undef: `${$t(`icu.no_*`, { value: `${$t(`common.lot`)}`.toLowerCase() })}`, + }, + handle_back: async () => { + await handle_back(1); + }, + }} + /> + <TradeFieldDisplayKv + basis={{ + visible: $carousel_index === 2, + label: `${$t(`common.description`)}`, + display: { + kv: `summary`, + undef: `${$t(`icu.no_*`, { value: `${$t(`common.description`)}`.toLowerCase() })}`, + }, + handle_back: async () => { + await handle_back(1); + }, + }} + /> + </div> + <div + class={`flex flex-col h-auto w-full py-6 gap-[5px] justify-center items-start border-t-line border-layer-0-glyph_d`} + > + <TradeFieldDisplayKv + basis={{ + visible: $carousel_index === 2, + label: `${$t(`common.price`)}`, + kv_wrap: `price_wrap`, + display: { + value: + tradepr_cprice_amt && + tradepr_price_qty_unit_sel + ? `${fmt_currency_price(tradepr_cprice_amt)} / ${`${$t(`measurement.mass.unit.${tradepr_price_qty_unit_sel}_ab`)}`.toLowerCase()}` + : ``, + undef: `${$t(`icu.no_*`, { value: `${$t(`common.price`)}`.toLowerCase() })}`, + nostyle: true, + }, + handle_back: async () => { + await handle_back(1); + }, + }} + /> + <TradeFieldDisplayKv + basis={{ + visible: $carousel_index === 2, + label: `${$t(`icu.*_quantity`, { value: `${$t(`common.order`)}` })}`, + display: { + value: tradepr_parsed_quantity + ? `${tradepr_parsed_quantity.mass} ${`${$t(`measurement.mass.unit.${tradepr_parsed_quantity.mass_unit}_ab`)}`.toLowerCase()} ${tradepr_parsed_quantity.label || `${$t(`common.bag`)}`}` + : ``, + undef: `${$t(`icu.no_*`, { value: `${$t(`icu.*_quantity`, { value: `${$t(`common.order`)}` })}` })}`, + nostyle: + !!tradepr_parsed_quantity, + }, + kv_wrap: `qty_wrap`, + handle_back: async () => { + await handle_back(1); + }, + }} + /> + <TradeFieldDisplayEl + basis={{ + visible: $carousel_index === 2, + label: `${$t(`icu.*_available`, { value: `${$t(`common.quantity`)}` })}${tradepr_parsed_quantity ? ` (${$tradepr_qty_avail})` : ``}`, + display: { + classes: tradepr_parsed_quantity + ? `` + : `pr-4`, + value: tradepr_parsed_quantity + ? `~` + : ``, + hide: !!tradepr_parsed_quantity, + undef: ascii.dash, + }, + }} + > + {#if tradepr_parsed_quantity} + <div + class={`flex flex-row gap-2 pl-2 pr-1 justify-center items-center`} + > + <button + class={`group flex flex-row justify-center items-center`} + on:click={async () => { + tradepr_qty_avail.set( + int_step( + $tradepr_qty_avail, + `-`, + 1, + ), + ); + }} + > + <Glyph + basis={{ + key: `arrow-down`, + dim: `xs`, + classes: `h-[1.3rem] w-[1.3rem] text-layer-1-glyph_d bg-layer-2-surface/60 rounded-full el-re`, + }} + /> + </button> + <button + class={`group flex flex-row justify-center items-center`} + on:click={async () => { + tradepr_qty_avail.set( + int_step( + $tradepr_qty_avail, + `+`, + ), + ); + }} + > + <Glyph + basis={{ + key: `arrow-up`, + dim: `xs`, + classes: `h-[1.3rem] w-[1.3rem] text-layer-1-glyph_d bg-layer-2-surface/60 rounded-full el-re`, + }} + /> + </button> + </div> + {/if} + </TradeFieldDisplayEl> + <TradeFieldDisplayEl + basis={{ + visible: $carousel_index === 2, + label: `${$t(`icu.*_total`, { value: `${$t(`common.quantity`)}` })}`, + display: { + classes: tradepr_parsed_quantity + ? `pr-2` + : `pr-4`, + value: tradepr_parsed_quantity + ? `${Number( + $tradepr_qty_avail * + tradepr_parsed_quantity.mass, + ).toFixed( + 2, + )} ${`${$t(`measurement.mass.unit.${tradepr_parsed_quantity.mass_unit}_ab`)}`.toLowerCase()}` + : ``, + undef: ascii.dash, + nostyle: true, + }, + }} + /> + </div> + <div + class={`flex flex-col h-auto w-full pb-6 gap-[5px] justify-center items-start`} + > + <TradeFieldDisplayEl + basis={{ + visible: $carousel_index === 2, + label: `${$t(`icu.*_total`, { value: `${$t(`common.order`)}` })}`, + display: { + classes: + tradepr_parsed_quantity && + tradepr_cprice_amt + ? `pr-2` + : `pr-4`, + value: tradepr_cprice_total + ? `${fmt_currency_price(tradepr_cprice_total)}` + : ``, + undef: ascii.dash, + }, + }} + /> + </div> + </div> + </div> + </div> + <button + class={`flex flex-row h-12 w-${$app_layout} justify-center items-center bg-layer-1-glyph-hl active:bg-layer-1-glyph-hl_a round-40 font-sans font-[600] text-[1.1rem] text-white capitalize el-re`} + on:click={async () => { + await submit(); + }} + > + {`${$t(`common.post`)}`} + </button> + </LayoutTrellis> + </div> </div> </div> </LayoutView> -<div - in:fade={{ delay: 0, duration: 50 }} - out:fade={{ delay: 50, duration: 200 }} - class={`flex flex-col w-full justify-start items-center fade-in`} -> - <Nav - basis={{ - prev: { - label: `${$t(`common.back`)}`, - route: `/models/trade-product`, - prevent_route: - view === `fl_1` && $carousel_index === 0 + +<Nav + basis={{ + prev: { + label: `${$t(`common.back`)}`, + route: `/models/trade-product`, + prevent_route: + view === `c_1` && $carousel_index === 0 + ? undefined + : { + callback: async () => { + await handle_back(); + }, + }, + callback: async () => { + await tradeproduct_init_kv(fmt_id()); + }, + }, + title: { + label: { + value: `${$t(`icu.new_*`, { value: `${$t(`common.product`)}` })}`, + }, + callback: async () => {}, + }, + option: { + loading: load_submit, + label: { + value: + $carousel_num > 1 + ? `${$t(`common.back`)}` + : page_param.carousel[view].get($carousel_index) + ?.label_next || ``, + glyph: + $carousel_index === $carousel_index_max ? undefined : { - callback: async () => { - await handle_back(); - }, + key: `caret-right`, + classes: `text-layer-1-glyph-hl`, }, - callback: async () => { - await tradeproduct_init_kv(fmt_id()); - }, - }, - title: { - label: { - value: `${$t(`icu.new_*`, { value: `${$t(`common.product`)}` })}`, - }, - callback: async () => {}, }, - option: { - loading: load_submit, - label: { - value: - $carousel_num > 1 - ? `${$t(`common.return`)}` - : page_param.carousel[view].get($carousel_index) - ?.label_next || ``, - glyph: - $carousel_index > 0 - ? { - key: `caret-right`, - classes: `text-layer-1-glyph-hl`, - } - : undefined, - }, - callback: async () => { - if ($carousel_index === $carousel_index_max) await submit(); - else await handle_continue(); - }, + callback: async () => { + await handle_continue(); }, - }} - /> -</div> + }, + }} +/> <MapPointSelectEnvelope - bind:map_point_select={tradeproduct_location_select_point} - bind:map_point_select_geoc={tradeproduct_location_select_geoc} + bind:map_point_select={tradepr_lgc_map_point} + bind:map_point_select_geoc={tradepr_lgc_map_geoc} basis={{ - visible: tradeproduct_location_select_vis, + visible: tradepr_lgc_map_vis, close: async () => { - tradeproduct_location_select_vis = false; + tradepr_lgc_sel.set(`*geoc`); + tradepr_lgc_map_vis = false; }, }} /> diff --git a/src/routes/(app)/test/+page.svelte b/src/routes/(app)/test/+page.svelte @@ -1,7 +1,61 @@ <script lang="ts"> - import { LayoutView } from "@radroots/svelte-lib"; + import { db } from "$lib/client"; + import type { LocationGcs } from "@radroots/models"; + import { LayoutView, Nav } from "@radroots/svelte-lib"; + import { onMount } from "svelte"; + + let list1: LocationGcs[] = []; + + onMount(async () => { + try { + const res1 = await db.location_gcs_get({ list: [`all`] }); + if (!(`err` in res1)) list1 = res1.results; + } catch (e) { + } finally { + } + }); </script> <LayoutView> - <div class={`flex flex-col w-full justify-center items-center`}></div> + <div class={`flex flex-col w-full justify-center items-center`}> + <p class={`font-sans font-[400] text-layer-0-glyph`}> + {`Models`} + </p> + <div class={`flex flex-col w-full px-4 justify-center items-center`}> + {#each list1 as li} + <div class={`flex flex-col justify-start items-center`}> + <p + class={`font-sans font-[400] text-layer-0-glyph break-all`} + > + {JSON.stringify(li, null, 4)} + </p> + <div + class={`flex flex-row w-full justify-center items-center`} + > + <button + class={`flex flex-row justify-center items-center`} + on:click={async () => { + await db.location_gcs_delete({ id: li.id }); + }} + > + {`del`} + </button> + </div> + </div> + {/each} + </div> + </div> </LayoutView> +<Nav + basis={{ + prev: { + label: `Home`, + route: `/`, + }, + title: { + label: { + value: `Test`, + }, + }, + }} +/> diff --git a/src/routes/(cfg)/cfg/init/+page.svelte b/src/routes/(cfg)/cfg/init/+page.svelte @@ -511,7 +511,7 @@ return { tok: res.data.tok }; } else if (res.data && `message` in res.data) return err_msg( - `${$t(`radroots-org.error.${res.data.message}`, { default: `${$t(`error.client.request_failure`)}` })}`, + `${$t(`radroots-org.error.${res.data.message}`)}`, ); return err_msg(`${$t(`error.client.request_failure`)}`); } catch (e) { diff --git a/src/routes/+error.svelte b/src/routes/+error.svelte @@ -14,7 +14,7 @@ }} /> <p class={`font-sans font-[400] text-layer-0-glyph`}> - {`${$t(`error.client.page.status.${$page.status}`, { default: `${$t(`error.client.unhandled`)}` })}`} + {`${$t(`error.client.page.status.${$page.status}`)}`} </p> </div> </div> diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte @@ -103,4 +103,4 @@ <Controls /> <CssStatic /> <CssStyles /> -<div class="hidden h-entry_guide h-entry_line" /> +<div class="hidden h-entry_guide h-entry_line h-[calc(100vh-12%)]" />