commit 9e4ca5e5a4076049b24c3c193f9e3c767b7512a5
parent 8ca0920ad497be22e4dd3f7303d877d7d2ad2bb9
Author: triesap <137732411+triesap@users.noreply.github.com>
Date: Sat, 7 Dec 2024 22:01:30 +0000
Add `/farm/land` and `/farm/land/add` routes. Edit `/settings` layout. Add map point select component. Add/edit styles.
Diffstat:
6 files changed, 471 insertions(+), 51 deletions(-)
diff --git a/src/lib/components/map_point_select.svelte b/src/lib/components/map_point_select.svelte
@@ -0,0 +1,80 @@
+<script lang="ts">
+ import { geoc } from "$lib/client";
+ import { cfg } from "$lib/conf";
+ import type { GeocoderReverseResult } from "@radroots/geocoder";
+ import { app_thc } from "@radroots/svelte-lib";
+ import { MapLibre, Marker } from "@radroots/svelte-maplibre";
+ import type { GeolocationCoordinatesPoint } from "@radroots/utils";
+ import MapMarkerDot from "./map_marker_dot.svelte";
+ import MapPopupPointGeolocation from "./map_popup_point_geolocation.svelte";
+
+ export let map_point: GeolocationCoordinatesPoint;
+ export let map_geoc: GeocoderReverseResult | undefined = undefined;
+ export let map_center: GeolocationCoordinatesPoint = cfg.map.coords.default;
+
+ $: if (map_point && map_center.lat === 0 && map_center.lng === 0) {
+ map_center = {
+ lat: map_point.lat,
+ lng: map_point.lng - 0.065,
+ };
+ }
+
+ $: {
+ if (
+ map_point &&
+ map_center &&
+ map_center.lat !== 0 &&
+ map_center.lng !== 0
+ ) {
+ (async () => {
+ try {
+ const geoc_res = await geoc.reverse({
+ point: map_point,
+ });
+ if (`results` in geoc_res && geoc_res.results.length > 0)
+ map_geoc = geoc_res.results[0];
+ else map_geoc = undefined;
+ } catch (e) {
+ console.log(`(error) map choose location`, e);
+ }
+ })();
+ }
+ }
+</script>
+
+{#if map_point}
+ <MapLibre
+ center={map_center}
+ zoom={10}
+ class={`h-full w-full`}
+ style={cfg.map.styles.base[$app_thc]}
+ attributionControl={false}
+ >
+ <Marker
+ bind:lngLat={map_point}
+ draggable
+ on:dragend={async () => {
+ if (!map_point) return;
+ const geoc_res = await geoc.reverse({
+ point: map_point,
+ limit: 1,
+ });
+ if (`results` in geoc_res && geoc_res.results.length > 0)
+ map_geoc = geoc_res.results[0];
+ }}
+ >
+ <button
+ class={`flex flex-row justify-center items-center transform -translate-x-[42%]`}
+ on:click={async () => {}}
+ >
+ <MapPopupPointGeolocation
+ basis={{
+ point: map_point,
+ geoc: map_geoc,
+ }}
+ />
+ </button>
+ <MapMarkerDot />
+ </Marker>
+ </MapLibre>
+{/if}
diff --git a/src/routes/(app)/+page.svelte b/src/routes/(app)/+page.svelte
@@ -4,11 +4,11 @@
app_nostr_key,
envelope_visible,
EnvelopeLower,
- Glyph,
LayoutView,
- LogoCircleSm,
ls,
nav_prev,
+ NavToolbar,
+ PageHeader,
route,
TabsFloat,
} from "@radroots/svelte-lib";
@@ -32,50 +32,20 @@
</script>
<LayoutView>
- <div class={`flex flex-row h-12 w-full px-6 justify-between items-center`}>
- <div class={`flex flex-row gap-2 justify-start items-center`}>
- <LogoCircleSm />
- <p
- class={`font-sansd italic font-[700] text-[1.7rem] text-layer-0-glyph`}
- >
- {`radroots`}
- </p>
- </div>
- <button
- class={`flex flex-row justify-center items-center`}
- on:click={async () => {
- await route(`/settings`);
- }}
- >
- <Glyph
- basis={{
- classes: `text-layer-0-glyph`,
- dim: `lg`,
- weight: `bold`,
- key: `gear`,
- }}
- />
- </button>
- </div>
- <div
- class={`flex flex-col w-full pt-4 px-6 gap-4 justify-center items-center`}
- >
- <div class={`flex flex-row w-full justify-start items-center`}>
- <p class={`font-sansd font-[600] text-2xl text-layer-0-glyph`}>
- {`${$ls(`common.general`)}`}
- </p>
- </div>
+ <NavToolbar />
+ <PageHeader basis={{ label: `${$ls(`common.general`)}` }} />
+ <div class={`flex flex-col w-full px-4 gap-4 justify-center items-center`}>
<div class={`flex flex-col w-full gap-5 justify-center items-center`}>
<button
class={`group flex flex-row h-[3.5rem] w-full justify-center items-center rounded-touch bg-layer-1-surface layer-1-active-surface layer-1-active-ring`}
on:click={async () => {
- await route(`/settings/profile`);
+ await route(`/farm/land`);
}}
>
<p
class={`font-sans font-[700] text-xl text-layer-0-glyph capitalize tracking-wider opacity-active`}
>
- {`${$ls(`common.profile`)}`}
+ {`${$ls(`common.farm_land`)}`}
</p>
</button>
</div>
diff --git a/src/routes/(app)/farm/land/+page.svelte b/src/routes/(app)/farm/land/+page.svelte
@@ -0,0 +1,38 @@
+<script lang="ts">
+ import {
+ Fill,
+ LayoutView,
+ NavToolbar,
+ PageHeader,
+ TabsFloat,
+ ls,
+ route,
+ } from "@radroots/svelte-lib";
+</script>
+
+<LayoutView>
+ <NavToolbar />
+ <PageHeader basis={{ label: `${$ls(`common.farm_land`)}` }} />
+ <div class={`flex flex-col w-full px-4 justify-start items-center`}>
+ <button
+ class={`group flex flex-row h-[7rem] w-full px-8 justify-start items-center bg-layer-1-surface layer-1-active-surface round-36 el-re`}
+ on:click={async () => {
+ await route(`/farm/land/add`);
+ }}
+ >
+ <div
+ class={`flex flex-col h-[5rem] w-[5rem] justify-start items-center bg-layer-2-surface round-24 bg-repeat heropattern-topography-white`}
+ >
+ <Fill />
+ </div>
+ <div class={`flex flex-row flex-grow justify-center items-center`}>
+ <p
+ class={`font-sans font-[500] text-[1.4rem] text-layer-0-glyph capitalize opacity-active el-re`}
+ >
+ {`${$ls(`icu.add_*`, { value: `${$ls(`common.land_plot`)}` })}`}
+ </p>
+ </div>
+ </button>
+ </div>
+</LayoutView>
+<TabsFloat />
diff --git a/src/routes/(app)/farm/land/add/+page.svelte b/src/routes/(app)/farm/land/add/+page.svelte
@@ -0,0 +1,337 @@
+<script lang="ts">
+ import { dialog, geol } from "$lib/client";
+ import MapPointSelect from "$lib/components/map_point_select.svelte";
+ import type { GeocoderReverseResult } from "@radroots/geocoder";
+ import {
+ ButtonGlyphPrimary,
+ Fade,
+ InputElement,
+ LayoutView,
+ NavToolbar,
+ PageHeader,
+ carousel_dec,
+ carousel_inc,
+ carousel_index,
+ carousel_init,
+ fmt_geol_latitude,
+ fmt_geol_longitude,
+ fmt_id,
+ ls,
+ } from "@radroots/svelte-lib";
+ import { type GeolocationCoordinatesPoint, regex } from "@radroots/utils";
+ import { onMount } from "svelte";
+
+ let view_init: View = `c_1`;
+ type View = `c_1`;
+ let view: View = view_init;
+
+ let _map_point: GeolocationCoordinatesPoint | undefined = undefined;
+ let _map_geoc: GeocoderReverseResult | undefined = undefined;
+
+ onMount(async () => {
+ try {
+ await init_page();
+ } catch (e) {
+ } finally {
+ }
+ });
+
+ const init_page = async (): Promise<void> => {
+ try {
+ carousel_init(1);
+ const geolc = await geol.current();
+ if (`err` in geolc) {
+ await dialog.alert(
+ `${$ls(`icu.failure_*`, { value: `${$ls(`icu.reading_*`, { value: `${$ls(`common.geocode`)}`.toLowerCase() })}` })}`,
+ );
+ return;
+ }
+ _map_point = {
+ lat: geolc.lat,
+ lng: geolc.lng,
+ };
+ } catch (e) {
+ console.log(`(error) init_page `, e);
+ }
+ };
+
+ const handle_inc = async (): Promise<void> => {
+ try {
+ await carousel_inc(view);
+ } catch (e) {
+ console.log(`(error) handle_inc `, e);
+ }
+ };
+
+ const handle_dec = async (): Promise<void> => {
+ try {
+ await carousel_dec(view);
+ } catch (e) {
+ console.log(`(error) handle_dec `, e);
+ }
+ };
+</script>
+
+<LayoutView>
+ <NavToolbar />
+ <PageHeader
+ basis={{
+ label: `${$ls(`icu.add_*`, { value: `${$ls(`common.farm_land`)}` })}`,
+ }}
+ >
+ <div slot="option" class={`flex flex-row justify-start items-center`}>
+ {#if $carousel_index > 0}
+ <Fade>
+ <ButtonGlyphPrimary
+ basis={{
+ label: `${$ls(`common.back`)}`,
+ callback: async () => {
+ await handle_dec();
+ },
+ }}
+ />
+ </Fade>
+ {/if}
+ </div>
+ </PageHeader>
+ <div
+ data-view={`c_1`}
+ class={`flex flex-col h-full w-full justify-start items-center`}
+ >
+ <div
+ data-carousel-container={`c_1`}
+ class={`carousel-container flex h-full w-full`}
+ >
+ <div
+ data-carousel-item={`c_1`}
+ class={`carousel-item flex flex-col w-full justify-start items-center`}
+ >
+ <div
+ class={`flex flex-col w-full px-4 gap-4 justify-start items-center`}
+ >
+ {#if _map_point}
+ <div
+ class={`flex flex-row h-[24rem] w-full justify-center items-center round-44 overflow-hidden`}
+ >
+ <MapPointSelect
+ bind:map_point={_map_point}
+ bind:map_geoc={_map_geoc}
+ />
+ </div>
+ <div
+ class={`flex flex-col w-full pt-2 justify-center items-center`}
+ >
+ <ButtonGlyphPrimary
+ basis={{
+ label: `${$ls(`icu.add_*`, { value: `${$ls(`common.location`)}` })}`,
+ callback: async () => {
+ if (_map_geoc) await handle_inc();
+ },
+ }}
+ />
+ </div>
+ {/if}
+ </div>
+ </div>
+ <div
+ data-carousel-item={`c_1`}
+ class={`carousel-item flex flex-col w-full justify-start items-center`}
+ >
+ <div
+ class={`flex flex-col w-full px-4 gap-4 justify-start items-center`}
+ >
+ <div
+ class={`flex flex-col h-[24rem] w-full px-2 gap-4 justify-start items-center`}
+ >
+ {#if _map_geoc && _map_point}
+ <div
+ class={`flex flex-col w-full gap-1 justify-start items-start`}
+ >
+ <div
+ class={`flex flex-row w-full justify-start items-center`}
+ >
+ <p
+ class={`font-sansd text-trellisTitle text-layer-0-glyph-label uppercase`}
+ >
+ {`${$ls(`common.location`)}`}
+ </p>
+ </div>
+ <div
+ class={`flex flex-row h-12 w-full justify-start items-center border-y-line border-layer-0-surface-edge`}
+ >
+ <p
+ class={`font-sans font-[400] text-[1.1rem] text-layer-0-glyph`}
+ >
+ {`${_map_geoc.name}, ${_map_geoc.admin1_id}, ${_map_geoc.country_name}`}
+ </p>
+ </div>
+ </div>
+ <div
+ class={`flex flex-col w-full gap-1 justify-start items-start`}
+ >
+ <p
+ class={`font-sansd text-trellisTitle text-layer-0-glyph-label uppercase`}
+ >
+ {`${$ls(`common.coordinates`)}`}
+ </p>
+ <div
+ class={`flex flex-row h-12 w-full justify-start items-center border-y-line border-layer-0-surface-edge`}
+ >
+ <p
+ class={`font-sans font-[400] text-[1.1rem] text-layer-0-glyph`}
+ >
+ {`${fmt_geol_latitude(
+ _map_point.lat,
+ `d`,
+ 4,
+ )}, ${fmt_geol_longitude(
+ _map_point.lng,
+ `d`,
+ 4,
+ )}`}
+ </p>
+ </div>
+ </div>
+ <div
+ class={`flex flex-col w-full gap-1 justify-start items-start`}
+ >
+ <div
+ class={`flex flex-row w-full justify-start items-center`}
+ >
+ <p
+ class={`font-sansd text-trellisTitle text-layer-0-glyph-label uppercase`}
+ >
+ {`${$ls(`common.farm`)}/${`${$ls(`common.estate`)}`}`}
+ </p>
+ </div>
+ <div
+ class={`flex flex-row h-12 w-full justify-start items-center border-y-line border-layer-0-surface-edge`}
+ >
+ <InputElement
+ basis={{
+ id: fmt_id(`farm_estate`),
+ sync: true,
+ layer: 0,
+ classes: `h-10 placeholder:text-[1.1rem]`,
+ placeholder: `Name of farm or estate`,
+ field: {
+ charset: regex.description,
+ validate: regex.description_ch,
+ validate_keypress: true,
+ },
+ }}
+ />
+ </div>
+ </div>
+ <div
+ class={`flex flex-col w-full gap-1 justify-start items-start`}
+ >
+ <div
+ class={`flex flex-row w-full justify-start items-center`}
+ >
+ <p
+ class={`font-sansd text-trellisTitle text-layer-0-glyph-label uppercase`}
+ >
+ {`${$ls(`common.area`)} (ac.)`}
+ </p>
+ </div>
+ <div
+ class={`flex flex-row h-12 w-full justify-start items-center border-y-line border-layer-0-surface-edge`}
+ >
+ <InputElement
+ basis={{
+ id: fmt_id(`area`),
+ sync: true,
+ layer: 0,
+ classes: `h-10 placeholder:text-[1.1rem]`,
+ placeholder: `Land area`,
+ field: {
+ charset: regex.num,
+ validate: regex.num,
+ validate_keypress: true,
+ },
+ }}
+ />
+ </div>
+ </div>
+ <div
+ class={`flex flex-col w-full gap-1 justify-start items-start`}
+ >
+ <div
+ class={`flex flex-row w-full justify-start items-center`}
+ >
+ <p
+ class={`font-sansd text-trellisTitle text-layer-0-glyph-label uppercase`}
+ >
+ {`${$ls(`common.elevation`)}`}
+ </p>
+ </div>
+ <div
+ class={`flex flex-row h-12 w-full justify-start items-center border-y-line border-layer-0-surface-edge`}
+ >
+ <InputElement
+ basis={{
+ id: fmt_id(`elevation`),
+ sync: true,
+ layer: 0,
+ classes: `h-10 placeholder:text-[1.1rem]`,
+ placeholder: `Approx. elevation`,
+ field: {
+ charset: regex.num,
+ validate: regex.num,
+ validate_keypress: true,
+ },
+ }}
+ />
+ </div>
+ </div>
+ <div
+ class={`flex flex-col w-full gap-1 justify-start items-start`}
+ >
+ <div
+ class={`flex flex-row w-full justify-start items-center`}
+ >
+ <p
+ class={`font-sansd text-trellisTitle text-layer-0-glyph-label uppercase`}
+ >
+ {`${$ls(`common.climate`)}`}
+ </p>
+ </div>
+ <div
+ class={`flex flex-row h-12 w-full justify-start items-center border-y-line border-layer-0-surface-edge`}
+ >
+ <InputElement
+ basis={{
+ id: fmt_id(`climate`),
+ sync: true,
+ layer: 0,
+ classes: `h-10 placeholder:text-[1.1rem]`,
+ placeholder: `Local climate`,
+ field: {
+ charset: regex.description,
+ validate: regex.description_ch,
+ validate_keypress: true,
+ },
+ }}
+ />
+ </div>
+ </div>
+ <div
+ class={`flex flex-row w-full pt-2 justify-center items-center`}
+ >
+ <ButtonGlyphPrimary
+ basis={{
+ label: `${$ls(`icu.add_*`, { value: `${$ls(`common.location`)}` })}`,
+ callback: async () => {
+ if (_map_geoc) await handle_inc();
+ },
+ }}
+ />
+ </div>
+ {/if}
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</LayoutView>
diff --git a/src/routes/(app)/settings/+page.svelte b/src/routes/(app)/settings/+page.svelte
@@ -7,7 +7,8 @@
LayoutTrellis,
LayoutView,
ls,
- Nav,
+ NavToolbar,
+ PageHeader,
route,
Trellis,
} from "@radroots/svelte-lib";
@@ -15,6 +16,12 @@
</script>
<LayoutView>
+ <NavToolbar />
+ <PageHeader
+ basis={{
+ label: `${$ls(`common.settings`)}`,
+ }}
+ />
<LayoutTrellis>
<Trellis
basis={{
@@ -414,16 +421,3 @@
/>
</LayoutTrellis>
</LayoutView>
-<Nav
- basis={{
- prev: {
- label: `${$ls(`common.home`)}`,
- route: `/`,
- },
- title: {
- label: {
- value: `${$ls(`common.settings`)}`,
- },
- },
- }}
-/>
diff --git a/tailwind.config.ts b/tailwind.config.ts
@@ -116,6 +116,7 @@ const config: Config = {
of: [`Outfit`]
},
fontSize: {
+ guide: [`1.2rem`, { lineHeight: `1.2rem` }],
line_label: [`1.3rem`, { lineHeight: `1.3rem` }],
trellisTitle: [`0.8rem`, { lineHeight: `1rem`, fontWeight: 300 }],
trellisTitleNote: [`0.76rem`, { lineHeight: `1rem`, fontWeight: 200 }],