refactor zo zod and felte

This commit is contained in:
Christian Beutel
2024-12-30 19:52:44 +01:00
parent 75c94a3ce4
commit 871481a84e
45 changed files with 659 additions and 1040 deletions

View File

@@ -1,42 +1,58 @@
<script lang="ts">
import { Waypoint, waypointSchema } from "$lib/models/waypoint";
import { createEventDispatcher } from "svelte";
import { WaypointCreateSchema } from "$lib/models/api/waypoint_schema";
import { convertDMSToDD } from "$lib/models/gpx/utils";
import { show_toast } from "$lib/stores/toast_store";
import { waypoint } from "$lib/stores/waypoint_store";
import { cloneDeep } from "$lib/util/deep_util";
import { icons } from "$lib/util/icon_util";
import EXIF from "$lib/vendor/exif-js/exif";
import { createForm } from "$lib/vendor/svelte-form-lib/index";
import { util } from "$lib/vendor/svelte-form-lib/util";
import { validator } from "@felte/validator-zod";
import { createForm } from "felte";
import { _ } from "svelte-i18n";
import { z } from "zod";
import Combobox from "../base/combobox.svelte";
import Modal from "../base/modal.svelte";
import TextField from "../base/text_field.svelte";
import Textarea from "../base/textarea.svelte";
import PhotoPicker from "../trail/photo_picker.svelte";
import { show_toast } from "$lib/stores/toast_store";
import { convertDMSToDD } from "$lib/models/gpx/utils";
export let openModal: (() => void) | undefined = undefined;
export let closeModal: (() => void) | undefined = undefined;
const dispatch = createEventDispatcher();
const { form, errors, handleChange, handleSubmit } = createForm<Waypoint>({
const ClientWaypointCreateSchema = WaypointCreateSchema.extend({
_photos: z.array(z.instanceof(File)).optional(),
});
const { form, errors, data, setFields } = createForm<
z.infer<typeof ClientWaypointCreateSchema>
>({
initialValues: $waypoint,
validationSchema: waypointSchema,
onSubmit: async (submittedWaypoint) => {
dispatch("save", submittedWaypoint);
extend: validator({ schema: ClientWaypointCreateSchema }),
onSubmit: async (form) => {
dispatch("save", form);
closeModal!();
},
transform: (values: unknown) => {
const v = values as any;
return {
...v,
lat: parseFloat(v.lat),
lon: parseFloat(v.lon),
};
},
});
$: form.set(util.cloneDeep($waypoint));
$: setFields(cloneDeep($waypoint));
$: filteredIcons =
($form.icon?.length ?? 0) > 2
($data.icon?.length ?? 0) > 2
? icons
.filter((i) => i.includes($form.icon ?? ""))
.filter((i) => i.includes($data.icon ?? ""))
.map((i) => ({ text: i, value: i, icon: i }))
: [];
@@ -48,8 +64,8 @@
const lonDir = EXIF.getTag(p, "GPSLongitudeRef");
if (lat && lon) {
$form.lat = convertDMSToDD(lat, latDir);
$form.lon = convertDMSToDD(lon, lonDir);
setFields("lat", convertDMSToDD(lat, latDir));
setFields("lon", convertDMSToDD(lon, lonDir));
} else {
show_toast({
text: "No GPS data in image",
@@ -63,7 +79,7 @@
<Modal
id="waypoint-modal"
title={$form.id ? $_("edit-waypoint") : $_("add-waypoint")}
title={$data.id ? $_("edit-waypoint") : $_("add-waypoint")}
let:openModal
bind:openModal
bind:closeModal
@@ -73,50 +89,31 @@
id="waypoint-form"
slot="content"
class="modal-content space-y-4"
on:submit={handleSubmit}
use:form
>
<div class="flex gap-4">
<div class="basis-2/3">
<TextField
name="name"
label={$_("name")}
bind:value={$form.name}
error={$errors.name}
on:change={handleChange}
<TextField name="name" label={$_("name")} error={$errors.name}
></TextField>
</div>
<Combobox
name="icon"
bind:value={$form.icon}
icon={$form.icon}
icon={$data.icon}
items={filteredIcons}
label={$_("icon")}
on:change={handleChange}
></Combobox>
</div>
<Textarea
name="description"
label={$_("description")}
bind:value={$form.description}
error={$errors.description}
on:change={handleChange}
></Textarea>
<div class="flex gap-4">
<TextField
name="lat"
label={$_("latitude")}
bind:value={$form.lat}
error={$errors.lat}
on:change={handleChange}
<TextField name="lat" label={$_("latitude")} error={$errors.lat}
></TextField>
<TextField
name="lon"
label={$_("longitude")}
bind:value={$form.lon}
error={$errors.lat}
on:change={handleChange}
<TextField name="lon" label={$_("longitude")} error={$errors.lat}
></TextField>
</div>
<div>
@@ -125,10 +122,10 @@
</label>
<PhotoPicker
id="waypoint-photo-input"
parent={$form}
parent={$data}
on:exif={(e) => getCoordinatesFromPhoto(e.detail)}
bind:photos={$form.photos}
bind:photoFiles={$form._photos}
bind:photos={$data.photos}
bind:photoFiles={$data._photos}
showThumbnailControls={false}
showExifControls={true}
></PhotoPicker>