From a85e7a3f108e569309c51d23c4a53041032b7939 Mon Sep 17 00:00:00 2001
From: Sven Verweij <37927107+SvenVw@users.noreply.github.com>
Date: Tue, 1 Apr 2025 14:39:22 +0200
Subject: [PATCH 01/33] Setup first draft of page for adding new field
---
fdm-app/app/components/custom/field/form.tsx | 123 +++++++++
.../app/components/custom/field/schema.tsx | 16 ++
...farm.$b_id_farm.$calendar.field._index.tsx | 22 +-
.../farm.$b_id_farm.$calendar.field.new.tsx | 255 ++++++++++++++++++
4 files changed, 401 insertions(+), 15 deletions(-)
create mode 100644 fdm-app/app/components/custom/field/form.tsx
create mode 100644 fdm-app/app/components/custom/field/schema.tsx
create mode 100644 fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
diff --git a/fdm-app/app/components/custom/field/form.tsx b/fdm-app/app/components/custom/field/form.tsx
new file mode 100644
index 000000000..6de28be0f
--- /dev/null
+++ b/fdm-app/app/components/custom/field/form.tsx
@@ -0,0 +1,123 @@
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+} from "@/components/ui/dialog"
+import { Button } from "@/components/ui/button"
+import { RemixFormProvider, useRemixForm } from "remix-hook-form"
+import { useEffect } from "react"
+import {
+ FormControl,
+ FormDescription,
+ FormField,
+ FormItem,
+ FormLabel,
+ FormMessage,
+} from "@/components/ui/form"
+import { Input } from "@/components/ui/input"
+import type { z } from "zod"
+import { zodResolver } from "@hookform/resolvers/zod"
+import { Form } from "react-router"
+import { FormSchema } from "./schema"
+
+interface FieldDetailsDialogProps {
+ open: boolean
+ setOpen: (value: boolean) => void
+ field: any
+ onFieldAdded: () => void
+}
+
+export default function FieldDetailsDialog({
+ open,
+ setOpen,
+ field,
+ onFieldAdded,
+}: FieldDetailsDialogProps) {
+ const form = useRemixForm>({
+ mode: "onTouched",
+ resolver: zodResolver(FormSchema),
+ defaultValues: {
+ b_name: `Perceel`,
+ b_area: field.properties.b_area,
+ },
+ })
+
+ useEffect(() => {
+ form.reset({
+ b_name: `Perceel`,
+ b_area: field.properties.b_area,
+ })
+ }, [form, field])
+
+ const handleSubmit = async (values: any) => {
+ //todo: add the field to database with b_id_source, b_geometry and other props
+ console.log(values, field)
+ }
+
+ return (
+
+ )
+}
diff --git a/fdm-app/app/components/custom/field/schema.tsx b/fdm-app/app/components/custom/field/schema.tsx
new file mode 100644
index 000000000..bf428a7b0
--- /dev/null
+++ b/fdm-app/app/components/custom/field/schema.tsx
@@ -0,0 +1,16 @@
+import { z } from "zod"
+
+const FormSchema = z.object({
+ b_name: z
+ .string({
+ required_error: "Naam van perceel is verplicht",
+ })
+ .min(3, {
+ message: "Naam van perceel moet minimaal 3 karakters bevatten",
+ }),
+ b_area: z.coerce.number({
+ required_error: "Oppervlakte van perceel is verplicht",
+ }),
+})
+
+export { FormSchema }
\ No newline at end of file
diff --git a/fdm-app/app/routes/farm.$b_id_farm.$calendar.field._index.tsx b/fdm-app/app/routes/farm.$b_id_farm.$calendar.field._index.tsx
index 8359a82e3..218995542 100644
--- a/fdm-app/app/routes/farm.$b_id_farm.$calendar.field._index.tsx
+++ b/fdm-app/app/routes/farm.$b_id_farm.$calendar.field._index.tsx
@@ -150,17 +150,11 @@ export default function FarmFieldIndex() {
Het lijkt erop dat je nog geen perceel hebt
:(
-
- Het aanmaken van een perceel is binnenkort
- beschikbaar.
-
-
+
+
+
{/*
*/}
@@ -230,12 +224,10 @@ export default function FarmFieldIndex() {
Of maak een nieuw perceel aan:
-
-
+
+
+
+
diff --git a/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx b/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
new file mode 100644
index 000000000..02ca785d0
--- /dev/null
+++ b/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
@@ -0,0 +1,255 @@
+import { ZOOM_LEVEL_FIELDS } from "@/components/custom/atlas/atlas"
+import { generateFeatureClass } from "@/components/custom/atlas/atlas-functions"
+import {
+ getMapboxStyle,
+ getMapboxToken,
+} from "@/components/custom/atlas/atlas-mapbox"
+import {
+ FieldsPanelHover,
+ FieldsPanelSelection,
+ FieldsPanelZoom,
+} from "@/components/custom/atlas/atlas-panels"
+import {
+ FieldsSourceAvailable,
+ FieldsSourceSelected,
+} from "@/components/custom/atlas/atlas-sources"
+import { getFieldsStyle } from "@/components/custom/atlas/atlas-styles"
+import { getViewState } from "@/components/custom/atlas/atlas-viewstate"
+import {
+ Breadcrumb,
+ BreadcrumbItem,
+ BreadcrumbLink,
+ BreadcrumbList,
+ BreadcrumbSeparator,
+} from "@/components/ui/breadcrumb"
+import { Separator } from "@/components/ui/separator"
+import { SidebarInset, SidebarTrigger } from "@/components/ui/sidebar"
+import { Skeleton } from "@/components/ui/skeleton"
+import { getSession } from "@/lib/auth.server"
+import { getCalendar, getTimeframe } from "@/lib/calendar"
+import { handleActionError, handleLoaderError } from "@/lib/error"
+import { useCalendarStore } from "@/store/calendar"
+import { addCultivation, addField, getFarm, getFarms } from "@svenvw/fdm-core"
+import { centroid } from "@turf/centroid"
+import { useState } from "react"
+import {
+ GeolocateControl,
+ Layer,
+ Map as MapGL,
+ NavigationControl,
+} from "react-map-gl"
+import {
+ type ActionFunctionArgs,
+ type LoaderFunctionArgs,
+ type MetaFunction,
+ data,
+ useLoaderData,
+} from "react-router"
+import { redirectWithSuccess } from "remix-toast"
+import { ClientOnly } from "remix-utils/client-only"
+import { fdm } from "../lib/fdm.server"
+import FieldDetailsDialog from "@/components/custom/field/form"
+import { FarmHeader } from "@/components/custom/farm/farm-header"
+
+// Meta
+export const meta: MetaFunction = () => {
+ return [
+ { title: "FDM App" },
+ { name: "description", content: "Welcome to FDM!" },
+ ]
+}
+
+/**
+ * Retrieves farm details and map configurations for rendering the farm map.
+ *
+ * This loader function extracts the farm ID from route parameters, validates its presence, and uses the current session to fetch the corresponding farm details. It then retrieves the Mapbox token and style configuration, and returns these along with the farm's display name and a URL for available fields. Any errors encountered during processing are transformed using {@link handleLoaderError}.
+ *
+ * @throws {Response} When the farm ID is missing, the specified farm is not found, or another error occurs during data retrieval.
+ *
+ * @returns An object containing the farm name, Mapbox token, Mapbox style, and the URL for available fields.
+ */
+export async function loader({ request, params }: LoaderFunctionArgs) {
+ try {
+ // Get the Id and name of the farm
+ const b_id_farm = params.b_id_farm
+ if (!b_id_farm) {
+ throw data("Farm ID is required", {
+ status: 400,
+ statusText: "Farm ID is required",
+ })
+ }
+
+ // Get the session
+ const session = await getSession(request)
+
+ // Get a list of possible farms of the user
+ const farms = await getFarms(fdm, session.principal_id)
+ const farmOptions = farms.map((farm) => {
+ if (!farm?.b_id_farm || !farm?.b_name_farm) {
+ throw new Error("Invalid farm data structure")
+ }
+ return {
+ b_id_farm: farm.b_id_farm,
+ b_name_farm: farm.b_name_farm,
+ }
+ })
+
+ const farm = await getFarm(fdm, session.principal_id, b_id_farm)
+
+ if (!farm) {
+ throw data("Farm not found", {
+ status: 404,
+ statusText: "Farm not found",
+ })
+ }
+
+ // Get the Mapbox token and style
+ const mapboxToken = getMapboxToken()
+ const mapboxStyle = getMapboxStyle()
+
+ return {
+ farmOptions: farmOptions,
+ b_id_farm: b_id_farm,
+ b_name_farm: farm.b_name_farm,
+ mapboxToken: mapboxToken,
+ mapboxStyle: mapboxStyle,
+ fieldsAvailableUrl: process.env.AVAILABLE_FIELDS_URL,
+ }
+ } catch (error) {
+ throw handleLoaderError(error)
+ }
+}
+
+// Main
+export default function Index() {
+ const loaderData = useLoaderData
()
+ const calendar = useCalendarStore((state) => state.calendar)
+
+ const fieldsAvailableId = "fieldsAvailable"
+ // const fields = loaderData.savedFields
+ const viewState = getViewState(null)
+ const fieldsAvailableStyle = getFieldsStyle(fieldsAvailableId)
+
+ const fieldsSelectedId = "fieldsSelected"
+ const fieldsSelectedStyle = getFieldsStyle(fieldsSelectedId)
+
+ // Set selected fields
+ const [selectedFieldsData, setSelectedFieldsData] = useState(
+ generateFeatureClass(),
+ )
+ const [open, setOpen] = useState(false)
+ const [selectedField, setSelectedField] = useState(null)
+
+ const handleSelectField = (feature: any) => {
+ setSelectedField(feature)
+ setOpen(true)
+ }
+ const handleFieldAdded = () => {
+ setOpen(false)
+ }
+ return (
+
+
+
+
+
+
+
+ Nieuw perceel
+
+
+ Zoom in en voeg een nieuw perceel toe
+
+
+
+
+
+
+
+ }
+ >
+ {() => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+
+
+
+ {selectedField && (
+
+ )}
+
+ )
+}
+
+export async function action({ request, params }: ActionFunctionArgs) {
+ //todo: implement add field
+ throw new Error("Not implemented")
+}
From f30f2aaa07f369c6565626f3f17354285889cc05 Mon Sep 17 00:00:00 2001
From: Sven Verweij <37927107+SvenVw@users.noreply.github.com>
Date: Tue, 1 Apr 2025 15:34:27 +0200
Subject: [PATCH 02/33] Remove not needing lines
---
fdm-app/app/components/custom/atlas/atlas-sources.tsx | 2 --
1 file changed, 2 deletions(-)
diff --git a/fdm-app/app/components/custom/atlas/atlas-sources.tsx b/fdm-app/app/components/custom/atlas/atlas-sources.tsx
index fdefd63c1..ad8d7984b 100644
--- a/fdm-app/app/components/custom/atlas/atlas-sources.tsx
+++ b/fdm-app/app/components/custom/atlas/atlas-sources.tsx
@@ -4,7 +4,6 @@ import throttle from "lodash.throttle"
import { type Dispatch, type SetStateAction, useEffect, useState } from "react"
import { Source, useMap } from "react-map-gl"
import { generateFeatureClass } from "./atlas-functions"
-import type { fieldsAvailableUrlType } from "./atlas.d"
export function FieldsSourceNotClickable({
id,
@@ -37,7 +36,6 @@ export function FieldsSourceSelected({
useEffect(() => {
function clickOnMap(evt) {
- console.log("jh")
if (!map) return
const features = map.queryRenderedFeatures(evt.point, {
From 3e667ce34c1e738848b844c0f7314c46f7b9bc06 Mon Sep 17 00:00:00 2001
From: Sven Verweij <37927107+SvenVw@users.noreply.github.com>
Date: Tue, 1 Apr 2025 15:34:34 +0200
Subject: [PATCH 03/33] Fix layers
---
.../components/custom/atlas/atlas-panels.tsx | 2 +-
.../farm.$b_id_farm.$calendar.field.new.tsx | 79 +++++++++++++++----
2 files changed, 64 insertions(+), 17 deletions(-)
diff --git a/fdm-app/app/components/custom/atlas/atlas-panels.tsx b/fdm-app/app/components/custom/atlas/atlas-panels.tsx
index 950026f2f..140f41441 100644
--- a/fdm-app/app/components/custom/atlas/atlas-panels.tsx
+++ b/fdm-app/app/components/custom/atlas/atlas-panels.tsx
@@ -15,7 +15,7 @@ import throttle from "lodash.throttle"
import { Check, Info } from "lucide-react"
import { useEffect, useState } from "react"
import { useMap } from "react-map-gl"
-import type { MapBoxZoomEvent, MapEvent, MapMouseEvent } from "react-map-gl"
+import type { MapBoxZoomEvent, MapMouseEvent } from "react-map-gl"
import { useFetcher } from "react-router"
export function FieldsPanelHover({
diff --git a/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx b/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
index 02ca785d0..dbb543c9e 100644
--- a/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
+++ b/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
@@ -11,6 +11,7 @@ import {
} from "@/components/custom/atlas/atlas-panels"
import {
FieldsSourceAvailable,
+ FieldsSourceNotClickable,
FieldsSourceSelected,
} from "@/components/custom/atlas/atlas-sources"
import { getFieldsStyle } from "@/components/custom/atlas/atlas-styles"
@@ -29,7 +30,13 @@ import { getSession } from "@/lib/auth.server"
import { getCalendar, getTimeframe } from "@/lib/calendar"
import { handleActionError, handleLoaderError } from "@/lib/error"
import { useCalendarStore } from "@/store/calendar"
-import { addCultivation, addField, getFarm, getFarms } from "@svenvw/fdm-core"
+import {
+ addCultivation,
+ addField,
+ getFarm,
+ getFarms,
+ getFields,
+} from "@svenvw/fdm-core"
import { centroid } from "@turf/centroid"
import { useState } from "react"
import {
@@ -50,6 +57,7 @@ import { ClientOnly } from "remix-utils/client-only"
import { fdm } from "../lib/fdm.server"
import FieldDetailsDialog from "@/components/custom/field/form"
import { FarmHeader } from "@/components/custom/farm/farm-header"
+import { FeatureCollection } from "geojson"
// Meta
export const meta: MetaFunction = () => {
@@ -82,6 +90,9 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
// Get the session
const session = await getSession(request)
+ // Get timeframe from calendar store
+ const timeframe = getTimeframe(params)
+
// Get a list of possible farms of the user
const farms = await getFarms(fdm, session.principal_id)
const farmOptions = farms.map((farm) => {
@@ -103,6 +114,33 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
})
}
+ // Get the fields of the farm
+ const fields = await getFields(
+ fdm,
+ session.principal_id,
+ b_id_farm,
+ timeframe,
+ )
+ const features = fields.map((field) => {
+ const feature = {
+ type: "Feature",
+ properties: {
+ b_id: field.b_id,
+ b_name: field.b_name,
+ b_area: Math.round(field.b_area * 10) / 10,
+ b_lu_name: field.b_lu_name,
+ b_id_source: field.b_id_source,
+ },
+ geometry: field.b_geometry,
+ }
+ return feature
+ })
+
+ const featureCollection: FeatureCollection = {
+ type: "FeatureCollection",
+ features: features,
+ }
+
// Get the Mapbox token and style
const mapboxToken = getMapboxToken()
const mapboxStyle = getMapboxStyle()
@@ -111,6 +149,7 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
farmOptions: farmOptions,
b_id_farm: b_id_farm,
b_name_farm: farm.b_name_farm,
+ featureCollection: featureCollection,
mapboxToken: mapboxToken,
mapboxStyle: mapboxStyle,
fieldsAvailableUrl: process.env.AVAILABLE_FIELDS_URL,
@@ -125,13 +164,16 @@ export default function Index() {
const loaderData = useLoaderData()
const calendar = useCalendarStore((state) => state.calendar)
+ const fieldsSavedId = "fieldsSaved"
+ const fieldsSaved = loaderData.featureCollection
+ const viewState = getViewState(fieldsSaved)
+ const fieldsSavedStyle = getFieldsStyle(fieldsSavedId)
+
const fieldsAvailableId = "fieldsAvailable"
- // const fields = loaderData.savedFields
- const viewState = getViewState(null)
const fieldsAvailableStyle = getFieldsStyle(fieldsAvailableId)
- const fieldsSelectedId = "fieldsSelected"
- const fieldsSelectedStyle = getFieldsStyle(fieldsSelectedId)
+ // const fieldsSelectedId = "fieldsSelected"
+ // const fieldsSelectedStyle = getFieldsStyle(fieldsSelectedId)
// Set selected fields
const [selectedFieldsData, setSelectedFieldsData] = useState(
@@ -141,8 +183,9 @@ export default function Index() {
const [selectedField, setSelectedField] = useState(null)
const handleSelectField = (feature: any) => {
- setSelectedField(feature)
- setOpen(true)
+ // setSelectedField(feature)
+ // setOpen(true)
+ console.log("hoi")
}
const handleFieldAdded = () => {
setOpen(false)
@@ -191,7 +234,7 @@ export default function Index() {
mapboxAccessToken={loaderData.mapboxToken}
interactiveLayerIds={[
fieldsAvailableId,
- fieldsSelectedId,
+ fieldsSavedId,
]}
>
@@ -206,31 +249,35 @@ export default function Index() {
-
+
+
+
+ {/*
-
+ */}
-
-
+ /> */}
)}
From 2036e0162807a5b04d9729bbbd7d2b0791d18d5d Mon Sep 17 00:00:00 2001
From: Sven Verweij <37927107+SvenVw@users.noreply.github.com>
Date: Tue, 1 Apr 2025 16:16:37 +0200
Subject: [PATCH 04/33] Fix type
---
fdm-app/app/components/custom/atlas/atlas-sources.tsx | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/fdm-app/app/components/custom/atlas/atlas-sources.tsx b/fdm-app/app/components/custom/atlas/atlas-sources.tsx
index ad8d7984b..17846d3c3 100644
--- a/fdm-app/app/components/custom/atlas/atlas-sources.tsx
+++ b/fdm-app/app/components/custom/atlas/atlas-sources.tsx
@@ -4,6 +4,7 @@ import throttle from "lodash.throttle"
import { type Dispatch, type SetStateAction, useEffect, useState } from "react"
import { Source, useMap } from "react-map-gl"
import { generateFeatureClass } from "./atlas-functions"
+import type { FieldsAvailableUrlType } from "./atlas.d"
export function FieldsSourceNotClickable({
id,
@@ -106,7 +107,7 @@ export function FieldsSourceAvailable({
children,
}: {
id: string
- url: fieldsAvailableUrlType
+ url: FieldsAvailableUrlType
zoomLevelFields: number
children: JSX.Element
}) {
From aac6434f7d3cdb7ec283d7a2ee1a5c17669781f4 Mon Sep 17 00:00:00 2001
From: Sven Verweij <37927107+SvenVw@users.noreply.github.com>
Date: Tue, 1 Apr 2025 16:16:49 +0200
Subject: [PATCH 05/33] Open dialog on click
---
.../farm.$b_id_farm.$calendar.field.new.tsx | 42 ++++++-------------
1 file changed, 13 insertions(+), 29 deletions(-)
diff --git a/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx b/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
index dbb543c9e..9b155ba97 100644
--- a/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
+++ b/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
@@ -172,24 +172,14 @@ export default function Index() {
const fieldsAvailableId = "fieldsAvailable"
const fieldsAvailableStyle = getFieldsStyle(fieldsAvailableId)
- // const fieldsSelectedId = "fieldsSelected"
- // const fieldsSelectedStyle = getFieldsStyle(fieldsSelectedId)
-
- // Set selected fields
- const [selectedFieldsData, setSelectedFieldsData] = useState(
- generateFeatureClass(),
- )
const [open, setOpen] = useState(false)
const [selectedField, setSelectedField] = useState(null)
const handleSelectField = (feature: any) => {
- // setSelectedField(feature)
- // setOpen(true)
- console.log("hoi")
- }
- const handleFieldAdded = () => {
- setOpen(false)
+ setSelectedField(feature)
+ setOpen(true)
}
+
return (
{
+ if (!evt.features) return
+ const features = evt.features.filter(
+ (f) => f.source === fieldsAvailableId,
+ )
+ if (features.length > 0) {
+ handleSelectField(features[0])
+ }
+ }}
>
@@ -244,7 +243,6 @@ export default function Index() {
id={fieldsAvailableId}
url={loaderData.fieldsAvailableUrl}
zoomLevelFields={ZOOM_LEVEL_FIELDS}
- onFeatureSelect={handleSelectField}
>
@@ -256,15 +254,6 @@ export default function Index() {
- {/*
-
- */}
-
- {/* */}
)}
@@ -288,8 +273,7 @@ export default function Index() {
)}
From ecf55333a604fd433aa001f72d3978e0415540e9 Mon Sep 17 00:00:00 2001
From: Sven Verweij <37927107+SvenVw@users.noreply.github.com>
Date: Wed, 2 Apr 2025 10:51:45 +0200
Subject: [PATCH 06/33] Improve accessibility of combobox
---
fdm-app/app/components/custom/combobox.tsx | 23 +++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/fdm-app/app/components/custom/combobox.tsx b/fdm-app/app/components/custom/combobox.tsx
index e7b785297..95f0bbb74 100644
--- a/fdm-app/app/components/custom/combobox.tsx
+++ b/fdm-app/app/components/custom/combobox.tsx
@@ -1,5 +1,4 @@
-import { type ReactNode, useMemo, useState } from "react"
-
+import { type ReactNode, useMemo, useState, useRef, useEffect } from "react"
import { Button } from "@/components/ui/button"
import {
Command,
@@ -48,6 +47,7 @@ export function Combobox({
disabled,
}: ComboboxProps) {
const [open, setOpen] = useState(false)
+ const listboxRef = useRef(null)
/** Map of option values to their labels for efficient lookup */
const optionsMap = useMemo(
@@ -67,6 +67,15 @@ export function Combobox({
[defaultValue, optionsMap],
)
+ useEffect(() => {
+ if (open) {
+ const activeElement = listboxRef.current?.querySelector('[data-active]') as HTMLElement | null
+ if (activeElement) {
+ activeElement.focus()
+ }
+ }
+ }, [open]);
+
return (
(
- {label}
+ {label}
+
+
+
)}
/>
diff --git a/fdm-app/app/components/custom/field/form.tsx b/fdm-app/app/components/custom/field/form.tsx
index 6de28be0f..cd0ac3646 100644
--- a/fdm-app/app/components/custom/field/form.tsx
+++ b/fdm-app/app/components/custom/field/form.tsx
@@ -22,52 +22,55 @@ import type { z } from "zod"
import { zodResolver } from "@hookform/resolvers/zod"
import { Form } from "react-router"
import { FormSchema } from "./schema"
+import { Combobox } from "../combobox"
interface FieldDetailsDialogProps {
open: boolean
setOpen: (value: boolean) => void
field: any
- onFieldAdded: () => void
+ cultivationOptions: any
+ fieldNameDefault: string
+ b_source: string
+ b_geometry: string
}
export default function FieldDetailsDialog({
open,
setOpen,
field,
- onFieldAdded,
+ cultivationOptions,
+ fieldNameDefault,
}: FieldDetailsDialogProps) {
+ const b_geojson = JSON.stringify(field.geometry)
+ const b_lu_catalogue = `nl_${field.properties.b_lu_catalogue}`
+
const form = useRemixForm>({
mode: "onTouched",
resolver: zodResolver(FormSchema),
defaultValues: {
- b_name: `Perceel`,
- b_area: field.properties.b_area,
+ b_name: fieldNameDefault,
+ b_lu_catalogue: b_lu_catalogue,
+ b_id_source: field.properties.b_id_source,
+ b_geometry: b_geojson,
},
})
useEffect(() => {
form.reset({
- b_name: `Perceel`,
- b_area: field.properties.b_area,
+ b_name: fieldNameDefault,
+ b_lu_catalogue: b_lu_catalogue,
+ b_id_source: field.properties.b_id_source,
+ b_geometry: b_geojson,
})
- }, [form, field])
-
- const handleSubmit = async (values: any) => {
- //todo: add the field to database with b_id_source, b_geometry and other props
- console.log(values, field)
- }
+ }, [form, field, fieldNameDefault, b_lu_catalogue, b_geojson])
return (
-
+
diff --git a/fdm-app/app/components/custom/field/schema.tsx b/fdm-app/app/components/custom/field/schema.tsx
index bf428a7b0..b54523295 100644
--- a/fdm-app/app/components/custom/field/schema.tsx
+++ b/fdm-app/app/components/custom/field/schema.tsx
@@ -8,9 +8,15 @@ const FormSchema = z.object({
.min(3, {
message: "Naam van perceel moet minimaal 3 karakters bevatten",
}),
- b_area: z.coerce.number({
- required_error: "Oppervlakte van perceel is verplicht",
+ b_lu_catalogue: z.string({
+ required_error: "Hoofdgewas is verplicht",
+ }),
+ b_id_source: z.string({
+ required_error: "Bron is verplicht",
+ }),
+ b_geometry: z.string({
+ required_error: "Geometrie is verplicht",
}),
})
-export { FormSchema }
\ No newline at end of file
+export { FormSchema }
diff --git a/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx b/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
index 9b155ba97..b2a3b1b69 100644
--- a/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
+++ b/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
@@ -33,6 +33,8 @@ import { useCalendarStore } from "@/store/calendar"
import {
addCultivation,
addField,
+ addSoilAnalysis,
+ getCultivationsFromCatalogue,
getFarm,
getFarms,
getFields,
@@ -52,12 +54,14 @@ import {
data,
useLoaderData,
} from "react-router"
-import { redirectWithSuccess } from "remix-toast"
+import { dataWithError, redirectWithSuccess } from "remix-toast"
import { ClientOnly } from "remix-utils/client-only"
import { fdm } from "../lib/fdm.server"
import FieldDetailsDialog from "@/components/custom/field/form"
import { FarmHeader } from "@/components/custom/farm/farm-header"
-import { FeatureCollection } from "geojson"
+import type { FeatureCollection, Polygon } from "geojson"
+import { extractFormValuesFromRequest } from "@/lib/form"
+import { FormSchema } from "@/components/custom/field/schema"
// Meta
export const meta: MetaFunction = () => {
@@ -141,6 +145,26 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
features: features,
}
+ // Get the available cultivations
+ let cultivationOptions = []
+ const cultivationsCatalogue = await getCultivationsFromCatalogue(
+ fdm,
+ session.principal_id,
+ b_id_farm,
+ )
+ cultivationOptions = cultivationsCatalogue
+ .filter(
+ (cultivation) =>
+ cultivation?.b_lu_catalogue && cultivation?.b_lu_name,
+ )
+ .map((cultivation) => ({
+ value: cultivation.b_lu_catalogue,
+ label: `${cultivation.b_lu_name} (${cultivation.b_lu_catalogue.split("_")[1]})`,
+ }))
+
+ // Create default field name
+ const fieldNameDefault = `Perceel ${fields.length + 1}`
+
// Get the Mapbox token and style
const mapboxToken = getMapboxToken()
const mapboxStyle = getMapboxStyle()
@@ -150,6 +174,8 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
b_id_farm: b_id_farm,
b_name_farm: farm.b_name_farm,
featureCollection: featureCollection,
+ fieldNameDefault: fieldNameDefault,
+ cultivationOptions: cultivationOptions,
mapboxToken: mapboxToken,
mapboxStyle: mapboxStyle,
fieldsAvailableUrl: process.env.AVAILABLE_FIELDS_URL,
@@ -273,7 +299,9 @@ export default function Index() {
)}
@@ -281,6 +309,136 @@ export default function Index() {
}
export async function action({ request, params }: ActionFunctionArgs) {
- //todo: implement add field
- throw new Error("Not implemented")
+ console.log("hoi")
+ // Get the farm id
+ const b_id_farm = params.b_id_farm
+ if (!b_id_farm) {
+ throw data("Farm ID is required", {
+ status: 400,
+ statusText: "Farm ID is required",
+ })
+ }
+
+ try {
+ // Get the session
+ const session = await getSession(request)
+
+ // Get the timeframe
+ const timeframe = getTimeframe(params)
+
+ // Get from values
+ const formValues = await extractFormValuesFromRequest(
+ request,
+ FormSchema,
+ )
+ console.log(formValues)
+
+ // Check if cultivation is available
+ let cultivationOptions = []
+ const cultivationsCatalogue = await getCultivationsFromCatalogue(
+ fdm,
+ session.principal_id,
+ b_id_farm,
+ )
+ cultivationOptions = cultivationsCatalogue
+ .filter(
+ (cultivation) =>
+ cultivation?.b_lu_catalogue && cultivation?.b_lu_name,
+ )
+ .map((cultivation) => {
+ return cultivation.b_lu_catalogue
+ })
+ if (!cultivationOptions.includes(formValues.b_lu_catalogue)) {
+ return dataWithError(
+ `Cultivation ${formValues.b_lu_catalogue} is not available`,
+ "Gewas is onbekend. Kies een gewas uit de lijst",
+ )
+ }
+
+ const b_name = formValues.b_name
+ const b_id_source = formValues.b_id_source
+ const b_lu_catalogue = formValues.b_lu_catalogue
+ const b_geometry = formValues.b_geometry as Polygon
+ const currentYear = new Date().getFullYear()
+ const defaultDate = timeframe.start
+ ? timeframe.start
+ : `${currentYear}-01-01`
+ const b_start = defaultDate
+ const b_lu_start = defaultDate
+ const b_lu_end = undefined
+ const b_end = undefined
+ const b_acquiring_method = "unknown"
+
+ const b_id = await addField(
+ fdm,
+ session.principal_id,
+ b_id_farm,
+ b_name,
+ b_id_source,
+ b_geometry,
+ b_start,
+ b_acquiring_method,
+ b_end,
+ )
+ await addCultivation(
+ fdm,
+ session.principal_id,
+ b_lu_catalogue,
+ b_id,
+ b_lu_start,
+ b_lu_end,
+ )
+
+ if (process.env.NMI_API_KEY) {
+ const fieldCentroid = centroid(formValues.geometry)
+ const a_lon = fieldCentroid.geometry.coordinates[0]
+ const a_lat = fieldCentroid.geometry.coordinates[1]
+
+ const responseApi = await fetch(
+ `https://api.nmi-agro.nl/estimates?${new URLSearchParams({
+ a_lat: a_lat.toString(),
+ a_lon: a_lon.toString(),
+ })}`,
+ {
+ method: "GET",
+ headers: {
+ Authorization: `Bearer ${process.env.NMI_API_KEY}`,
+ },
+ },
+ )
+
+ if (!responseApi.ok) {
+ throw data(responseApi.statusText, {
+ status: responseApi.status,
+ statusText: responseApi.statusText,
+ })
+ }
+
+ const result = await responseApi.json()
+ const response = result.data
+
+ await addSoilAnalysis(
+ fdm,
+ session.principal_id,
+ undefined,
+ "NMI",
+ b_id,
+ 0.3,
+ undefined,
+ {
+ a_p_al: response.a_p_al,
+ a_p_cc: response.a_p_cc,
+ a_som_loi: response.a_som_loi,
+ b_soiltype_agr: response.b_soiltype_agr,
+ b_gwl_class: response.b_gwl_class,
+ },
+ )
+ }
+
+ return redirectWithSuccess("./", {
+ message: `${b_name} is toegevoegd! 🎉`,
+ })
+ } catch (error) {
+ throw handleActionError(error)
+ }
}
From e75408237274245fbeb984aa95432d59f4e9d248 Mon Sep 17 00:00:00 2001
From: Sven Verweij <37927107+SvenVw@users.noreply.github.com>
Date: Wed, 2 Apr 2025 11:06:24 +0200
Subject: [PATCH 08/33] Add submitting stage to button
---
fdm-app/app/components/custom/field/form.tsx | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/fdm-app/app/components/custom/field/form.tsx b/fdm-app/app/components/custom/field/form.tsx
index cd0ac3646..9d79d5dca 100644
--- a/fdm-app/app/components/custom/field/form.tsx
+++ b/fdm-app/app/components/custom/field/form.tsx
@@ -23,6 +23,7 @@ import { zodResolver } from "@hookform/resolvers/zod"
import { Form } from "react-router"
import { FormSchema } from "./schema"
import { Combobox } from "../combobox"
+import { LoadingSpinner } from "@/components/custom/loadingspinner"
interface FieldDetailsDialogProps {
open: boolean
@@ -122,7 +123,17 @@ export default function FieldDetailsDialog({
/>
-
+
From 9a2821d275d5558be9699e78e488fcd66862e3ee Mon Sep 17 00:00:00 2001
From: Sven Verweij <37927107+SvenVw@users.noreply.github.com>
Date: Wed, 2 Apr 2025 14:45:40 +0200
Subject: [PATCH 09/33] Fix displaying on small screen
---
...farm.$b_id_farm.$calendar.field.$b_id.cultivation._index.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.cultivation._index.tsx b/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.cultivation._index.tsx
index afd9ea5a9..2cc76fae0 100644
--- a/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.cultivation._index.tsx
+++ b/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.cultivation._index.tsx
@@ -143,7 +143,7 @@ export default function FarmFieldsOverviewBlock() {
-
+
Date: Wed, 2 Apr 2025 14:46:15 +0200
Subject: [PATCH 10/33] Remove not needed validation
---
fdm-app/app/components/custom/field/schema.tsx | 6 ------
1 file changed, 6 deletions(-)
diff --git a/fdm-app/app/components/custom/field/schema.tsx b/fdm-app/app/components/custom/field/schema.tsx
index b54523295..e0bc16f7f 100644
--- a/fdm-app/app/components/custom/field/schema.tsx
+++ b/fdm-app/app/components/custom/field/schema.tsx
@@ -11,12 +11,6 @@ const FormSchema = z.object({
b_lu_catalogue: z.string({
required_error: "Hoofdgewas is verplicht",
}),
- b_id_source: z.string({
- required_error: "Bron is verplicht",
- }),
- b_geometry: z.string({
- required_error: "Geometrie is verplicht",
- }),
})
export { FormSchema }
From f2a41247f4d4cd731febd0c1f4533cddd09c9cfc Mon Sep 17 00:00:00 2001
From: Sven Verweij <37927107+SvenVw@users.noreply.github.com>
Date: Wed, 2 Apr 2025 16:05:16 +0200
Subject: [PATCH 11/33] Improve colors of layers
---
fdm-app/app/components/custom/atlas/atlas-styles.tsx | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/fdm-app/app/components/custom/atlas/atlas-styles.tsx b/fdm-app/app/components/custom/atlas/atlas-styles.tsx
index 57c2811fd..05f87ade2 100644
--- a/fdm-app/app/components/custom/atlas/atlas-styles.tsx
+++ b/fdm-app/app/components/custom/atlas/atlas-styles.tsx
@@ -13,14 +13,18 @@ export function getFieldsStyle(layerId: string): LayerProps & {
id: layerId,
type: "fill",
paint: {
- "fill-color": "#93c5fd",
+ "fill-color": "#3b82f6",
"fill-opacity": 0.5,
"fill-outline-color": "#1e3a8a",
},
}
if (layerId === "fieldsSelected") {
- fieldsStyle.paint["fill-color"] = "#fca5a5"
+ fieldsStyle.paint["fill-color"] = "#f43f5e"
+ fieldsStyle.paint["fill-opacity"] = 0.8
+ }
+ if (layerId === "fieldsSaved") {
+ fieldsStyle.paint["fill-color"] = "#10b981"
fieldsStyle.paint["fill-opacity"] = 0.8
}
return fieldsStyle
From 5611acf7c77583c24e32cc42bd6cb6241fdc23c8 Mon Sep 17 00:00:00 2001
From: Sven Verweij <37927107+SvenVw@users.noreply.github.com>
Date: Wed, 2 Apr 2025 16:08:45 +0200
Subject: [PATCH 12/33] Improve boxes
---
fdm-app/app/components/custom/atlas/atlas-sources.tsx | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/fdm-app/app/components/custom/atlas/atlas-sources.tsx b/fdm-app/app/components/custom/atlas/atlas-sources.tsx
index 17846d3c3..af219897a 100644
--- a/fdm-app/app/components/custom/atlas/atlas-sources.tsx
+++ b/fdm-app/app/components/custom/atlas/atlas-sources.tsx
@@ -127,10 +127,10 @@ export function FieldsSourceAvailable({
if (bounds) {
const [[minX, minY], [maxX, maxY]] = bounds.toArray()
const bbox = {
- minX: 0.9999 * minX,
- maxX: 1.0001 * maxX,
- minY: 0.9999 * minY,
- maxY: 1.0001 * maxY,
+ minX: 0.9995 * minX,
+ maxX: 1.0005 * maxX,
+ minY: 0.9995 * minY,
+ maxY: 1.0005 * maxY,
}
try {
const iter = deserialize(url, bbox)
From 4b3169fd71e7dac616e44f86554d426c8257229b Mon Sep 17 00:00:00 2001
From: Sven Verweij <37927107+SvenVw@users.noreply.github.com>
Date: Wed, 2 Apr 2025 16:16:26 +0200
Subject: [PATCH 13/33] Improve types
---
.../components/custom/atlas/atlas-styles.tsx | 44 +++++++++++++------
1 file changed, 30 insertions(+), 14 deletions(-)
diff --git a/fdm-app/app/components/custom/atlas/atlas-styles.tsx b/fdm-app/app/components/custom/atlas/atlas-styles.tsx
index 05f87ade2..6aa373d75 100644
--- a/fdm-app/app/components/custom/atlas/atlas-styles.tsx
+++ b/fdm-app/app/components/custom/atlas/atlas-styles.tsx
@@ -1,23 +1,38 @@
-import type { LayerProps } from "react-map-gl"
+import type {
+ FillLayerSpecification,
+ LayerProps,
+ SymbolLayerSpecification,
+} from "react-map-gl"
-export function getFieldsStyle(layerId: string): LayerProps & {
- id: string
- type: string
- paint: {
- "fill-color": string
- "fill-opacity": number
- "fill-outline-color": string
- }
-} {
- const fieldsStyle = {
- id: layerId,
+export function getFieldsStyle(
+ layerId: string,
+): LayerProps &
+ (
+ | ({
+ id: string
+ type: "fill"
+ paint: FillLayerSpecification["paint"]
+ })
+ | {
+ id: string
+ type: "symbol"
+ layout: SymbolLayerSpecification["layout"]
+ paint: SymbolLayerSpecification["paint"]
+ }
+ ) {
+ const baseFieldsStyle: Omit = {
type: "fill",
paint: {
- "fill-color": "#3b82f6",
+ "fill-color": "#60a5fa",
"fill-opacity": 0.5,
"fill-outline-color": "#1e3a8a",
},
- }
+ } as FillLayerSpecification // Cast to FillLayerSpecification to allow modification of paint
+
+ const fieldsStyle = {
+ ...baseFieldsStyle,
+ id: layerId,
+ } as LayerProps & FillLayerSpecification // Cast to FillLayerSpecification to allow modification of paint
if (layerId === "fieldsSelected") {
fieldsStyle.paint["fill-color"] = "#f43f5e"
@@ -27,5 +42,6 @@ export function getFieldsStyle(layerId: string): LayerProps & {
fieldsStyle.paint["fill-color"] = "#10b981"
fieldsStyle.paint["fill-opacity"] = 0.8
}
+
return fieldsStyle
}
From 16508ce54d551ca0dc9c0d2efe3078ec6a95b766 Mon Sep 17 00:00:00 2001
From: Sven Verweij <37927107+SvenVw@users.noreply.github.com>
Date: Thu, 3 Apr 2025 10:24:05 +0200
Subject: [PATCH 14/33] Fix viewState if no fields are present
---
fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx b/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
index b2a3b1b69..f4f0364b9 100644
--- a/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
+++ b/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
@@ -192,8 +192,11 @@ export default function Index() {
const fieldsSavedId = "fieldsSaved"
const fieldsSaved = loaderData.featureCollection
- const viewState = getViewState(fieldsSaved)
const fieldsSavedStyle = getFieldsStyle(fieldsSavedId)
+ let viewState = getViewState(null)
+ if (fieldsSaved.features.length > 0) {
+ viewState = getViewState(fieldsSaved)
+ }
const fieldsAvailableId = "fieldsAvailable"
const fieldsAvailableStyle = getFieldsStyle(fieldsAvailableId)
From f7e8b090befefceb4508e4f2f2703f8f5a261802 Mon Sep 17 00:00:00 2001
From: Sven Verweij <37927107+SvenVw@users.noreply.github.com>
Date: Thu, 3 Apr 2025 11:42:25 +0200
Subject: [PATCH 15/33] Remove whiteline
---
fdm-app/app/components/blocks/farm.tsx | 1 -
1 file changed, 1 deletion(-)
diff --git a/fdm-app/app/components/blocks/farm.tsx b/fdm-app/app/components/blocks/farm.tsx
index e13c9cebb..ddf264606 100644
--- a/fdm-app/app/components/blocks/farm.tsx
+++ b/fdm-app/app/components/blocks/farm.tsx
@@ -2,7 +2,6 @@ import { zodResolver } from "@hookform/resolvers/zod"
import { Form } from "react-router"
import { RemixFormProvider, useRemixForm } from "remix-hook-form"
import type { z } from "zod"
-
import { Button } from "@/components/ui/button"
import {
Card,
From 795718b0e778b7b06f4bd9dfe516070fe9fd271f Mon Sep 17 00:00:00 2001
From: Sven Verweij <37927107+SvenVw@users.noreply.github.com>
Date: Thu, 3 Apr 2025 11:42:45 +0200
Subject: [PATCH 16/33] Fix form submission handling
---
fdm-app/app/components/custom/field/form.tsx | 148 ++++++++++--------
.../app/components/custom/field/schema.tsx | 6 +
.../farm.$b_id_farm.$calendar.field.new.tsx | 2 +-
3 files changed, 87 insertions(+), 69 deletions(-)
diff --git a/fdm-app/app/components/custom/field/form.tsx b/fdm-app/app/components/custom/field/form.tsx
index 9d79d5dca..49240e45d 100644
--- a/fdm-app/app/components/custom/field/form.tsx
+++ b/fdm-app/app/components/custom/field/form.tsx
@@ -31,8 +31,6 @@ interface FieldDetailsDialogProps {
field: any
cultivationOptions: any
fieldNameDefault: string
- b_source: string
- b_geometry: string
}
export default function FieldDetailsDialog({
@@ -69,72 +67,86 @@ export default function FieldDetailsDialog({
-
diff --git a/fdm-app/app/components/custom/field/schema.tsx b/fdm-app/app/components/custom/field/schema.tsx
index cd618bc5c..06ef0abcf 100644
--- a/fdm-app/app/components/custom/field/schema.tsx
+++ b/fdm-app/app/components/custom/field/schema.tsx
@@ -13,10 +13,10 @@ const FormSchema = z.object({
}),
b_id_source: z.string({
required_error: "ID van bron is verplicht",
- }),
+ }).optional(),
b_geometry: z.string({
required_error: "Geometrie van perceel is verplicht",
- }),
+ }).optional(),
})
export { FormSchema }
diff --git a/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx b/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
index 6f2b859fb..385cea6de 100644
--- a/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
+++ b/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
@@ -117,7 +117,7 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
)
const features = fields.map((field) => {
const feature: Feature = {
- type: "Feature" as const,
+ type: "Feature" as const,
properties: {
b_id: field.b_id,
b_name: field.b_name,
@@ -320,6 +320,7 @@ export default function Index() {
export async function action({ request, params }: ActionFunctionArgs) {
// Get the farm id
+ console.log("Action!")
const b_id_farm = params.b_id_farm
if (!b_id_farm) {
throw data("Farm ID is required", {
@@ -370,7 +371,7 @@ export async function action({ request, params }: ActionFunctionArgs) {
const b_lu_catalogue = formValues.b_lu_catalogue
// Parse the geometry string twice to get the actual GeoJSON object
const b_geometry = JSON.parse(
- JSON.parse(formValues.b_geometry),
+ JSON.parse(String(formValues.b_geometry)),
) as Polygon
const currentYear = new Date().getFullYear()
const defaultDate = timeframe.start
@@ -449,7 +450,7 @@ export async function action({ request, params }: ActionFunctionArgs) {
}
return redirectWithSuccess(
- `/farm/${b_id_farm}/${calendar}/field/${b_id}`,
+ `/farm/${b_id_farm}/${calendar}/field/${b_id}/fertilizer`,
{
message: "${b_name} is toegevoegd! 🎉",
},
diff --git a/fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx b/fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
index f06fde780..b173e8974 100644
--- a/fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
+++ b/fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
@@ -28,7 +28,6 @@ import { Skeleton } from "@/components/ui/skeleton"
import { getSession } from "@/lib/auth.server"
import { getCalendar, getTimeframe } from "@/lib/calendar"
import { handleActionError, handleLoaderError } from "@/lib/error"
-import { useCalendarStore } from "@/store/calendar"
import {
addCultivation,
addField,
From 4de27856dd175af5f783a901fb139108123afe8f Mon Sep 17 00:00:00 2001
From: Sven Verweij <37927107+SvenVw@users.noreply.github.com>
Date: Mon, 7 Apr 2025 14:58:51 +0200
Subject: [PATCH 23/33] Fixes
---
fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx b/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
index 385cea6de..20d9ae076 100644
--- a/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
+++ b/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
@@ -342,7 +342,6 @@ export async function action({ request, params }: ActionFunctionArgs) {
request,
FormSchema,
)
- console.log(formValues)
// Check if cultivation is available
let cultivationOptions = []
@@ -452,7 +451,7 @@ export async function action({ request, params }: ActionFunctionArgs) {
return redirectWithSuccess(
`/farm/${b_id_farm}/${calendar}/field/${b_id}/fertilizer`,
{
- message: "${b_name} is toegevoegd! 🎉",
+ message: `${b_name} is toegevoegd! 🎉`,
},
)
} catch (error) {
From d693cdbb91e275aba6ab562a2e73154274517658 Mon Sep 17 00:00:00 2001
From: Sven Verweij <37927107+SvenVw@users.noreply.github.com>
Date: Mon, 7 Apr 2025 15:14:00 +0200
Subject: [PATCH 24/33] Fix that soil data without sampling date is not
excluded
---
.changeset/slick-buses-bow.md | 5 ++
fdm-core/src/soil.test.ts | 122 ++++++++++++++++++++++++++++++++++
fdm-core/src/soil.ts | 27 ++++++--
3 files changed, 148 insertions(+), 6 deletions(-)
create mode 100644 .changeset/slick-buses-bow.md
diff --git a/.changeset/slick-buses-bow.md b/.changeset/slick-buses-bow.md
new file mode 100644
index 000000000..314104c72
--- /dev/null
+++ b/.changeset/slick-buses-bow.md
@@ -0,0 +1,5 @@
+---
+"@svenvw/fdm-core": patch
+---
+
+Fix that soil data without sampling date is not excluded
diff --git a/fdm-core/src/soil.test.ts b/fdm-core/src/soil.test.ts
index 0281d12c8..ac8952e2c 100644
--- a/fdm-core/src/soil.test.ts
+++ b/fdm-core/src/soil.test.ts
@@ -646,6 +646,128 @@ describe("Soil Analysis Functions", () => {
const currentData = await getCurrentSoilData(fdm, principal_id, b_id)
expect(currentData.length).toEqual(0)
})
+
+ it("should retrieve soil analyses including those with null b_sampling_date and order correctly", async () => {
+ const a_date = new Date()
+ const a_source = "test source"
+ const b_depth = 10
+
+ // Add analyses with valid b_sampling_date
+ const b_sampling_date1 = new Date("2024-01-01T00:00:00Z")
+ await addSoilAnalysis(
+ fdm,
+ principal_id,
+ a_date,
+ a_source,
+ b_id,
+ b_depth,
+ b_sampling_date1,
+ )
+
+ const b_sampling_date2 = new Date("2024-01-05T00:00:00Z")
+ await addSoilAnalysis(
+ fdm,
+ principal_id,
+ a_date,
+ a_source,
+ b_id,
+ b_depth,
+ b_sampling_date2,
+ )
+
+ // Add an analysis with null b_sampling_date
+ await addSoilAnalysis(
+ fdm,
+ principal_id,
+ a_date,
+ a_source,
+ b_id,
+ b_depth,
+ null,
+ )
+
+ // Retrieve all analyses
+ const allAnalyses = await getSoilAnalyses(fdm, principal_id, b_id)
+
+ expect(allAnalyses).toHaveLength(3)
+
+ // Check that the analysis with null date comes last
+ expect(allAnalyses[0].b_sampling_date).toEqual(b_sampling_date2)
+ expect(allAnalyses[1].b_sampling_date).toEqual(b_sampling_date1)
+ expect(allAnalyses[2].b_sampling_date).toBeNull()
+ })
+
+ it("should retrieve soil analyses including those with null b_sampling_date and order correctly with timeframe", async () => {
+ const a_date = new Date()
+ const a_source = "test source"
+ const b_depth = 10
+
+ // Add analyses with valid b_sampling_date
+ const b_sampling_date1 = new Date("2024-01-01T00:00:00Z")
+ const properties1 = { a_som_loi: 5 }
+ await addSoilAnalysis(
+ fdm,
+ principal_id,
+ a_date,
+ a_source,
+ b_id,
+ b_depth,
+ b_sampling_date1,
+ properties1,
+ )
+
+ const b_sampling_date2 = new Date("2024-01-05T00:00:00Z")
+ const properties2 = { a_som_loi: 6 }
+ await addSoilAnalysis(
+ fdm,
+ principal_id,
+ a_date,
+ a_source,
+ b_id,
+ b_depth,
+ b_sampling_date2,
+ properties2,
+ )
+
+ // Add an analysis with null b_sampling_date
+ const properties3 = { a_som_loi: 7, a_p_al: 20 }
+ await addSoilAnalysis(
+ fdm,
+ principal_id,
+ a_date,
+ a_source,
+ b_id,
+ b_depth,
+ null,
+ properties3,
+ )
+
+ // Retrieve all analyses
+ const allAnalyses = await getSoilAnalyses(fdm, principal_id, b_id, {
+ start: new Date("2023-01-01"),
+ end: new Date("2025-01-01"),
+ })
+
+ expect(allAnalyses).toHaveLength(3)
+
+ // Check that the analysis with null date comes last
+ expect(allAnalyses[0].b_sampling_date).toEqual(b_sampling_date2)
+ expect(allAnalyses[1].b_sampling_date).toEqual(b_sampling_date1)
+ expect(allAnalyses[2].b_sampling_date).toBeNull()
+
+ const currentData = await getCurrentSoilData(fdm, principal_id, b_id, {
+ start: new Date("2023-01-01"),
+ end: new Date("2025-01-01"),
+ })
+
+ const somLoiData = currentData.find(
+ (item) => item.parameter === "a_som_loi",
+ )
+ expect(somLoiData?.value).toEqual(properties2.a_som_loi)
+
+ const palData = currentData.find((item) => item.parameter === "a_p_al")
+ expect(palData?.value).toEqual(properties3.a_p_al)
+ })
})
describe("getSoilParametersDescription", () => {
diff --git a/fdm-core/src/soil.ts b/fdm-core/src/soil.ts
index 6cdcde409..9dfe0f5c7 100644
--- a/fdm-core/src/soil.ts
+++ b/fdm-core/src/soil.ts
@@ -1,4 +1,4 @@
-import { type SQL, and, eq, gte, lte, sql } from "drizzle-orm"
+import { type SQL, and, eq, gte, isNull, lte, or, sql } from "drizzle-orm"
import { checkPermission } from "./authorization"
import type { PrincipalId } from "./authorization.d"
import * as schema from "./db/schema"
@@ -262,18 +262,30 @@ export async function getSoilAnalyses(
if (timeframe?.start && timeframe.end) {
whereClause = and(
eq(schema.soilSampling.b_id, b_id),
- gte(schema.soilSampling.b_sampling_date, timeframe.start),
- lte(schema.soilSampling.b_sampling_date, timeframe.end),
+ or(
+ gte(schema.soilSampling.b_sampling_date, timeframe.start),
+ isNull(schema.soilSampling.b_sampling_date),
+ ),
+ or(
+ lte(schema.soilSampling.b_sampling_date, timeframe.end),
+ isNull(schema.soilSampling.b_sampling_date),
+ ),
)
} else if (timeframe?.start) {
whereClause = and(
eq(schema.soilSampling.b_id, b_id),
- gte(schema.soilSampling.b_sampling_date, timeframe.start),
+ or(
+ gte(schema.soilSampling.b_sampling_date, timeframe.start),
+ isNull(schema.soilSampling.b_sampling_date),
+ ),
)
} else if (timeframe?.end) {
whereClause = and(
eq(schema.soilSampling.b_id, b_id),
- lte(schema.soilSampling.b_sampling_date, timeframe.end),
+ or(
+ lte(schema.soilSampling.b_sampling_date, timeframe.end),
+ isNull(schema.soilSampling.b_sampling_date),
+ ),
)
} else {
whereClause = eq(schema.soilSampling.b_id, b_id)
@@ -349,7 +361,10 @@ export async function getCurrentSoilData(
if (timeframe?.end) {
whereClause = and(
eq(schema.soilSampling.b_id, b_id),
- lte(schema.soilSampling.b_sampling_date, timeframe.end),
+ or(
+ lte(schema.soilSampling.b_sampling_date, timeframe.end),
+ isNull(schema.soilSampling.b_sampling_date),
+ ),
)
} else {
whereClause = eq(schema.soilSampling.b_id, b_id)
From 61a515766c30e169866cc0d2d88480f4c43ddcca Mon Sep 17 00:00:00 2001
From: Sven Verweij <37927107+SvenVw@users.noreply.github.com>
Date: Mon, 7 Apr 2025 15:27:38 +0200
Subject: [PATCH 25/33] fix lock file
---
pnpm-lock.yaml | 285 +++++--------------------------------------------
1 file changed, 27 insertions(+), 258 deletions(-)
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 667630d7b..15604d9b6 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -238,10 +238,10 @@ importers:
version: 1.39.0
'@react-router/dev':
specifier: ^7.4.1
- version: 7.4.1(@react-router/serve@7.4.1(react-router@7.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.7.3))(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(react-router@7.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(terser@5.39.0)(typescript@5.7.3)(vite@6.2.5(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1))(yaml@2.7.1)
+ version: 7.4.1(@react-router/serve@7.4.1(react-router@7.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.7.3))(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(react-router@7.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(terser@5.39.0)(typescript@5.7.3)(vite@6.2.5(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1))(yaml@2.7.1)
'@react-router/fs-routes':
specifier: ^7.4.1
- version: 7.4.1(@react-router/dev@7.4.1(@react-router/serve@7.4.1(react-router@7.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.7.3))(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(react-router@7.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(terser@5.39.0)(typescript@5.7.3)(vite@6.2.5(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1))(yaml@2.7.1))(typescript@5.7.3)
+ version: 7.4.1(@react-router/dev@7.4.1(@react-router/serve@7.4.1(react-router@7.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.7.3))(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(react-router@7.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(terser@5.39.0)(typescript@5.7.3)(vite@6.2.5(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1))(yaml@2.7.1))(typescript@5.7.3)
'@types/geojson':
specifier: ^7946.0.16
version: 7946.0.16
@@ -277,10 +277,10 @@ importers:
version: 5.7.3
vite:
specifier: 'catalog:'
- version: 6.2.5(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)
+ version: 6.2.5(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)
vite-tsconfig-paths:
specifier: 'catalog:'
- version: 5.1.4(typescript@5.7.3)(vite@6.2.5(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1))
+ version: 5.1.4(typescript@5.7.3)(vite@6.2.5(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1))
fdm-calculator:
dependencies:
@@ -3125,201 +3125,101 @@ packages:
cpu: [arm]
os: [android]
- '@rollup/rollup-android-arm-eabi@4.39.0':
- resolution: {integrity: sha512-lGVys55Qb00Wvh8DMAocp5kIcaNzEFTmGhfFd88LfaogYTRKrdxgtlO5H6S49v2Nd8R2C6wLOal0qv6/kCkOwA==}
- cpu: [arm]
- os: [android]
-
'@rollup/rollup-android-arm64@4.38.0':
resolution: {integrity: sha512-VUsgcy4GhhT7rokwzYQP+aV9XnSLkkhlEJ0St8pbasuWO/vwphhZQxYEKUP3ayeCYLhk6gEtacRpYP/cj3GjyQ==}
cpu: [arm64]
os: [android]
- '@rollup/rollup-android-arm64@4.39.0':
- resolution: {integrity: sha512-It9+M1zE31KWfqh/0cJLrrsCPiF72PoJjIChLX+rEcujVRCb4NLQ5QzFkzIZW8Kn8FTbvGQBY5TkKBau3S8cCQ==}
- cpu: [arm64]
- os: [android]
-
'@rollup/rollup-darwin-arm64@4.38.0':
resolution: {integrity: sha512-buA17AYXlW9Rn091sWMq1xGUvWQFOH4N1rqUxGJtEQzhChxWjldGCCup7r/wUnaI6Au8sKXpoh0xg58a7cgcpg==}
cpu: [arm64]
os: [darwin]
- '@rollup/rollup-darwin-arm64@4.39.0':
- resolution: {integrity: sha512-lXQnhpFDOKDXiGxsU9/l8UEGGM65comrQuZ+lDcGUx+9YQ9dKpF3rSEGepyeR5AHZ0b5RgiligsBhWZfSSQh8Q==}
- cpu: [arm64]
- os: [darwin]
-
'@rollup/rollup-darwin-x64@4.38.0':
resolution: {integrity: sha512-Mgcmc78AjunP1SKXl624vVBOF2bzwNWFPMP4fpOu05vS0amnLcX8gHIge7q/lDAHy3T2HeR0TqrriZDQS2Woeg==}
cpu: [x64]
os: [darwin]
- '@rollup/rollup-darwin-x64@4.39.0':
- resolution: {integrity: sha512-mKXpNZLvtEbgu6WCkNij7CGycdw9cJi2k9v0noMb++Vab12GZjFgUXD69ilAbBh034Zwn95c2PNSz9xM7KYEAQ==}
- cpu: [x64]
- os: [darwin]
-
'@rollup/rollup-freebsd-arm64@4.38.0':
resolution: {integrity: sha512-zzJACgjLbQTsscxWqvrEQAEh28hqhebpRz5q/uUd1T7VTwUNZ4VIXQt5hE7ncs0GrF+s7d3S4on4TiXUY8KoQA==}
cpu: [arm64]
os: [freebsd]
- '@rollup/rollup-freebsd-arm64@4.39.0':
- resolution: {integrity: sha512-jivRRlh2Lod/KvDZx2zUR+I4iBfHcu2V/BA2vasUtdtTN2Uk3jfcZczLa81ESHZHPHy4ih3T/W5rPFZ/hX7RtQ==}
- cpu: [arm64]
- os: [freebsd]
-
'@rollup/rollup-freebsd-x64@4.38.0':
resolution: {integrity: sha512-hCY/KAeYMCyDpEE4pTETam0XZS4/5GXzlLgpi5f0IaPExw9kuB+PDTOTLuPtM10TlRG0U9OSmXJ+Wq9J39LvAg==}
cpu: [x64]
os: [freebsd]
- '@rollup/rollup-freebsd-x64@4.39.0':
- resolution: {integrity: sha512-8RXIWvYIRK9nO+bhVz8DwLBepcptw633gv/QT4015CpJ0Ht8punmoHU/DuEd3iw9Hr8UwUV+t+VNNuZIWYeY7Q==}
- cpu: [x64]
- os: [freebsd]
-
'@rollup/rollup-linux-arm-gnueabihf@4.38.0':
resolution: {integrity: sha512-mimPH43mHl4JdOTD7bUMFhBdrg6f9HzMTOEnzRmXbOZqjijCw8LA5z8uL6LCjxSa67H2xiLFvvO67PT05PRKGg==}
cpu: [arm]
os: [linux]
- '@rollup/rollup-linux-arm-gnueabihf@4.39.0':
- resolution: {integrity: sha512-mz5POx5Zu58f2xAG5RaRRhp3IZDK7zXGk5sdEDj4o96HeaXhlUwmLFzNlc4hCQi5sGdR12VDgEUqVSHer0lI9g==}
- cpu: [arm]
- os: [linux]
-
'@rollup/rollup-linux-arm-musleabihf@4.38.0':
resolution: {integrity: sha512-tPiJtiOoNuIH8XGG8sWoMMkAMm98PUwlriOFCCbZGc9WCax+GLeVRhmaxjJtz6WxrPKACgrwoZ5ia/uapq3ZVg==}
cpu: [arm]
os: [linux]
- '@rollup/rollup-linux-arm-musleabihf@4.39.0':
- resolution: {integrity: sha512-+YDwhM6gUAyakl0CD+bMFpdmwIoRDzZYaTWV3SDRBGkMU/VpIBYXXEvkEcTagw/7VVkL2vA29zU4UVy1mP0/Yw==}
- cpu: [arm]
- os: [linux]
-
'@rollup/rollup-linux-arm64-gnu@4.38.0':
resolution: {integrity: sha512-wZco59rIVuB0tjQS0CSHTTUcEde+pXQWugZVxWaQFdQQ1VYub/sTrNdY76D1MKdN2NB48JDuGABP6o6fqos8mA==}
cpu: [arm64]
os: [linux]
- '@rollup/rollup-linux-arm64-gnu@4.39.0':
- resolution: {integrity: sha512-EKf7iF7aK36eEChvlgxGnk7pdJfzfQbNvGV/+l98iiMwU23MwvmV0Ty3pJ0p5WQfm3JRHOytSIqD9LB7Bq7xdQ==}
- cpu: [arm64]
- os: [linux]
-
'@rollup/rollup-linux-arm64-musl@4.38.0':
resolution: {integrity: sha512-fQgqwKmW0REM4LomQ+87PP8w8xvU9LZfeLBKybeli+0yHT7VKILINzFEuggvnV9M3x1Ed4gUBmGUzCo/ikmFbQ==}
cpu: [arm64]
os: [linux]
- '@rollup/rollup-linux-arm64-musl@4.39.0':
- resolution: {integrity: sha512-vYanR6MtqC7Z2SNr8gzVnzUul09Wi1kZqJaek3KcIlI/wq5Xtq4ZPIZ0Mr/st/sv/NnaPwy/D4yXg5x0B3aUUA==}
- cpu: [arm64]
- os: [linux]
-
'@rollup/rollup-linux-loongarch64-gnu@4.38.0':
resolution: {integrity: sha512-hz5oqQLXTB3SbXpfkKHKXLdIp02/w3M+ajp8p4yWOWwQRtHWiEOCKtc9U+YXahrwdk+3qHdFMDWR5k+4dIlddg==}
cpu: [loong64]
os: [linux]
- '@rollup/rollup-linux-loongarch64-gnu@4.39.0':
- resolution: {integrity: sha512-NMRUT40+h0FBa5fb+cpxtZoGAggRem16ocVKIv5gDB5uLDgBIwrIsXlGqYbLwW8YyO3WVTk1FkFDjMETYlDqiw==}
- cpu: [loong64]
- os: [linux]
-
'@rollup/rollup-linux-powerpc64le-gnu@4.38.0':
resolution: {integrity: sha512-NXqygK/dTSibQ+0pzxsL3r4Xl8oPqVoWbZV9niqOnIHV/J92fe65pOir0xjkUZDRSPyFRvu+4YOpJF9BZHQImw==}
cpu: [ppc64]
os: [linux]
- '@rollup/rollup-linux-powerpc64le-gnu@4.39.0':
- resolution: {integrity: sha512-0pCNnmxgduJ3YRt+D+kJ6Ai/r+TaePu9ZLENl+ZDV/CdVczXl95CbIiwwswu4L+K7uOIGf6tMo2vm8uadRaICQ==}
- cpu: [ppc64]
- os: [linux]
-
'@rollup/rollup-linux-riscv64-gnu@4.38.0':
resolution: {integrity: sha512-GEAIabR1uFyvf/jW/5jfu8gjM06/4kZ1W+j1nWTSSB3w6moZEBm7iBtzwQ3a1Pxos2F7Gz+58aVEnZHU295QTg==}
cpu: [riscv64]
os: [linux]
- '@rollup/rollup-linux-riscv64-gnu@4.39.0':
- resolution: {integrity: sha512-t7j5Zhr7S4bBtksT73bO6c3Qa2AV/HqiGlj9+KB3gNF5upcVkx+HLgxTm8DK4OkzsOYqbdqbLKwvGMhylJCPhQ==}
- cpu: [riscv64]
- os: [linux]
-
'@rollup/rollup-linux-riscv64-musl@4.38.0':
resolution: {integrity: sha512-9EYTX+Gus2EGPbfs+fh7l95wVADtSQyYw4DfSBcYdUEAmP2lqSZY0Y17yX/3m5VKGGJ4UmIH5LHLkMJft3bYoA==}
cpu: [riscv64]
os: [linux]
- '@rollup/rollup-linux-riscv64-musl@4.39.0':
- resolution: {integrity: sha512-m6cwI86IvQ7M93MQ2RF5SP8tUjD39Y7rjb1qjHgYh28uAPVU8+k/xYWvxRO3/tBN2pZkSMa5RjnPuUIbrwVxeA==}
- cpu: [riscv64]
- os: [linux]
-
'@rollup/rollup-linux-s390x-gnu@4.38.0':
resolution: {integrity: sha512-Mpp6+Z5VhB9VDk7RwZXoG2qMdERm3Jw07RNlXHE0bOnEeX+l7Fy4bg+NxfyN15ruuY3/7Vrbpm75J9QHFqj5+Q==}
cpu: [s390x]
os: [linux]
- '@rollup/rollup-linux-s390x-gnu@4.39.0':
- resolution: {integrity: sha512-iRDJd2ebMunnk2rsSBYlsptCyuINvxUfGwOUldjv5M4tpa93K8tFMeYGpNk2+Nxl+OBJnBzy2/JCscGeO507kA==}
- cpu: [s390x]
- os: [linux]
-
'@rollup/rollup-linux-x64-gnu@4.38.0':
resolution: {integrity: sha512-vPvNgFlZRAgO7rwncMeE0+8c4Hmc+qixnp00/Uv3ht2x7KYrJ6ERVd3/R0nUtlE6/hu7/HiiNHJ/rP6knRFt1w==}
cpu: [x64]
os: [linux]
- '@rollup/rollup-linux-x64-gnu@4.39.0':
- resolution: {integrity: sha512-t9jqYw27R6Lx0XKfEFe5vUeEJ5pF3SGIM6gTfONSMb7DuG6z6wfj2yjcoZxHg129veTqU7+wOhY6GX8wmf90dA==}
- cpu: [x64]
- os: [linux]
-
'@rollup/rollup-linux-x64-musl@4.38.0':
resolution: {integrity: sha512-q5Zv+goWvQUGCaL7fU8NuTw8aydIL/C9abAVGCzRReuj5h30TPx4LumBtAidrVOtXnlB+RZkBtExMsfqkMfb8g==}
cpu: [x64]
os: [linux]
- '@rollup/rollup-linux-x64-musl@4.39.0':
- resolution: {integrity: sha512-ThFdkrFDP55AIsIZDKSBWEt/JcWlCzydbZHinZ0F/r1h83qbGeenCt/G/wG2O0reuENDD2tawfAj2s8VK7Bugg==}
- cpu: [x64]
- os: [linux]
-
'@rollup/rollup-win32-arm64-msvc@4.38.0':
resolution: {integrity: sha512-u/Jbm1BU89Vftqyqbmxdq14nBaQjQX1HhmsdBWqSdGClNaKwhjsg5TpW+5Ibs1mb8Es9wJiMdl86BcmtUVXNZg==}
cpu: [arm64]
os: [win32]
- '@rollup/rollup-win32-arm64-msvc@4.39.0':
- resolution: {integrity: sha512-jDrLm6yUtbOg2TYB3sBF3acUnAwsIksEYjLeHL+TJv9jg+TmTwdyjnDex27jqEMakNKf3RwwPahDIt7QXCSqRQ==}
- cpu: [arm64]
- os: [win32]
-
'@rollup/rollup-win32-ia32-msvc@4.38.0':
resolution: {integrity: sha512-mqu4PzTrlpNHHbu5qleGvXJoGgHpChBlrBx/mEhTPpnAL1ZAYFlvHD7rLK839LLKQzqEQMFJfGrrOHItN4ZQqA==}
cpu: [ia32]
os: [win32]
- '@rollup/rollup-win32-ia32-msvc@4.39.0':
- resolution: {integrity: sha512-6w9uMuza+LbLCVoNKL5FSLE7yvYkq9laSd09bwS0tMjkwXrmib/4KmoJcrKhLWHvw19mwU+33ndC69T7weNNjQ==}
- cpu: [ia32]
- os: [win32]
-
'@rollup/rollup-win32-x64-msvc@4.38.0':
resolution: {integrity: sha512-jjqy3uWlecfB98Psxb5cD6Fny9Fupv9LrDSPTQZUROqjvZmcCqNu4UMl7qqhlUUGpwiAkotj6GYu4SZdcr/nLw==}
cpu: [x64]
os: [win32]
- '@rollup/rollup-win32-x64-msvc@4.39.0':
- resolution: {integrity: sha512-yAkUOkIKZlK5dl7u6dg897doBgLXmUHhIINM2c+sND3DZwnrdQkkSiDh7N75Ll4mM4dxSkYfXqU9fW3lLkMFug==}
- cpu: [x64]
- os: [win32]
-
'@rspack/binding-darwin-arm64@1.2.0-alpha.0':
resolution: {integrity: sha512-EPprIe6BrkJ9XuWL5HBXJFaH4vvt5C2kBTvyu+t5E3wacyH9A0gIDaMOEmH30Kt3zl4B07OCBC1nCiJ1sTtimw==}
cpu: [arm64]
@@ -8177,11 +8077,6 @@ packages:
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
- rollup@4.39.0:
- resolution: {integrity: sha512-thI8kNc02yNvnmJp8dr3fNWJ9tCONDhp6TV35X6HkKGGs9E6q7YWCHbe5vKiTa7TAiNcFEmXKj3X/pG2b3ci0g==}
- engines: {node: '>=18.0.0', npm: '>=8.0.0'}
- hasBin: true
-
rou3@0.5.1:
resolution: {integrity: sha512-OXMmJ3zRk2xeXFGfA3K+EOPHC5u7RDFG7lIOx0X1pdnhUkI8MdVrbV+sNsD80ElpUZ+MRHdyxPnFthq9VHs8uQ==}
@@ -9055,46 +8950,6 @@ packages:
vite:
optional: true
- vite@6.2.4:
- resolution: {integrity: sha512-veHMSew8CcRzhL5o8ONjy8gkfmFJAd5Ac16oxBUjlwgX3Gq2Wqr+qNC3TjPIpy7TPV/KporLga5GT9HqdrCizw==}
- engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
- hasBin: true
- peerDependencies:
- '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
- jiti: '>=1.21.0'
- less: '*'
- lightningcss: ^1.21.0
- sass: '*'
- sass-embedded: '*'
- stylus: '*'
- sugarss: '*'
- terser: ^5.16.0
- tsx: ^4.8.1
- yaml: ^2.4.2
- peerDependenciesMeta:
- '@types/node':
- optional: true
- jiti:
- optional: true
- less:
- optional: true
- lightningcss:
- optional: true
- sass:
- optional: true
- sass-embedded:
- optional: true
- stylus:
- optional: true
- sugarss:
- optional: true
- terser:
- optional: true
- tsx:
- optional: true
- yaml:
- optional: true
-
vite@6.2.5:
resolution: {integrity: sha512-j023J/hCAa4pRIUH6J9HemwYfjB5llR2Ps0CWeikOtdR8+pAURAk0DoJC5/mm9kd+UgdnIy7d6HE4EAvlYhPhA==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
@@ -11356,7 +11211,7 @@ snapshots:
'@docusaurus/utils': 3.7.0(@swc/core@1.11.15)(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@docusaurus/utils-common': 3.7.0(@swc/core@1.11.15)(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@types/history': 4.7.11
- '@types/react': 19.0.12
+ '@types/react': 18.3.20
'@types/react-router-config': 5.0.11
clsx: 2.1.1
parse-numeric-range: 1.3.0
@@ -12752,7 +12607,7 @@ snapshots:
'@radix-ui/rect@1.1.0': {}
- '@react-router/dev@7.4.1(@react-router/serve@7.4.1(react-router@7.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.7.3))(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(react-router@7.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(terser@5.39.0)(typescript@5.7.3)(vite@6.2.5(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1))(yaml@2.7.1)':
+ '@react-router/dev@7.4.1(@react-router/serve@7.4.1(react-router@7.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.7.3))(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(react-router@7.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(terser@5.39.0)(typescript@5.7.3)(vite@6.2.5(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1))(yaml@2.7.1)':
dependencies:
'@babel/core': 7.26.10
'@babel/generator': 7.27.0
@@ -12781,8 +12636,8 @@ snapshots:
semver: 7.7.1
set-cookie-parser: 2.7.1
valibot: 0.41.0(typescript@5.7.3)
- vite: 6.2.5(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)
- vite-node: 3.0.0-beta.2(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)
+ vite: 6.2.5(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)
+ vite-node: 3.0.0-beta.2(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)
optionalDependencies:
'@react-router/serve': 7.4.1(react-router@7.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.7.3)
typescript: 5.7.3
@@ -12810,9 +12665,9 @@ snapshots:
optionalDependencies:
typescript: 5.7.3
- '@react-router/fs-routes@7.4.1(@react-router/dev@7.4.1(@react-router/serve@7.4.1(react-router@7.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.7.3))(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(react-router@7.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(terser@5.39.0)(typescript@5.7.3)(vite@6.2.5(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1))(yaml@2.7.1))(typescript@5.7.3)':
+ '@react-router/fs-routes@7.4.1(@react-router/dev@7.4.1(@react-router/serve@7.4.1(react-router@7.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.7.3))(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(react-router@7.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(terser@5.39.0)(typescript@5.7.3)(vite@6.2.5(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1))(yaml@2.7.1))(typescript@5.7.3)':
dependencies:
- '@react-router/dev': 7.4.1(@react-router/serve@7.4.1(react-router@7.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.7.3))(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(react-router@7.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(terser@5.39.0)(typescript@5.7.3)(vite@6.2.5(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1))(yaml@2.7.1)
+ '@react-router/dev': 7.4.1(@react-router/serve@7.4.1(react-router@7.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.7.3))(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(react-router@7.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(terser@5.39.0)(typescript@5.7.3)(vite@6.2.5(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1))(yaml@2.7.1)
minimatch: 9.0.5
optionalDependencies:
typescript: 5.7.3
@@ -12907,123 +12762,63 @@ snapshots:
'@rollup/rollup-android-arm-eabi@4.38.0':
optional: true
- '@rollup/rollup-android-arm-eabi@4.39.0':
- optional: true
-
'@rollup/rollup-android-arm64@4.38.0':
optional: true
- '@rollup/rollup-android-arm64@4.39.0':
- optional: true
-
'@rollup/rollup-darwin-arm64@4.38.0':
optional: true
- '@rollup/rollup-darwin-arm64@4.39.0':
- optional: true
-
'@rollup/rollup-darwin-x64@4.38.0':
optional: true
- '@rollup/rollup-darwin-x64@4.39.0':
- optional: true
-
'@rollup/rollup-freebsd-arm64@4.38.0':
optional: true
- '@rollup/rollup-freebsd-arm64@4.39.0':
- optional: true
-
'@rollup/rollup-freebsd-x64@4.38.0':
optional: true
- '@rollup/rollup-freebsd-x64@4.39.0':
- optional: true
-
'@rollup/rollup-linux-arm-gnueabihf@4.38.0':
optional: true
- '@rollup/rollup-linux-arm-gnueabihf@4.39.0':
- optional: true
-
'@rollup/rollup-linux-arm-musleabihf@4.38.0':
optional: true
- '@rollup/rollup-linux-arm-musleabihf@4.39.0':
- optional: true
-
'@rollup/rollup-linux-arm64-gnu@4.38.0':
optional: true
- '@rollup/rollup-linux-arm64-gnu@4.39.0':
- optional: true
-
'@rollup/rollup-linux-arm64-musl@4.38.0':
optional: true
- '@rollup/rollup-linux-arm64-musl@4.39.0':
- optional: true
-
'@rollup/rollup-linux-loongarch64-gnu@4.38.0':
optional: true
- '@rollup/rollup-linux-loongarch64-gnu@4.39.0':
- optional: true
-
'@rollup/rollup-linux-powerpc64le-gnu@4.38.0':
optional: true
- '@rollup/rollup-linux-powerpc64le-gnu@4.39.0':
- optional: true
-
'@rollup/rollup-linux-riscv64-gnu@4.38.0':
optional: true
- '@rollup/rollup-linux-riscv64-gnu@4.39.0':
- optional: true
-
'@rollup/rollup-linux-riscv64-musl@4.38.0':
optional: true
- '@rollup/rollup-linux-riscv64-musl@4.39.0':
- optional: true
-
'@rollup/rollup-linux-s390x-gnu@4.38.0':
optional: true
- '@rollup/rollup-linux-s390x-gnu@4.39.0':
- optional: true
-
'@rollup/rollup-linux-x64-gnu@4.38.0':
optional: true
- '@rollup/rollup-linux-x64-gnu@4.39.0':
- optional: true
-
'@rollup/rollup-linux-x64-musl@4.38.0':
optional: true
- '@rollup/rollup-linux-x64-musl@4.39.0':
- optional: true
-
'@rollup/rollup-win32-arm64-msvc@4.38.0':
optional: true
- '@rollup/rollup-win32-arm64-msvc@4.39.0':
- optional: true
-
'@rollup/rollup-win32-ia32-msvc@4.38.0':
optional: true
- '@rollup/rollup-win32-ia32-msvc@4.39.0':
- optional: true
-
'@rollup/rollup-win32-x64-msvc@4.38.0':
optional: true
- '@rollup/rollup-win32-x64-msvc@4.39.0':
- optional: true
-
'@rspack/binding-darwin-arm64@1.2.0-alpha.0':
optional: true
@@ -13833,21 +13628,21 @@ snapshots:
chai: 5.2.0
tinyrainbow: 2.0.0
- '@vitest/mocker@3.1.1(vite@6.2.4(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1))':
+ '@vitest/mocker@3.1.1(vite@6.2.5(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1))':
dependencies:
'@vitest/spy': 3.1.1
estree-walker: 3.0.3
magic-string: 0.30.17
optionalDependencies:
- vite: 6.2.4(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)
+ vite: 6.2.5(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)
- '@vitest/mocker@3.1.1(vite@6.2.4(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1))':
+ '@vitest/mocker@3.1.1(vite@6.2.5(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1))':
dependencies:
'@vitest/spy': 3.1.1
estree-walker: 3.0.3
magic-string: 0.30.17
optionalDependencies:
- vite: 6.2.4(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)
+ vite: 6.2.5(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)
'@vitest/pretty-format@3.1.1':
dependencies:
@@ -18613,32 +18408,6 @@ snapshots:
'@rollup/rollup-win32-x64-msvc': 4.38.0
fsevents: 2.3.3
- rollup@4.39.0:
- dependencies:
- '@types/estree': 1.0.7
- optionalDependencies:
- '@rollup/rollup-android-arm-eabi': 4.39.0
- '@rollup/rollup-android-arm64': 4.39.0
- '@rollup/rollup-darwin-arm64': 4.39.0
- '@rollup/rollup-darwin-x64': 4.39.0
- '@rollup/rollup-freebsd-arm64': 4.39.0
- '@rollup/rollup-freebsd-x64': 4.39.0
- '@rollup/rollup-linux-arm-gnueabihf': 4.39.0
- '@rollup/rollup-linux-arm-musleabihf': 4.39.0
- '@rollup/rollup-linux-arm64-gnu': 4.39.0
- '@rollup/rollup-linux-arm64-musl': 4.39.0
- '@rollup/rollup-linux-loongarch64-gnu': 4.39.0
- '@rollup/rollup-linux-powerpc64le-gnu': 4.39.0
- '@rollup/rollup-linux-riscv64-gnu': 4.39.0
- '@rollup/rollup-linux-riscv64-musl': 4.39.0
- '@rollup/rollup-linux-s390x-gnu': 4.39.0
- '@rollup/rollup-linux-x64-gnu': 4.39.0
- '@rollup/rollup-linux-x64-musl': 4.39.0
- '@rollup/rollup-win32-arm64-msvc': 4.39.0
- '@rollup/rollup-win32-ia32-msvc': 4.39.0
- '@rollup/rollup-win32-x64-msvc': 4.39.0
- fsevents: 2.3.3
-
rou3@0.5.1: {}
rtlcss@4.3.0:
@@ -19576,7 +19345,7 @@ snapshots:
debug: 4.4.0
es-module-lexer: 1.6.0
pathe: 1.1.2
- vite: 6.2.5(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)
+ vite: 6.2.5(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)
transitivePeerDependencies:
- '@types/node'
- jiti
@@ -19612,13 +19381,13 @@ snapshots:
- tsx
- yaml
- vite-tsconfig-paths@5.1.4(typescript@5.7.3)(vite@6.2.5(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)):
+ vite-node@3.1.1(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1):
dependencies:
cac: 6.7.14
debug: 4.4.0
es-module-lexer: 1.6.0
pathe: 2.0.3
- vite: 6.2.4(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)
+ vite: 6.2.5(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)
transitivePeerDependencies:
- '@types/node'
- jiti
@@ -19633,22 +19402,22 @@ snapshots:
- tsx
- yaml
- vite-tsconfig-paths@5.1.4(typescript@5.7.3)(vite@6.2.4(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)):
+ vite-tsconfig-paths@5.1.4(typescript@5.7.3)(vite@6.2.5(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)):
dependencies:
debug: 4.4.0
globrex: 0.1.2
tsconfck: 3.1.5(typescript@5.7.3)
optionalDependencies:
- vite: 6.2.5(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)
+ vite: 6.2.5(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)
transitivePeerDependencies:
- supports-color
- typescript
- vite@6.2.4(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1):
+ vite@6.2.5(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1):
dependencies:
esbuild: 0.25.2
postcss: 8.5.3
- rollup: 4.39.0
+ rollup: 4.38.0
optionalDependencies:
'@types/node': 22.13.16
fsevents: 2.3.3
@@ -19657,13 +19426,13 @@ snapshots:
terser: 5.39.0
yaml: 2.7.1
- vite@6.2.5(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1):
+ vite@6.2.5(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1):
dependencies:
esbuild: 0.25.2
postcss: 8.5.3
rollup: 4.38.0
optionalDependencies:
- '@types/node': 22.13.16
+ '@types/node': 22.14.0
fsevents: 2.3.3
jiti: 1.21.7
lightningcss: 1.29.3
@@ -19673,7 +19442,7 @@ snapshots:
vitest@3.1.1(@types/debug@4.1.12)(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1):
dependencies:
'@vitest/expect': 3.1.1
- '@vitest/mocker': 3.1.1(vite@6.2.4(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1))
+ '@vitest/mocker': 3.1.1(vite@6.2.5(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1))
'@vitest/pretty-format': 3.1.1
'@vitest/runner': 3.1.1
'@vitest/snapshot': 3.1.1
@@ -19689,7 +19458,7 @@ snapshots:
tinyexec: 0.3.2
tinypool: 1.0.2
tinyrainbow: 2.0.0
- vite: 6.2.4(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)
+ vite: 6.2.5(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)
vite-node: 3.1.1(@types/node@22.13.16)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)
why-is-node-running: 2.3.0
optionalDependencies:
@@ -19712,7 +19481,7 @@ snapshots:
vitest@3.1.1(@types/debug@4.1.12)(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1):
dependencies:
'@vitest/expect': 3.1.1
- '@vitest/mocker': 3.1.1(vite@6.2.4(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1))
+ '@vitest/mocker': 3.1.1(vite@6.2.5(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1))
'@vitest/pretty-format': 3.1.1
'@vitest/runner': 3.1.1
'@vitest/snapshot': 3.1.1
@@ -19728,7 +19497,7 @@ snapshots:
tinyexec: 0.3.2
tinypool: 1.0.2
tinyrainbow: 2.0.0
- vite: 6.2.4(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)
+ vite: 6.2.5(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)
vite-node: 3.1.1(@types/node@22.14.0)(jiti@1.21.7)(lightningcss@1.29.3)(terser@5.39.0)(yaml@2.7.1)
why-is-node-running: 2.3.0
optionalDependencies:
From 2ab7ffd5ba6ef0f22cf87d2ee36af95dcce51a35 Mon Sep 17 00:00:00 2001
From: Sven Verweij <37927107+SvenVw@users.noreply.github.com>
Date: Mon, 7 Apr 2025 15:32:02 +0200
Subject: [PATCH 26/33] Various fixes due to merge with development
---
fdm-app/app/components/custom/field/form.tsx | 21 ++++---
.../farm.$b_id_farm.$calendar.field.new.tsx | 63 +++++++++++++------
2 files changed, 58 insertions(+), 26 deletions(-)
diff --git a/fdm-app/app/components/custom/field/form.tsx b/fdm-app/app/components/custom/field/form.tsx
index 4c5d0004d..e904f0723 100644
--- a/fdm-app/app/components/custom/field/form.tsx
+++ b/fdm-app/app/components/custom/field/form.tsx
@@ -5,8 +5,8 @@ import {
DialogFooter,
DialogHeader,
DialogTitle,
-} from "@/components/ui/dialog"
-import { Button } from "@/components/ui/button"
+} from "~/components/ui/dialog"
+import { Button } from "~/components/ui/button"
import { RemixFormProvider, useRemixForm } from "remix-hook-form"
import { useEffect, useState } from "react"
import {
@@ -16,13 +16,13 @@ import {
FormItem,
FormLabel,
FormMessage,
-} from "@/components/ui/form"
-import { Input } from "@/components/ui/input"
+} from "~/components/ui/form"
+import { Input } from "~/components/ui/input"
import type { z } from "zod"
import { zodResolver } from "@hookform/resolvers/zod"
import { FormSchema } from "./schema"
-import { Combobox } from "../combobox"
-import { LoadingSpinner } from "@/components/custom/loadingspinner"
+import { Combobox } from "~/components/custom/combobox"
+import { LoadingSpinner } from "~/components/custom/loadingspinner"
import type { Feature, Polygon } from "geojson"
import { Form } from "react-router"
@@ -42,7 +42,8 @@ export default function FieldDetailsDialog({
fieldNameDefault,
}: FieldDetailsDialogProps) {
const b_lu_catalogue = `nl_${field.properties?.b_lu_catalogue ?? ""}`
- const [selectedCultivation, setSelectedCultivation] = useState(b_lu_catalogue);
+ const [selectedCultivation, setSelectedCultivation] =
+ useState(b_lu_catalogue)
const form = useRemixForm>({
mode: "onTouched",
@@ -71,7 +72,11 @@ export default function FieldDetailsDialog({
-