commit 5934eba13f9351afa291a9909f37d3cafbe6627b
parent 6e709b53201eac0c0c191a514417094f791ead7b
Author: triesap <137732411+triesap@users.noreply.github.com>
Date: Mon, 28 Oct 2024 03:28:38 +0000
Edit `models/trade-product/add` rewrite prior page adding writable stores, photo upload feature, simplified views, page param, handler functions. Add image upload display and image upload row components. Add validate fields util for `trade_product`. Add global.d.ts. Add/edit styles.
Diffstat:
9 files changed, 852 insertions(+), 1258 deletions(-)
diff --git a/crates/tauri/capabilities/default.json b/crates/tauri/capabilities/default.json
@@ -8,6 +8,7 @@
"permissions": [
"core:default",
"dialog:default",
+ "fs:default",
"geolocation:allow-check-permissions",
"geolocation:allow-get-current-position",
"geolocation:allow-request-permissions",
diff --git a/src/app.d.ts b/src/app.d.ts
@@ -1,5 +1,6 @@
declare global {
namespace App { }
+
declare class Keyva {
/**
* An IDBKeyRange that has no upper or lower bounding.
@@ -135,4 +136,3 @@ declare global {
}
export { };
-
diff --git a/src/global.d.ts b/src/global.d.ts
@@ -0,0 +1,6 @@
+declare module 'jshashes' {
+ export class SHA256 {
+ b64(input: string): string;
+ b64_hmac(key: string, input: string): string;
+ }
+}
diff --git a/src/lib/components/image_upload_display.svelte b/src/lib/components/image_upload_display.svelte
@@ -0,0 +1,68 @@
+<script lang="ts">
+ import { fs } from "$lib/client";
+ import {
+ Glyph,
+ ImageBlob,
+ type CallbackPromise,
+ } from "@radroots/svelte-lib";
+
+ export let basis: {
+ loading: boolean;
+ list: {
+ file_path: string;
+ }[];
+ callback_add: CallbackPromise;
+ };
+</script>
+
+<div
+ class={`flex flex-row h-[12rem] w-full pl-12 pr-4 gap-4 justify-start items-center`}
+>
+ <div class={`flex flex-col h-[11rem] gap-1 justify-center items-center`}>
+ <div
+ class={`relative flex flex-col h-36 w-36 justify-center items-center rounded-full border-edge border-layer-0-glyph ${basis.list.length === 0 ? `group-active:border-layer-0-glyph/60 ` : ``} overflow-hidden delay-100 duration-300 ease-in-out transition-all`}
+ >
+ {#if basis.list[0]?.file_path}
+ {#await fs.read_bin(basis.list[0].file_path) then file_data}
+ <ImageBlob
+ basis={{
+ data: file_data,
+ }}
+ />
+ {/await}
+ {/if}
+ <button
+ class={`z-10 group absolute bottom-0 flex flex-row h-8 w-full justify-center items-start bg-layer-2-surface active:bg-layer-1-surface`}
+ on:click={async () => {}}
+ >
+ <p
+ class={`font-circ font-[500] text-[0.8rem] tracking-tight text-layer-0-glyph group-active:text-layer-0-glyph/60 el-re`}
+ >
+ {`Primary photo`}
+ </p>
+ </button>
+ </div>
+ </div>
+ <div
+ class={`grid grid-cols-12 flex flex-row w-full gap-y-2 justify-start items-center`}
+ >
+ {#each Array(6).fill(0) as li}
+ <div
+ class={`col-span-4 flex flex-row pr-2 justify-start items-center`}
+ >
+ <button
+ class={`group flex flex-row h-[2.8rem] w-[2.8rem] justify-center items-center rounded-full border-line border-layer-0-glyph/90 active:border-layer-0-glyph/60`}
+ on:click={async () => {}}
+ >
+ <Glyph
+ basis={{
+ classes: `text-layer-0-glyph text-layer-0-glyph/80 group-active:text-layer-0-glyph/60 el-re`,
+ dim: `sm`,
+ key: `image-square`,
+ }}
+ />
+ </button>
+ </div>
+ {/each}
+ </div>
+</div>
diff --git a/src/lib/components/image_upload_row.svelte b/src/lib/components/image_upload_row.svelte
@@ -0,0 +1,109 @@
+<script lang="ts">
+ import { fs } from "$lib/client";
+ import {
+ Glyph,
+ ImageBlob,
+ Loading,
+ t,
+ type CallbackPromise,
+ } from "@radroots/svelte-lib";
+ import { fade } from "svelte/transition";
+
+ export let basis: {
+ loading: boolean;
+ list: {
+ file_path: string;
+ }[];
+ callback_add: CallbackPromise;
+ };
+</script>
+
+<div
+ class={`flex flex-row w-[100vw] ${basis.list.length > 1 ? `justify-start` : `justify-center`} items-center overflow-x-auto scroll-hide`}
+>
+ <div
+ class={`flex flex-row ${basis.list.length > 1 ? `px-24` : ``} space-x-4 delay-[200ms] duration-[500ms] ease-in-out transition-all`}
+ >
+ <button
+ in:fade={{ duration: 200 }}
+ out:fade={{ delay: 0, duration: 200 }}
+ on:click={async () => {
+ if (basis.list.length === 0) await basis.callback_add();
+ }}
+ class={`group flex flex-col gap-2 justify-start items-center`}
+ >
+ <div
+ class={`flex flex-row ${basis.list.length ? `h-52 w-52` : `h-36 w-36`} justify-center items-center rounded-full border-edge border-layer-0-glyph ${basis.list.length === 0 ? `group-active:border-layer-0-glyph/60 ` : ``} overflow-hidden delay-100 duration-300 ease-in-out transition-all`}
+ >
+ {#if basis.list.length}
+ {#await fs.read_bin(basis.list[0].file_path) then file_data}
+ <ImageBlob
+ basis={{
+ data: file_data,
+ }}
+ />
+ {/await}
+ {:else if basis.loading}
+ <div
+ in:fade={{ duration: 200 }}
+ out:fade={{
+ delay: 0,
+ duration: 50,
+ }}
+ class={`flex flex-row justify-start items-center`}
+ >
+ <Loading />
+ </div>
+ {:else}
+ <div
+ in:fade={{ duration: 200 }}
+ out:fade={{
+ delay: 0,
+ duration: 50,
+ }}
+ class={`flex flex-row justify-start items-center`}
+ >
+ <Glyph
+ basis={{
+ classes: `text-layer-0-glyph group-active:text-layer-0-glyph/60 el-re`,
+ dim: `lg`,
+ weight: `bold`,
+ key: `download-simple`,
+ }}
+ />
+ </div>
+ {/if}
+ </div>
+ <div class={`flex flex-row justify-start items-center`}>
+ <button
+ class={`flex flex-row justify-center items-center`}
+ on:click={async () => {
+ await basis.callback_add();
+ }}
+ >
+ <p
+ class={`font-sans font-[500] text-[1.1rem] tracking-tight text-layer-0-glyph group-active:text-layer-0-glyph/60 el-re`}
+ >
+ {`${$t(`icu.add_*`, { value: `${$t(`common.photo`)}`.toLowerCase() })}`}
+ </p>
+ </button>
+ </div>
+ </button>
+ {#if basis.list.length > 1}
+ {#each basis.list.slice(1) as li}
+ <button
+ class={`flex flex-row h-52 w-52 justify-center items-center rounded-full border-edge border-layer-0-glyph group-active:border-layer-0-glyph/60 overflow-hidden delay-100 duration-300 ease-in-out transition-all fade-in`}
+ on:click={async () => {}}
+ >
+ {#await fs.read_bin(li.file_path) then file_data}
+ <ImageBlob
+ basis={{
+ data: file_data,
+ }}
+ />
+ {/await}
+ </button>
+ {/each}
+ {/if}
+ </div>
+</div>
diff --git a/src/lib/utils/kv.ts b/src/lib/utils/kv.ts
@@ -1,6 +1,6 @@
import { parse_trade_product_form_keys, trade_product_form_fields, trade_product_form_vals, type TradeProductFormFields } from "@radroots/models";
import { kv } from "@radroots/svelte-lib";
-import { err_msg, type ErrorMessage } from "@radroots/utils";
+import { err_msg, type ErrorMessage, type ResultPass } from "@radroots/utils";
export const kv_init_trade_product_fields = async (kv_pref: string): Promise<void> => {
try {
@@ -49,7 +49,27 @@ export const kv_validate_trade_product_fields = async (opts: {
}
return vals;
} catch (e) {
- console.log(`(error) trade_product_submit_preview `, e);
+ console.log(`(error) kv_validate_trade_product_fields `, e);
+ return err_msg(String(e))
+ }
+};
+
+export const validate_trade_product_fields = async (opts: {
+ kv_pref: string;
+ fields: string[];
+}): Promise<ResultPass | ErrorMessage<string>> => {
+ try {
+ for (const field of opts.fields) {
+ const field_k = parse_trade_product_form_keys(field);
+ if (!field_k) return err_msg(field);
+ const field_id = `${opts.kv_pref}-${field_k}`;
+ const field_val = await kv.get(field_id);
+ console.log(`${field_k}: '${field_val}'`)
+ if (!trade_product_form_fields[field_k].validation.test(field_val)) return err_msg(field_k);
+ }
+ return { pass: true };
+ } catch (e) {
+ console.log(`(error) validate_trade_product_fields `, e);
return err_msg(String(e))
}
};
\ No newline at end of file
diff --git a/src/routes/(app)/+page.svelte b/src/routes/(app)/+page.svelte
@@ -240,9 +240,7 @@
{
icon: `squares-four`,
label: `Menu`,
- callback: async () => {
- await route(`/settings`);
- },
+ callback: async () => {},
},
],
}}
diff --git a/src/routes/(app)/models/trade-product/add/+page.svelte b/src/routes/(app)/models/trade-product/add/+page.svelte
@@ -1,21 +1,13 @@
-<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<script lang="ts">
- import { db, dialog, geol } from "$lib/client";
- import MapChooseLocation from "$lib/components/map_choose_location.svelte";
- import { cfg } from "$lib/conf";
+ import { dialog } from "$lib/client";
+ import ImageUploadDisplay from "$lib/components/image_upload_display.svelte";
+ import ImageUploadRow from "$lib/components/image_upload_row.svelte";
import {
kv_init_trade_product_fields,
- kv_validate_trade_product_fields,
+ validate_trade_product_fields,
} from "$lib/utils/kv";
- import type { GeocoderReverseResult } from "@radroots/geocoder";
+ import { mass_units, trade_product_form_fields } from "@radroots/models";
import {
- mass_units,
- trade_product_form_fields,
- type LocationGcs,
- type TradeProductFormFields,
- } from "@radroots/models";
- import {
- ButtonGlyph,
carousel_dec,
carousel_inc,
carousel_index,
@@ -26,241 +18,270 @@
EntryMultiline,
EntrySelect,
EntryWrap,
- Fill,
- fmt_geol_latitude,
- fmt_geol_longitude,
fmt_id,
- Glyph,
InputElement,
- int_step,
kv,
LayoutTrellis,
LayoutTrellisLine,
LayoutView,
- locale,
Nav,
- SelectEl,
- sleep,
+ price_locale_fmt,
+ SelectElement,
t,
view_effect,
} from "@radroots/svelte-lib";
import {
fiat_currencies,
- fmt_trade_quantity_val,
- parse_currency_price,
+ fmt_trade_quantity_sel_val,
parse_trade_key,
- parse_trade_mass_tuple,
+ trade,
trade_keys,
- trade_quantities,
- type CurrencyPrice,
- type GeolocationCoordinatesPoint,
type TradeKey,
} from "@radroots/utils";
import { onMount } from "svelte";
-
- const trade_key_default: TradeKey = `coffee`;
+ import { writable } from "svelte/store";
+ import { fade } from "svelte/transition";
type CarouselParam = {
label_prev?: string;
label_next: string;
};
- const carousel_param = new Map<number, CarouselParam>([
- [
- 0,
- {
- label_next: `${$t(`icu.add_*`, { value: `${$t(`common.product`)}` })}`,
- },
- ],
- [
- 1,
- {
- label_next: `${$t(`icu.add_*`, { value: `${$t(`common.location`)}` })}`,
- },
- ],
- [
- 2,
- {
- label_next: `${$t(`icu.add_*`, { value: `${$t(`common.listing`)}` })}`,
- },
- ],
- [
- 3,
- {
- label_next: `${$t(`common.preview`)}`,
- },
- ],
- [
- 4,
- {
- label_next: `${$t(`common.publish`)}`,
- },
- ],
- ]);
+ const page_param: {
+ trade_product: {
+ key_default: TradeKey;
+ };
+ carousel: Map<number, CarouselParam>;
+ } = {
+ carousel: new Map<number, CarouselParam>([
+ [
+ 0,
+ {
+ label_next: `${$t(`common.add`)}`,
+ },
+ ],
+ [
+ 1,
+ {
+ label_next: `${$t(`icu.add_*`, { value: `${$t(`common.location`)}` })}`,
+ },
+ ],
+ [
+ 2,
+ {
+ label_next: `${$t(`icu.add_*`, { value: `${$t(`common.listing`)}` })}`,
+ },
+ ],
+ [
+ 3,
+ {
+ label_next: `${$t(`common.preview`)}`,
+ },
+ ],
+ [
+ 4,
+ {
+ label_next: `${$t(`common.publish`)}`,
+ },
+ ],
+ ]),
+ trade_product: {
+ key_default: `coffee`,
+ },
+ };
- type View = `load` | `form_1`;
- let view: View = `load`;
+ type View = `main` | `finish`;
+ let view: View = `main`;
$: {
view_effect<View>(view);
}
- onMount(async () => {
- try {
- await kv.set(fmt_id(`price_amt`), `2`);
- await handle_view(`load`);
- carousel_index.set(0);
- carousel_index_max.set(carousel_param.size - 1);
- sel_trade_product_price_currency = "eur";
- sel_trade_product_price_qty_unit = "kg";
- sel_trade_product_qty_unit = "kg";
- await fetch_models_models_location_gcs();
- } catch (e) {
- } finally {
- await handle_view(`form_1`);
- }
- });
-
- // let el_trellis_wrap_price: HTMLElement | null;
-
let loading_submit = false;
- let show_sel_trade_product_key_other = false;
- let sel_trade_product_key: string = trade_key_default;
- $: sel_trade_product_key_parsed = parse_trade_key(sel_trade_product_key);
- $: ls_trade_product_quantities = sel_trade_product_key_parsed
- ? trade_quantities[sel_trade_product_key_parsed]
- : trade_quantities[trade_key_default];
-
- let sel_location_gcs_id = ``;
- let ls_models_location_gcs: LocationGcs[] = [];
+ let photo_add_loading = false;
+ let photo_add_list: { file_path: string }[] = [];
- let map_choose_loc_loading = true;
- let map_choose_loc_geoc_point: GeolocationCoordinatesPoint =
- cfg.map.coords.default;
- let map_choose_loc_geoc_point_select: GeolocationCoordinatesPoint =
- cfg.map.coords.default;
- let map_choose_loc_geoc_point_select_geoc:
- | GeocoderReverseResult
- | undefined = undefined;
+ let tradeproduct_key_sel_toggle = false;
+ const tradeproduct_key_sel = writable<string>(``);
+ $: tradeproduct_key_parsed = parse_trade_key($tradeproduct_key_sel);
+ $: ls_trade_product_quantities = tradeproduct_key_parsed
+ ? trade.key[tradeproduct_key_parsed].quantity
+ : trade.default.quantity;
- let show_sel_trade_product_qty_tup_other = false;
- let sel_trade_product_qty_tup = ``;
+ const tradeproduct_price_curr_sel = writable<string>(``);
+ const tradeproduct_price_qty_unit_sel = writable<string>(``);
- let sel_trade_product_price_currency = ``;
- let sel_trade_product_price_qty_unit = ``;
+ const tradeproduct_qty_unit_tup_sel = writable<string>(``);
+ let tradeproduct_qty_unit_tup_sel_toggle = false;
- let sel_trade_product_qty_unit = ``;
+ const tradeproduct_process_sel = writable<string>(``);
+ let tradeproduct_process_sel_toggle = false;
+ $: ls_trade_product_processes = tradeproduct_key_parsed
+ ? trade.key[tradeproduct_key_parsed].process
+ : [];
- let preview_trade_product: TradeProductFormFields | undefined = undefined;
- let preview_trade_product_qty_avail = 0;
+ onMount(async () => {
+ try {
+ await kv_init();
+ await handle_view(`main`);
+ carousel_index.set(0);
+ carousel_index_max.set(page_param.carousel.size - 1);
+ tradeproduct_price_curr_sel.set(`eur`);
+ tradeproduct_price_qty_unit_sel.set(`kg`);
+ await setup_test();
+ } catch (e) {
+ } finally {
+ await handle_view(`main`);
+ }
+ });
- //let review_trade_product: TradeProductFormFields | undefined = undefined;
- //let review_location_gcs: LocationGcs | undefined = undefined;
+ tradeproduct_key_sel.subscribe(async (_tradeproduct_key_sel) => {
+ await kv.set(fmt_id(`key`), _tradeproduct_key_sel);
+ });
- $: num_trade_product_qty_amt = preview_trade_product
- ? Number(preview_trade_product.qty_amt)
- : 0;
+ $: if (tradeproduct_key_parsed) {
+ tradeproduct_qty_unit_tup_sel.set(
+ fmt_trade_quantity_sel_val(
+ trade.key[tradeproduct_key_parsed].quantity[0],
+ ),
+ );
+ tradeproduct_process_sel.set(
+ trade.key[tradeproduct_key_parsed].process[0],
+ );
+ }
- $: num_trade_product_price_amt = preview_trade_product
- ? Number(preview_trade_product.price_amt)
- : 0;
+ tradeproduct_price_curr_sel.subscribe(
+ async (_tradeproduct_price_curr_sel) => {
+ await kv.set(
+ fmt_id(`price_currency`),
+ _tradeproduct_price_curr_sel,
+ );
+ },
+ );
+
+ tradeproduct_price_qty_unit_sel.subscribe(
+ async (_tradeproduct_price_qty_unit_sel) => {
+ await kv.set(
+ fmt_id(`price_qty_unit`),
+ _tradeproduct_price_qty_unit_sel,
+ );
+ },
+ );
- $: num_trade_product_price_total =
- num_trade_product_price_amt *
- num_trade_product_qty_amt *
- preview_trade_product_qty_avail;
+ tradeproduct_qty_unit_tup_sel.subscribe(
+ async (_tradeproduct_qty_unit_tup_sel) => {
+ await kv.set(fmt_id(`qty_unit`), _tradeproduct_qty_unit_tup_sel);
+ },
+ );
- let preview_trade_product_price_currency: CurrencyPrice | undefined =
- undefined;
- $: preview_trade_product_price_currency =
- preview_trade_product && num_trade_product_price_amt > 0
- ? parse_currency_price(
- $locale,
- preview_trade_product.price_currency,
- num_trade_product_price_amt,
- )
- : undefined;
+ const setup_test = async (): Promise<void> => {
+ try {
+ tradeproduct_key_sel.set(page_param.trade_product.key_default);
+
+ await kv.set(
+ fmt_id(`summary`),
+ [`This is the first line`, `This is the another line`].join(
+ `.\n`,
+ ),
+ );
+ } catch (e) {
+ console.log(`(error) setup_test `, e);
+ }
+ };
- $: sel_trade_product_qty_tup = sel_trade_product_key_parsed
- ? fmt_trade_quantity_val(
- trade_quantities[sel_trade_product_key_parsed][0],
- )
- : fmt_trade_quantity_val(trade_quantities[trade_key_default][0]);
+ const kv_init = async (): Promise<void> => {
+ try {
+ const kv_pref = fmt_id();
+ const range = Keyva.prefix(kv_pref);
+ const kv_list = await kv.each({ range }, `keys`);
+ await Promise.all(kv_list.map((k) => kv.set(k, ``)));
+ } catch (e) {
+ console.log(`(error) kv_init `, e);
+ }
+ };
- $: if (ls_models_location_gcs.length && !sel_location_gcs_id) {
- sel_location_gcs_id = ls_models_location_gcs[0].id;
- }
+ const handle_view = async (new_view: View): Promise<void> => {
+ try {
+ view = new_view;
+ } catch (e) {
+ console.log(`(error) handle_view `, e);
+ }
+ };
- $: if (sel_location_gcs_id) {
- (async () => {
- try {
- await kv.set(fmt_id(`location_gcs_id`), sel_location_gcs_id);
- } catch (e) {}
- })();
- }
+ const toggle_tradeproduct_key = async (
+ visible_input: boolean,
+ ): Promise<void> => {
+ try {
+ tradeproduct_key_sel_toggle = visible_input;
+ if (visible_input) {
+ tradeproduct_key_sel.set(``);
+ } else {
+ //@todo tradeproduct_key_sel = trade_keys[0];
+ }
+ } catch (e) {
+ console.log(`(error) toggle_tradeproduct_key `, e);
+ }
+ };
- $: if (sel_trade_product_qty_tup) {
- (async () => {
- try {
- const mass_tup = parse_trade_mass_tuple(
- sel_trade_product_qty_tup,
- );
- if (mass_tup) {
- await kv.set(fmt_id(`qty_amt`), mass_tup[0].toString());
- await kv.set(fmt_id(`qty_unit`), mass_tup[1]);
- await kv.set(fmt_id(`qty_label`), mass_tup[2]);
- //@note
- await kv.set(fmt_id(`qty_avail`), `1`);
- }
- } catch (e) {}
- })();
- }
+ const toggle_tradeproduct_qty_amt = async (
+ visible_input: boolean,
+ ): Promise<void> => {
+ try {
+ tradeproduct_qty_unit_tup_sel_toggle = visible_input;
+ if (visible_input) {
+ tradeproduct_qty_unit_tup_sel.set(mass_units[0]);
+ } else {
+ $tradeproduct_qty_unit_tup_sel = tradeproduct_key_parsed
+ ? fmt_trade_quantity_sel_val(
+ trade.key[tradeproduct_key_parsed].quantity[0],
+ )
+ : ``;
+ }
+ } catch (e) {
+ console.log(`(error) toggle_tradeproduct_qty_amt `, e);
+ }
+ };
- $: if (sel_trade_product_price_currency) {
- (async () => {
- try {
- await kv.set(
- fmt_id(`price_currency`),
- sel_trade_product_price_currency,
+ const toggle_tradeproduct_process = async (
+ visible_input: boolean,
+ ): Promise<void> => {
+ try {
+ tradeproduct_process_sel_toggle = visible_input;
+ if (visible_input) {
+ tradeproduct_process_sel.set(``);
+ } else {
+ tradeproduct_process_sel.set(
+ ls_trade_product_processes.length
+ ? ls_trade_product_processes[0]
+ : ``,
);
- } catch (e) {}
- })();
- }
-
- carousel_index.subscribe(async (_carousel_index) => {
- switch (view) {
- case `form_1`: {
- switch (_carousel_index) {
- case 1:
- {
- await handle_render_map_initial();
- }
- break;
- case 2:
- {
- const kv_qty_avail = await kv.get(
- fmt_id(`qty_avail`),
- );
- if (isNaN(kv_qty_avail))
- preview_trade_product_qty_avail = 1;
- else
- preview_trade_product_qty_avail =
- Number(kv_qty_avail);
- }
- break;
- }
}
+ } catch (e) {
+ console.log(`(error) toggle_tradeproduct_process `, e);
}
- });
+ };
- const handle_view = async (new_view: View): Promise<void> => {
+ const handle_photo_add = async (): Promise<void> => {
try {
- view = new_view;
+ photo_add_loading = true;
+ const photo_paths = await dialog.open_photos();
+ if (!photo_paths) {
+ return; //@todo
+ }
+ const file_path = photo_paths.results[0];
+ photo_add_list = [
+ ...photo_add_list,
+ {
+ file_path,
+ },
+ ];
} catch (e) {
- console.log(`(error) handle_view `, e);
+ console.log(`(error) handle_photo_add `, e);
+ } finally {
+ photo_add_loading = false;
}
};
- const handle_back = async (num?: number): Promise<void> => {
+ const handle_back = async (carousel_offset?: number): Promise<void> => {
try {
switch ($carousel_index) {
default:
@@ -269,397 +290,444 @@
}
break;
}
- if (num) {
- carousel_num.set(num);
- carousel_index.set($carousel_index - (num - 1));
+ if (carousel_offset) {
+ carousel_num.set(carousel_offset);
+ carousel_index.set($carousel_index - (carousel_offset - 1));
}
} catch (e) {
console.log(`(error) handle_back `, e);
}
};
- const handle_continue = async (num?: number): Promise<void> => {
+ const handle_continue = async (): Promise<void> => {
try {
switch ($carousel_index) {
case 0:
{
- const vals_1 = await kv_validate_trade_product_fields({
- kv_pref: fmt_id(),
- no_validation: [
- `year`,
- `price_qty_amt`,
- `qty_avail`,
- `summary`,
- `title`,
- ],
- });
- if (`err` in vals_1) {
+ const validate_fields =
+ await validate_trade_product_fields({
+ kv_pref: fmt_id(),
+ fields: [`key`, `summary`],
+ });
+ if (`err` in validate_fields) {
await dialog.alert(
- `${$t(`trade.product.fields.${vals_1.err}.err_invalid`, { default: `${$t(`icu.invalid_*`, { value: vals_1.err })}` })}`,
+ `${$t(`icu.enter_a_*`, { value: `${$t(`model.trade_product.${validate_fields.err}`)}`.toLowerCase() })}`,
);
return;
}
- if (!vals_1.year)
- await kv.set(
- fmt_id(`year`),
- new Date().getFullYear().toString(),
- );
- if (!vals_1.price_qty_amt)
- await kv.set(fmt_id(`price_qty_amt`), `1`);
- if (!vals_1.qty_avail)
- await kv.set(fmt_id(`qty_avail`), `1`);
- const vals_2 = await kv_validate_trade_product_fields({
- kv_pref: fmt_id(),
- no_validation: [`summary`, `title`],
- });
- if (`err` in vals_2) {
- await dialog.alert(
- `${$t(`trade.product.fields.${vals_2.err}.err_invalid`, { default: `${$t(`icu.invalid_*`, { value: vals_2.err })}` })}`,
- );
- return;
+ if (photo_add_list.length < 1) {
+ await dialog.alert(`A primary photo is required`);
+ return; //@todo
}
- preview_trade_product = vals_2;
+
await carousel_inc(view);
}
break;
case 1:
{
- await carousel_inc(view);
- }
- break;
- case 2:
- {
- await carousel_inc(view);
- }
- break;
- case 3:
- {
- const vals = await kv_validate_trade_product_fields({
- kv_pref: fmt_id(),
- });
- if (`err` in vals) {
- const el = el_id(fmt_id(`${vals.err}_wrap`));
+ const validate_fields =
+ await validate_trade_product_fields({
+ kv_pref: fmt_id(),
+ fields: [
+ `price_amt`,
+ `price_currency`,
+ `price_qty_unit`,
+ ],
+ });
+ if (`err` in validate_fields) {
await dialog.alert(
- `${$t(`icu.enter_the_*`, { value: `${$t(`common.${vals.err}`)}`.toLowerCase() })}`,
+ `${$t(`icu.enter_the_*`, { value: `${$t(`model.trade_product.${validate_fields.err}`)}`.toLowerCase() })}`,
);
- el?.classList.add(`entry-layer-1-highlight`);
- await sleep(cfg.delay.entry_focus);
- el?.classList.remove(`entry-layer-1-highlight`);
return;
}
- await carousel_inc(view);
- }
- break;
- case 4:
- {
- await submit();
+ console.log(
+ JSON.stringify(validate_fields, null, 4),
+ `validate_fields`,
+ );
}
break;
}
- if (num) {
- carousel_num.set(num);
- }
} catch (e) {
console.log(`(error) handle_continue `, e);
}
};
- const toggle_show_key_other = async (visible: boolean): Promise<void> => {
- try {
- show_sel_trade_product_key_other = visible;
- if (visible) {
- await kv.set(fmt_id(`key`), ``);
- } else {
- sel_trade_product_key = trade_keys[0];
- }
- } catch (e) {
- console.log(`(error) toggle_show_key_other `, e);
- }
- };
-
- const toggle_show_qty_amt_other = async (
- visible: boolean,
- ): Promise<void> => {
- try {
- show_sel_trade_product_qty_tup_other = visible;
- if (visible) {
- sel_trade_product_price_qty_unit = mass_units[0];
- await kv.set(fmt_id(`qty_amt`), ``);
- } else {
- sel_trade_product_qty_tup = sel_trade_product_key_parsed
- ? fmt_trade_quantity_val(
- trade_quantities[sel_trade_product_key_parsed][0],
- )
- : ``;
- }
- } catch (e) {
- console.log(`(error) toggle_show_qty_amt_other `, e);
- }
- };
-
- const fetch_models_models_location_gcs = async (): Promise<void> => {
- try {
- const res = await db.location_gcs_get({
- list: [`all`],
- });
- if (`results` in res) ls_models_location_gcs = res.results;
- } catch (e) {
- console.log(`(error) fetch_models_models_location_gcs `, e);
- }
- };
-
- const handle_render_map_initial = async (): Promise<void> => {
- try {
- const geolc = await geol.current();
- if (!(`err` in geolc)) {
- map_choose_loc_geoc_point = {
- ...geolc,
- };
- map_choose_loc_geoc_point_select = map_choose_loc_geoc_point;
- }
- await sleep(600);
- } catch (e) {
- console.log(`(error) handle_render_map_initial `, e);
- } finally {
- map_choose_loc_loading = false;
- }
- };
-
- const handle_map_reset = (): void => {
- map_choose_loc_geoc_point_select = map_choose_loc_geoc_point;
- };
-
- const handle_entry_focus = async (id_key: string): Promise<void> => {
- try {
- const el = el_id(fmt_id(id_key));
- el?.classList.add(`entry-layer-1-highlight`);
- el?.focus();
- await handle_back(2);
- await sleep(1000);
- el?.classList.remove(`entry-layer-1-highlight`);
- } catch (e) {
- console.log(`(error) handle_entry_focus `, e);
- }
- };
-
const submit = async (): Promise<void> => {
try {
- loading_submit = true;
- console.log(`@todo submit`);
} catch (e) {
console.log(`(error) submit `, e);
- } finally {
- loading_submit = false;
}
};
</script>
<LayoutView>
<div
- data-view={`load`}
- class={`flex flex-col h-full w-full justify-start items-start`}
- >
- <Fill />
- </div>
- <div
- data-view={`form_1`}
- class={`hidden flex flex-col h-full w-full justify-start items-center`}
+ in:fade={{ delay: 100, duration: 200 }}
+ out:fade={{ delay: 0, duration: 200 }}
+ data-carousel-container={`main`}
+ class={`carousel-container flex h-full w-full`}
>
<div
- data-carousel-container={`form_1`}
- class={`carousel-container flex h-full w-full ${view === `form_1` ? `fade-in` : ``}`}
+ data-carousel-item={`main`}
+ class={`carousel-item flex flex-col w-full pt-4 justify-start items-center`}
>
- <div
- data-carousel-item={`form_1`}
- class={`carousel-item flex flex-col w-full justify-start items-center`}
- >
- <LayoutTrellis basis={{ classes: `gap-5` }}>
- <LayoutTrellisLine
+ <LayoutTrellis>
+ <ImageUploadRow
+ basis={{
+ loading: photo_add_loading,
+ list: photo_add_list,
+ callback_add: handle_photo_add,
+ }}
+ />
+ <LayoutTrellisLine
+ basis={{
+ label: {
+ value: `${$t(`common.product`)}`,
+ },
+ notify: tradeproduct_key_sel_toggle
+ ? {
+ label: {
+ value: `${$t(`common.back`)}`,
+ },
+ glyph: {
+ key: `selection-foreground`,
+ weight: `bold`,
+ dim: `xs`,
+ },
+ callback: async () => {
+ const kv_other = await kv.get(
+ fmt_id(`key`),
+ );
+ if (kv_other) {
+ const confirm = await dialog.confirm({
+ message: `${$t(`icu.the_current_entry_*_will_be_deleted`, { value: kv_other })}. ${$t(`common.do_you_want_to_continue_q`)}`,
+ });
+ if (confirm === false) return;
+ }
+ await toggle_tradeproduct_key(false);
+ },
+ }
+ : undefined,
+ }}
+ >
+ {#if !tradeproduct_key_sel_toggle}
+ <EntrySelect
+ bind:value={$tradeproduct_key_sel}
+ basis={{
+ wrap: {
+ id: fmt_id(`key_wrap`),
+ },
+ el: {
+ id: fmt_id(`key`),
+ layer: 1,
+ options: [
+ {
+ entries: [
+ {
+ value: ``,
+ label: `Choose product`,
+ disabled: true,
+ },
+ ...trade_keys.map((i) => ({
+ value: i,
+ label: `${$t(`trade.product.key.${i}.name`, { default: i })}`,
+ })),
+ {
+ value: `other`,
+ label: `${$t(`common.other`)}`,
+ },
+ ],
+ },
+ ],
+ callback: async (opt) => {
+ const el = el_id(fmt_id(`key_wrap`));
+ el?.classList.remove(
+ `entry-layer-1-highlight`,
+ );
+ if (opt.value === `other`) {
+ await toggle_tradeproduct_key(true);
+ }
+ },
+ },
+ }}
+ />
+ {:else}
+ <EntryLine
+ basis={{
+ wrap: {
+ id: fmt_id(`key_wrap`),
+ },
+ el: {
+ classes: `fade-in-long`,
+ id: fmt_id(`key`),
+ sync: true,
+ placeholder: `${$t(`icu.enter_the_*`, { value: `${$t(`icu.*_name`, { value: `${$t(`common.product`)}` })}`.toLowerCase() })}`,
+ field: {
+ charset:
+ trade_product_form_fields.title
+ .charset,
+ validate:
+ trade_product_form_fields.title
+ .validation,
+ validate_keypress: true,
+ },
+ },
+ }}
+ />
+ {/if}
+ </LayoutTrellisLine>
+ <LayoutTrellisLine
+ basis={{
+ label: {
+ value: `${$t(`common.description`)}`,
+ },
+ }}
+ >
+ <EntryMultiline
basis={{
- label: {
- value: `${$t(`common.product`)}`,
+ wrap: {
+ id: fmt_id(`summary_wrap`),
+ },
+ el: {
+ classes: `h-[14rem]`,
+ 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,
+ },
},
- notify: show_sel_trade_product_key_other
- ? {
- classes: `w-full justify-end`,
- label: {
- value: `${$t(`icu.show_*`, { value: `${$t(`common.options`)}` })}`,
- },
- callback: async () => {
- const kv_other = await kv.get(
- fmt_id(`key`),
- );
- if (kv_other) {
- const confirm =
- await dialog.confirm({
- message: `${$t(`icu.the_current_entry_*_will_be_deleted`, { value: kv_other })}. ${$t(`common.do_you_want_to_continue_q`)}`,
- });
- if (confirm === true)
- await kv.set(
- fmt_id(`key`),
- trade_key_default,
- );
- }
- await toggle_show_key_other(false);
- },
- }
- : undefined,
+ }}
+ />
+ </LayoutTrellisLine>
+ </LayoutTrellis>
+ </div>
+ <div
+ data-carousel-item={`main`}
+ class={`carousel-item flex flex-col w-full pt-4 justify-start items-center`}
+ >
+ <ImageUploadDisplay
+ basis={{
+ loading: photo_add_loading,
+ list: photo_add_list,
+ callback_add: handle_photo_add,
+ }}
+ />
+ <LayoutTrellis>
+ <LayoutTrellisLine
+ basis={{
+ label: {
+ value: `${$t(`icu.*_price`, { value: `${$t(`common.product`)}` })}`,
+ },
+ }}
+ >
+ <EntryWrap
+ basis={{
+ classes: `pl-3`,
+ id: fmt_id(`price_wrap`),
}}
>
- {#if !show_sel_trade_product_key_other}
- <EntrySelect
- bind:value={sel_trade_product_key}
+ <div
+ class={`flex flex-row justify-start items-center pr-3`}
+ >
+ <SelectElement
+ bind:value={$tradeproduct_price_curr_sel}
basis={{
- wrap: {
- id: fmt_id(`key_wrap`),
- },
- el: {
- id: fmt_id(`key`),
- sync: true,
- options: [
- ...trade_keys.map((i) => ({
- value: i,
- label: `${$t(`trade.product.key.${i}`, { default: i })}`,
- })),
- {
- value: `other`,
- label: `${$t(`common.other`)}`,
- },
- ],
- callback: async (val) => {
- const el = el_id(
- fmt_id(`key_wrap`),
- );
- el?.classList.remove(
- `entry-layer-1-highlight`,
- );
- if (val === `other`) {
- await toggle_show_key_other(
- true,
- );
- }
+ id: fmt_id(`price_currency`),
+ classes: `w-fit font-circ font-[500] text-[1.2rem] -translate-y-[1px]`,
+ layer: false,
+ options: [
+ {
+ entries: fiat_currencies.map(
+ (i) => ({
+ value: `${i}`,
+ label: `${$t(`currency.${i}.symbol`, { default: i })}`,
+ }),
+ ),
},
- },
+ ],
}}
/>
- {:else}
- <EntryLine
+ </div>
+ <InputElement
+ basis={{
+ id: fmt_id(`price_amt`),
+ layer: 1,
+ sync: true,
+ sync_init: true,
+ placeholder: `${$t(`common.price`)}`,
+ 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
+ ) {
+ const el = el_id(fmt_id(`price_wrap`));
+ el?.classList.remove(
+ `entry-layer-1-highlight`,
+ );
+ } else {
+ const el = el_id(fmt_id(`price_wrap`));
+ el?.classList.add(
+ `entry-layer-1-highlight`,
+ );
+ }
+ },
+ callback_blur: async ({ el }) => {
+ if (!el.value) return;
+ el.value = price_locale_fmt(
+ $tradeproduct_price_curr_sel,
+ el.value,
+ ).slice(1);
+ },
+ }}
+ />
+ <div
+ class={`flex flex-row gap-2 justify-end items-center text-layer-1-glyph/70`}
+ >
+ <p class={`font-circ font-[500] text-[1.05rem]`}>
+ {`${$t(`common.per`)}`}
+ </p>
+ <SelectElement
+ bind:value={$tradeproduct_price_qty_unit_sel}
basis={{
- wrap: {
- id: fmt_id(`key_wrap`),
- },
- el: {
- id: fmt_id(`key`),
- sync: true,
- sync_init: true,
- placeholder: `${$t(`icu.enter_the_*`, { value: `${$t(`icu.*_name`, { value: `${$t(`common.product`)}` })}`.toLowerCase() })}`,
- field: {
- charset:
- trade_product_form_fields.title
- .charset,
- validate:
- trade_product_form_fields.title
- .validation,
- validate_keypress: true,
+ id: fmt_id(`price_qty_unit`),
+ classes: `w-fit font-circ font-[500] text-[1.05rem]`,
+ layer: false,
+ options: [
+ {
+ entries: mass_units.map((i) => ({
+ value: i,
+ label: `${$t(`measurement.mass.unit.${i}_ab`, { default: i })}`.toLowerCase(),
+ })),
},
- },
+ ],
}}
/>
- {/if}
- </LayoutTrellisLine>
- <LayoutTrellisLine
- basis={{
- label: {
- value: `${$t(`common.price`)}`,
- },
- }}
- >
+ </div>
+ </EntryWrap>
+ </LayoutTrellisLine>
+ <LayoutTrellisLine
+ basis={{
+ label: {
+ value: `${$t(`common.quantity`)}`,
+ },
+ notify: tradeproduct_qty_unit_tup_sel_toggle
+ ? {
+ label: {
+ value: `${$t(`common.back`)}`,
+ },
+ glyph: {
+ key: `selection-foreground`,
+ weight: `bold`,
+ dim: `xs`,
+ },
+ callback: async () => {
+ await toggle_tradeproduct_qty_amt(false);
+ },
+ }
+ : undefined,
+ }}
+ >
+ {#if !tradeproduct_qty_unit_tup_sel_toggle}
+ <EntrySelect
+ bind:value={$tradeproduct_qty_unit_tup_sel}
+ basis={{
+ wrap: {
+ id: fmt_id(`qty_wrap`),
+ },
+ el: {
+ layer: 1,
+ options: [
+ {
+ entries: [
+ ...ls_trade_product_quantities.map(
+ (i) => ({
+ value: fmt_trade_quantity_sel_val(
+ i,
+ ),
+ label: `${i.mass} ${$t(`measurement.mass.unit.${i.mass_unit}_ab`, { default: i.mass_unit })} ${i.label}`,
+ }),
+ ),
+ {
+ value: `other`,
+ label: `${$t(`common.other`)}`,
+ },
+ ],
+ },
+ ],
+ callback: async ({ value }) => {
+ el_id(
+ fmt_id(`qty_wrap`),
+ )?.classList.remove(
+ `entry-layer-1-highlight`,
+ );
+ if (value === `other`) {
+ await toggle_tradeproduct_qty_amt(
+ true,
+ );
+ } else {
+ await kv.set(
+ fmt_id(`qty_avail`),
+ `1`,
+ );
+ }
+ },
+ },
+ }}
+ />
+ {:else}
<EntryWrap
basis={{
- id: fmt_id(`price_wrap`),
+ id: fmt_id(`qty_wrap`),
}}
>
<InputElement
basis={{
- id: fmt_id(`price_amt`),
+ id: fmt_id(`qty_amt`),
layer: 1,
sync: true,
- sync_init: true,
- placeholder: `${$t(`icu.enter_*`, { value: `${$t(`common.price`)}`.toLowerCase() })}`,
+ placeholder: `${$t(`icu.enter_*_per_order`, { value: `${$t(`common.quantity`)}`.toLowerCase() })}`,
field: {
charset:
- trade_product_form_fields.price_amt
+ trade_product_form_fields.qty_amt
.charset,
validate:
- trade_product_form_fields.price_amt
+ trade_product_form_fields.qty_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
- ) {
- const el = el_id(
- fmt_id(`price_wrap`),
- );
- el?.classList.remove(
- `entry-layer-1-highlight`,
- );
- } else {
- const el = el_id(
- fmt_id(`price_wrap`),
- );
- el?.classList.add(
- `entry-layer-1-highlight`,
- );
- }
- },
}}
/>
<div
- class={`flex flex-row gap-2 justify-end items-center text-layer-1-glyph/70`}
+ class={`absolute top-0 right-0 flex flex-row h-full pr-4 justify-end items-center`}
>
- <SelectEl
- bind:value={sel_trade_product_price_currency}
+ <SelectElement
+ bind:value={$tradeproduct_price_qty_unit_sel}
basis={{
- id: fmt_id(`price_currency`),
- classes: `w-fit font-circ font-[500] text-[1rem]`,
+ id: fmt_id(`qty_unit`),
+ classes: `w-fit font-circ font-[500] text-[1.1rem] text-layer-1-glyph/70`,
layer: false,
- //hide_arrows: true,
- //sync: true,
- options: [
- {
- entries: fiat_currencies.map(
- (i) => ({
- value: i,
- label: `${$t(`currency.${i}.symbol`, { default: i })}`,
- }),
- ),
- },
- ],
- }}
- />
- <p
- class={`font-sans font-[500] text-[1.1rem] -translate-y-[1px] scale-y-[120%]`}
- >
- {`/`}
- </p>
- <SelectEl
- bind:value={sel_trade_product_price_qty_unit}
- basis={{
- id: fmt_id(`price_qty_unit`),
- classes: `w-fit font-circ font-[500] text-[1rem]`,
- layer: false,
- // hide_arrows: true,
- // sync: true,
options: [
{
entries: mass_units.map(
@@ -674,47 +742,47 @@
/>
</div>
</EntryWrap>
- </LayoutTrellisLine>
- <LayoutTrellisLine
- basis={{
- label: {
- value: `${$t(`common.quantity`)}`,
- },
- notify: show_sel_trade_product_qty_tup_other
- ? {
- classes: `w-full justify-end`,
- label: {
- value: `${$t(`icu.show_*`, { value: `${$t(`common.options`)}` })}`,
- },
- callback: async () => {
- await toggle_show_qty_amt_other(
- false,
- );
- },
- }
- : undefined,
- }}
- >
- <div
- id={fmt_id(`qty_wrap`)}
- tabindex={-1}
- class={`relative el-re flex flex-row w-full gap-3 justify-between items-center h-form_line bg-layer-1-surface text-layer-1-glyph rounded-2xl`}
- >
- {#if !show_sel_trade_product_qty_tup_other}
- <EntrySelect
- bind:value={sel_trade_product_qty_tup}
- basis={{
- wrap: {
- id: `tmp`,
- },
- el: {
- options: [
- ...ls_trade_product_quantities.map(
+ {/if}
+ </LayoutTrellisLine>
+ <LayoutTrellisLine
+ basis={{
+ label: {
+ value: `${$t(`common.process`)}`,
+ },
+ notify: tradeproduct_process_sel_toggle
+ ? {
+ label: {
+ value: `${$t(`common.back`)}`,
+ },
+ glyph: {
+ key: `selection-foreground`,
+ weight: `bold`,
+ dim: `xs`,
+ },
+ glyph_last: true,
+ callback: async () => {
+ await toggle_tradeproduct_process(false);
+ },
+ }
+ : undefined,
+ }}
+ >
+ {#if !tradeproduct_process_sel_toggle}
+ <EntrySelect
+ bind:value={$tradeproduct_process_sel}
+ basis={{
+ wrap: {
+ id: fmt_id(`process_wrap`),
+ },
+ el: {
+ layer: 1,
+ options: [
+ {
+ entries: [
+ ...ls_trade_product_processes.map(
(i) => ({
- value: fmt_trade_quantity_val(
- i,
- ),
- label: `${i.mass} ${$t(`measurement.mass.unit.${i.mass_unit}_ab`, { default: i.mass_unit })} ${i.label}`,
+ value: i,
+ label: `${$t(`trade.product.key.${tradeproduct_key_parsed}.process.${i}`)}`,
}),
),
{
@@ -722,116 +790,35 @@
label: `${$t(`common.other`)}`,
},
],
- callback: async (val) => {
- el_id(
- fmt_id(`qty_wrap`),
- )?.classList.remove(
- `entry-layer-1-highlight`,
- );
- if (val === `other`) {
- await toggle_show_qty_amt_other(
- true,
- );
- } else {
- await kv.set(
- fmt_id(`qty_avail`),
- `1`,
- );
- }
- },
},
- }}
- />
- {:else}
- <div
- class={`relative flex flex-row w-full justify-center items-center`}
- >
- <InputElement
- basis={{
- id: fmt_id(`qty_amt`),
- layer: false,
- sync: true,
- placeholder: `${$t(`icu.enter_number_of_*_per_order`, { value: `${$t(`measurement.mass.unit.${sel_trade_product_price_qty_unit}_ab`, { default: sel_trade_product_price_qty_unit })}` })}`,
- field: {
- charset:
- trade_product_form_fields
- .qty_amt.charset,
- validate:
- trade_product_form_fields
- .qty_amt.validation,
- validate_keypress: true,
- },
- }}
- />
- <div
- class={`absolute top-0 right-0 flex flex-row h-full gap-2 justify-center items-center`}
- >
- <EntrySelect
- bind:value={sel_trade_product_qty_unit}
- basis={{
- wrap: {
- id: `tmp2`,
- },
- el: {
- id: fmt_id(`qty_unit`),
- classes: `w-[3.5rem] text-layer-1-glyph font-[500]`,
- //layer: false,
- //sync: true,
- options: mass_units.map(
- (i) => ({
- value: i,
- label: `${$t(`measurement.mass.unit.${i}_ab`, { default: i })}`,
- }),
- ),
- },
- }}
- />
- </div>
- </div>
- {/if}
- </div>
- </LayoutTrellisLine>
- <LayoutTrellisLine
- basis={{
- label: {
- value: `${$t(`model.trade_product.lot`)}`,
- },
- }}
- >
- <EntryLine
- basis={{
- el: {
- id: fmt_id(`lot`),
- sync: true,
- sync_init: true,
- placeholder: `${$t(`icu.enter_*`, { value: `${$t(`common.lot_name`)}`.toLowerCase() })}`,
- field: {
- charset:
- trade_product_form_fields.lot
- .charset,
- validate:
- trade_product_form_fields.lot
- .validation,
- validate_keypress: true,
+ ],
+ callback: async ({ value }) => {
+ el_id(
+ fmt_id(`process_wrap`),
+ )?.classList.remove(
+ `entry-layer-1-highlight`,
+ );
+ if (value === `other`) {
+ await toggle_tradeproduct_process(
+ true,
+ );
+ }
},
},
}}
/>
- </LayoutTrellisLine>
- <LayoutTrellisLine
- basis={{
- label: {
- value: `${$t(`model.trade_product.process`)}`,
- },
- }}
- >
- <EntryLine
+ {:else}
+ <EntryWrap
basis={{
- el: {
+ id: fmt_id(`process_wrap`),
+ }}
+ >
+ <InputElement
+ basis={{
id: fmt_id(`process`),
+ layer: 1,
sync: true,
- sync_init: true,
- placeholder: `${$t(`icu.enter_*`, { value: `${$t(`icu.*_description`, { value: `${$t(`common.process`)}` })}`.toLowerCase() })}`,
+ placeholder: `Enter the process`,
field: {
charset:
trade_product_form_fields.process
@@ -841,599 +828,12 @@
.validation,
validate_keypress: true,
},
- },
- }}
- />
- </LayoutTrellisLine>
- </LayoutTrellis>
- </div>
- <div
- data-carousel-item={`form_1`}
- class={`carousel-item flex flex-col w-full pt-4 gap-4 justify-start items-center`}
- >
- <MapChooseLocation
- basis={{
- classes_map: `h-[280px] w-full`,
- loading: map_choose_loc_loading,
- }}
- bind:map_point_center={map_choose_loc_geoc_point}
- bind:map_point_select={map_choose_loc_geoc_point_select}
- bind:map_point_select_geoc={map_choose_loc_geoc_point_select_geoc}
- />
- <div
- class={`grid grid-cols-12 flex flex-col w-full px-4 gap-1 justify-start items-center`}
- >
- <div
- class={`col-span-9 flex flex-row w-full justify-start items-center`}
- >
- <p
- class={`w-[5.3rem] font-circ font-[500] text-layer-1-glyph-shade tracking-tight`}
- >
- {`${$t(`common.latitude`)}:`}
- </p>
- <p class={`font-circ font-[400] text-layer-1-glyph`}>
- {fmt_geol_latitude(
- map_choose_loc_geoc_point_select.lat,
- `dms`,
- )}
- </p>
- </div>
- <div
- class={`col-span-3 flex flex-row w-full justify-end items-center`}
- >
- <button
- class={`group flex flex-row gap-[6px] justify-center items-center`}
- on:click={async () => {
- handle_map_reset();
- }}
- >
- <p
- class={`font-sg font-[500] text-layer-1-glyph tracking-tight group-active:opacity-80 el-re`}
- >
- {`${$t(`common.reset`)}`}
- </p>
- <Glyph
- basis={{
- classes: `text-layer-1-glyph/80 group-active:opacity-60 el-re`,
- dim: `sm`,
- weight: `bold`,
- key: `arrow-counter-clockwise`,
}}
/>
- </button>
- </div>
- <div
- class={`col-span-9 flex flex-row w-full justify-start items-center`}
- >
- <p
- class={`w-[5.3rem] font-circ font-[500] text-layer-1-glyph-shade tracking-tight`}
- >
- {`${$t(`common.longitude`)}:`}
- </p>
- <p class={`font-circ font-[400] text-layer-1-glyph`}>
- {fmt_geol_longitude(
- map_choose_loc_geoc_point_select.lng,
- `dms`,
- )}
- </p>
- </div>
- {#if map_choose_loc_geoc_point_select_geoc}
- <div
- class={`col-span-9 flex flex-row w-full justify-start items-center`}
- >
- <p
- class={`w-[5.3rem] font-circ font-[500] text-layer-1-glyph-shade tracking-tight`}
- >
- {`${$t(`common.location`)}:`}
- </p>
- <p
- class={`font-circ font-[400] text-layer-1-glyph`}
- >
- {`${map_choose_loc_geoc_point_select_geoc.admin1_name}, ${map_choose_loc_geoc_point_select_geoc.country_name}`}
- </p>
- </div>
- {/if}
- </div>
- </div>
- <div
- data-carousel-item={`form_1`}
- class={`carousel-item flex flex-col w-full justify-start items-center`}
- >
- <LayoutTrellis>
- {#if preview_trade_product && preview_trade_product_price_currency}
- <LayoutTrellisLine>
- <div
- class={`relative flex flex-col h-[36rem] w-full px-6 pb-4 gap-8 justify-around items-start bg-layer-0-surface rounded-touch`}
- >
- <div
- class={`flex flex-col flex-grow w-full justify-around items-center`}
- >
- <div
- class={`flex flex-col w-full gap-2 justify-start items-start`}
- >
- <p
- class={`font-mono font-[400] text-[1.25rem] text-layer-1-glyph`}
- >
- {`${$t(`common.product`)}:`}
- </p>
- <div
- class={`flex flex-row w-full justify-between items-center`}
- >
- <div
- class={`flex flex-row flex-grow gap-1 justify-start items-center`}
- >
- <p
- class={`font-mono font-[600] text-layer-2-glyph/40 pr-2`}
- >
- {`-`}
- </p>
- <p
- class={`font-circ font-[400] text-[1.3rem] text-layer-1-glyph-shade capitalize`}
- >
- {`${preview_trade_product.key}`}
- </p>
- </div>
- <div
- class={`flex flex-row justify-end items-center`}
- >
- <button
- class={`flex flex-row justify-start items-center active:opacity-60 transition-all`}
- on:click={async () => {
- await handle_entry_focus(
- `key_wrap`,
- );
- }}
- >
- <p
- class={`label-sg font-[600] text-[1rem] text-layer-2-glyph`}
- >
- {`${$t(`common.edit`)}`}
- </p>
- </button>
- </div>
- </div>
- </div>
- <div
- class={`flex flex-col w-full gap-2 justify-start items-start`}
- >
- <p
- class={`font-mono font-[400] text-[1.25rem] text-layer-1-glyph`}
- >
- {`${$t(`common.origin`)}:`}
- </p>
- <div
- class={`flex flex-row w-full justify-between items-center`}
- >
- <div
- class={`flex flex-row flex-grow gap-1 justify-start items-center`}
- >
- <p
- class={`font-mono font-[600] text-layer-2-glyph/40 pr-2`}
- >
- {`-`}
- </p>
- {#if map_choose_loc_geoc_point_select_geoc}
- <p
- class={`font-circ font-[400] text-[1.3rem] text-layer-1-glyph-shade capitalize`}
- >
- {`${map_choose_loc_geoc_point_select_geoc.admin1_name}, ${map_choose_loc_geoc_point_select_geoc.country_id}`}
- </p>
- {/if}
- </div>
- <div
- class={`flex flex-row justify-end items-center`}
- >
- <button
- class={`flex flex-row justify-start items-center active:opacity-60 transition-all`}
- on:click={async () => {
- await handle_back();
- }}
- >
- <p
- class={`label-sg font-[600] text-[1rem] text-layer-2-glyph`}
- >
- {`${$t(`common.edit`)}`}
- </p>
- </button>
- </div>
- </div>
- </div>
- <div
- class={`flex flex-col w-full gap-2 justify-start items-start`}
- >
- <p
- class={`font-mono font-[400] text-[1.25rem] text-layer-1-glyph`}
- >
- {`${$t(`common.price`)}:`}
- </p>
- <div
- class={`flex flex-row w-full justify-between items-center`}
- >
- <div
- class={`flex flex-row flex-grow gap-1 justify-start items-center`}
- >
- <p
- class={`font-mono font-[600] text-layer-2-glyph/40 pr-2`}
- >
- {`-`}
- </p>
- <p
- class={`font-circ font-[400] text-[1.3rem] text-layer-1-glyph-shade`}
- >
- {preview_trade_product_price_currency.symbol}
- </p>
- <p
- class={`font-circ font-[400] text-[1.3rem] text-layer-1-glyph-shade`}
- >
- {`${(preview_trade_product_price_currency.val_i + preview_trade_product_price_currency.val_f).toFixed(2)}`}
- </p>
- <p
- class={`font-circ font-[400] text-[1.3rem] text-layer-1-glyph-shade lowercase`}
- >
- {`${$t(`common.per`)}`}
- </p>
- {#if preview_trade_product.price_qty_amt === `1`}
- <p
- class={`font-circ font-[400] text-[1.3rem] text-layer-1-glyph-shade`}
- >
- {`${$t(`measurement.mass.unit.${preview_trade_product.price_qty_unit}_ab`, { default: preview_trade_product.price_qty_unit })}`}
- </p>
- {/if}
- </div>
- <div
- class={`flex flex-row justify-end items-center`}
- >
- <button
- class={`flex flex-row justify-start items-center active:opacity-60 transition-all`}
- on:click={async () => {
- await handle_entry_focus(
- `price_wrap`,
- );
- /*const el = el_id(
- fmt_id(
- `price_wrap`,
- ),
- );
- console.log(`el `, el);
- el?.classList.add(
- `entry-layer-1-highlight`,
- );
- el?.focus();
- await handle_back(2);
- await sleep(
- cfg.delay
- .entry_focus,
- );
- el?.classList.remove(
- `entry-layer-1-highlight`,
- );*/
- }}
- >
- <p
- class={`label-sg font-[600] text-[1rem] text-layer-2-glyph`}
- >
- {`${$t(`common.edit`)}`}
- </p>
- </button>
- </div>
- </div>
- </div>
- <div
- class={`flex flex-col w-full gap-2 justify-start items-start`}
- >
- <p
- class={`font-mono font-[400] text-[1.25rem] text-layer-1-glyph`}
- >
- {`${$t(`common.quantity`)}:`}
- </p>
- <div
- class={`flex flex-row w-full justify-between items-center`}
- >
- <div
- class={`flex flex-row flex-grow gap-1 justify-start items-center`}
- >
- <p
- class={`font-mono font-[600] text-layer-2-glyph/40 pr-2`}
- >
- {`-`}
- </p>
- <p
- class={`font-circ font-[400] text-[1.3rem] text-layer-1-glyph-shade`}
- >
- {preview_trade_product.qty_amt}
- </p>
- <p
- class={`font-circ font-[400] text-[1.3rem] text-layer-1-glyph-shade`}
- >
- {`${$t(`measurement.mass.unit.${preview_trade_product.qty_unit}_ab`, { default: preview_trade_product.qty_unit })}`}
- </p>
- <p
- class={`font-circ font-[400] text-[1.3rem] text-layer-1-glyph-shade`}
- >
- {preview_trade_product.qty_label}
- </p>
- </div>
- <div
- class={`flex flex-row justify-end items-center`}
- >
- <button
- class={`flex flex-row justify-start items-center active:opacity-60 transition-all`}
- on:click={async () => {
- const el = el_id(
- fmt_id(`qty_wrap`),
- );
- el?.classList.add(
- `entry-layer-1-highlight`,
- );
- el?.focus();
- await handle_back(2);
- await sleep(
- cfg.delay
- .entry_focus,
- );
- el?.classList.remove(
- `entry-layer-1-highlight`,
- );
- }}
- >
- <p
- class={`label-sg font-[600] text-[1rem] text-layer-2-glyph`}
- >
- {`${$t(`common.edit`)}`}
- </p>
- </button>
- </div>
- </div>
- </div>
- <div
- class={`flex flex-col w-full gap-2 justify-start items-start`}
- >
- <p
- class={`font-mono font-[400] text-[1.25rem] text-layer-1-glyph`}
- >
- {`${$t(`icu.*_available`, { value: `${$t(`common.quantity`)}` })}:`}
- </p>
- <div
- class={`flex flex-row w-full justify-between items-center`}
- >
- <div
- class={`flex flex-row flex-grow gap-1 justify-start items-center`}
- >
- <p
- class={`font-mono font-[600] text-layer-2-glyph/40 pr-2`}
- >
- {`-`}
- </p>
- <p
- class={`font-circ font-[400] text-[1.3rem] text-layer-1-glyph-shade`}
- >
- {`${preview_trade_product_qty_avail} ${preview_trade_product.qty_label}`}
- </p>
- <p
- class={`font-circ font-[400] text-[1.3rem] text-layer-1-glyph-shade`}
- >
- {`(${(preview_trade_product_qty_avail * num_trade_product_qty_amt).toFixed(2)} ${$t(`measurement.mass.unit.${preview_trade_product.qty_unit}_ab`, { default: preview_trade_product.qty_unit })})`}
- </p>
- </div>
- <div
- class={`flex flex-row gap-[10px] justify-center items-center`}
- >
- <ButtonGlyph
- basis={{
- key: `arrow-down`,
- dim: `xs+`,
- weight: `bold`,
- classes: `h-8 w-8 text-layer-2-glyph bg-layer-2-surface active:opacity-60 rounded-full transition-all`,
- callback: async () => {
- preview_trade_product_qty_avail =
- int_step(
- preview_trade_product_qty_avail,
- `-`,
- 1,
- );
- await kv.set(
- fmt_id(
- `qty_avail`,
- ),
- preview_trade_product_qty_avail.toString(),
- );
- },
- }}
- />
- <ButtonGlyph
- basis={{
- key: `arrow-up`,
- dim: `xs+`,
- weight: `bold`,
- classes: `h-8 w-8 text-layer-2-glyph bg-layer-2-surface active:opacity-60 rounded-full transition-all`,
- callback: async () => {
- preview_trade_product_qty_avail =
- int_step(
- preview_trade_product_qty_avail,
- `+`,
- );
- await kv.set(
- fmt_id(
- `qty_avail`,
- ),
- preview_trade_product_qty_avail.toString(),
- );
- },
- }}
- />
- </div>
- </div>
- </div>
- </div>
- <div
- class={`flex flex-row w-full justify-start items-center`}
- >
- <div
- class={` flex flex-row h-[1px] w-full justify-start items-center bg-layer-2-surface`}
- >
- <Fill />
- </div>
- </div>
- <div
- class={`flex flex-col w-full gap-4 justify-start items-start`}
- >
- <div
- class={`flex flex-col w-full gap-4 justify-start items-start`}
- >
- <div
- class={`flex flex-row w-full justify-between items-center`}
- >
- <div
- class={`flex flex-row justify-start items-center`}
- >
- <p
- class={`font-mono font-[400] text-layer-1-glyph text-lg`}
- >
- {`${`${$t(`common.quantity`)}`}:`}
- </p>
- </div>
- <div
- class={`flex flex-row gap-2 justify-start items-center`}
- >
- <p
- class={`font-mono font-[500] text-layer-1-glyph/80 text-lg`}
- >
- {preview_trade_product_qty_avail}
- </p>
- <p
- class={`font-mono font-[400] text-layer-2-glyph`}
- >
- {`x`}
- </p>
- <p
- class={`font-mono font-[500] text-layer-1-glyph/80 text-lg`}
- >
- {`${num_trade_product_qty_amt.toFixed(2)} ${$t(`measurement.mass.unit.${preview_trade_product.qty_unit}_ab`, { default: preview_trade_product.qty_unit })}`}
- </p>
- <p
- class={`font-mono font-[500] text-layer-1-glyph/80 text-lg`}
- >
- {preview_trade_product.qty_label}
- </p>
- </div>
- </div>
- <div
- class={`flex flex-row w-full justify-between items-center`}
- >
- <div
- class={`flex flex-row justify-start items-center`}
- >
- <p
- class={`font-mono font-[400] text-layer-1-glyph text-lg`}
- >
- {`${$t(`icu.total_*`, { value: `${$t(`common.price`)}` })}:`}
- </p>
- </div>
- <div
- class={`flex flex-row gap-2 justify-start items-center`}
- >
- <p
- class={`font-mono font-[400] text-layer-2-glyph text-lg`}
- >
- {preview_trade_product_price_currency.symbol}
- </p>
- <p
- class={`font-mono font-[600] text-layer-1-glyph/80 text-lg`}
- >
- {num_trade_product_price_total.toFixed(
- 2,
- )}
- </p>
- <p
- class={`font-mono font-[600] text-layer-1-glyph/80 text-lg uppercase`}
- >
- {preview_trade_product_price_currency.currency}
- </p>
- </div>
- </div>
- </div>
- </div>
- </div>
- </LayoutTrellisLine>
+ </EntryWrap>
{/if}
- </LayoutTrellis>
- </div>
- <div
- data-carousel-item={`form_1`}
- class={`carousel-item flex flex-col w-full justify-start items-center`}
- >
- <LayoutTrellis>
- <LayoutTrellisLine
- basis={{
- label: {
- value: `${$t(`common.title`)}`,
- },
- }}
- >
- <EntryLine
- basis={{
- wrap: {
- id: fmt_id(`title_wrap`),
- },
- el: {
- id: fmt_id(`title`),
- sync: true,
- sync_init: true,
- placeholder: `${$t(`icu.enter_the_*`, { value: `${$t(`icu.*_title`, { value: `${$t(`common.listing`)}` })}`.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.summary`)}`,
- },
- }}
- >
- <EntryMultiline
- basis={{
- id_wrap: fmt_id(`summary_wrap`),
- el: {
- classes: `h-[20rem]`,
- id: fmt_id(`summary`),
- sync: true,
- sync_init: true,
- placeholder: `${$t(`icu.enter_the_*`, { value: `${$t(`icu.*_summary`, { 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={`form_1`}
- class={`carousel-item flex flex-col w-full justify-start items-center`}
- >
- <LayoutTrellis>
- <p class={`font-sans font-[400] text-layer-0-glyph`}>
- {`@todo add preview`}
- </p>
- </LayoutTrellis>
- </div>
+ </LayoutTrellisLine>
+ </LayoutTrellis>
</div>
</div>
</LayoutView>
@@ -1456,7 +856,7 @@
},
title: {
label: {
- value: `${$t(`common.product`)}`,
+ value: `${$t(`icu.new_*`, { value: `${$t(`common.product`)}` })}`,
},
callback: async () => {},
},
@@ -1466,15 +866,8 @@
value:
$carousel_num > 1
? `${$t(`common.return`)}`
- : carousel_param.get($carousel_index)?.label_next || ``,
- classes: `text-layer-1-glyph-hl`,
- glyph:
- $carousel_num > 1
- ? {
- key: `caret-right`,
- classes: `text-layer-1-glyph-hl`,
- }
- : undefined,
+ : page_param.carousel.get($carousel_index)
+ ?.label_next || ``,
},
callback: async () => {
if ($carousel_index === $carousel_index_max) await submit();
diff --git a/tailwind.config.ts b/tailwind.config.ts
@@ -140,7 +140,8 @@ const config: Config = {
...Object.fromEntries(Object.entries(dimensions).map(([k, v]) => [`dim_${k}`, v])),
},
borderWidth: {
- "line": "1px"
+ "line": `1px`,
+ "edge": `2px`
},
borderRadius: {
input_form: "8px",
@@ -154,8 +155,6 @@ const config: Config = {
],
daisyui: {
themes: [
- themes.theme_garden_light,
- themes.theme_garden_dark,
themes.theme_earth_light,
themes.theme_earth_dark,
themes.theme_os_dark,