diff --git a/fdm-app/CHANGELOG.md b/fdm-app/CHANGELOG.md index 96eacc5c4..0ff0b04be 100644 --- a/fdm-app/CHANGELOG.md +++ b/fdm-app/CHANGELOG.md @@ -1,5 +1,26 @@ # Changelog fdm-app +## 0.4.0 + +### Minor Changes + +- bee0e62: Add `FertilizerApplicationsForm` to list, add and delete fertilizer applications +- 4112897: Remove selection of fertilizers for acquiring but select all fertilizers + +### Patch Changes + +- Updated dependencies [7af3fda] +- Updated dependencies [bc4e75f] +- Updated dependencies [a948c61] +- Updated dependencies [efa423d] +- Updated dependencies [b0c001e] +- Updated dependencies [6ef3d44] +- Updated dependencies [61da12f] +- Updated dependencies [5be0abc] +- Updated dependencies [4189f5d] + - @svenvw/fdm-core@0.7.0 + - @svenvw/fdm-data@1.0.0 + ## 0.3.1 ### Patch Changes diff --git a/fdm-app/app/components/blocks/farm.tsx b/fdm-app/app/components/blocks/farm.tsx index 2173ba79f..6ecd11dc0 100644 --- a/fdm-app/app/components/blocks/farm.tsx +++ b/fdm-app/app/components/blocks/farm.tsx @@ -1,4 +1,3 @@ -import { useState } from "react"; import { Form } from "react-router"; import { zodResolver } from "@hookform/resolvers/zod" import { useRemixForm, RemixFormProvider } from "remix-hook-form" @@ -14,7 +13,6 @@ import { CardTitle, } from "@/components/ui/card" import { Input } from "@/components/ui/input" -import { Label } from "@/components/ui/label" import { FormControl, FormDescription, @@ -23,11 +21,8 @@ import { FormLabel, FormMessage, } from "@/components/ui/form" - -import { MultiSelect } from "@/components/custom/multi-select" import { LoadingSpinner } from "../custom/loadingspinner"; - export interface fertilizersListType { value: string label: string @@ -35,10 +30,6 @@ export interface fertilizersListType { export interface farmType { b_name_farm: string | null - b_fertilizers_organic: string[] - b_fertilizers_mineral: string[] - organicFertilizersList: fertilizersListType[] - mineralFertilizersList: fertilizersListType[] action: "/app/addfarm/new" FormSchema: z.Schema } @@ -49,11 +40,7 @@ export interface farmType { * @returns The JSX element representing the farm form. */ export function Farm(props: farmType) { - const organicFertilizersList = props.organicFertilizersList - const mineralFertilizersList = props.mineralFertilizersList const FormSchema = props.FormSchema - const [selectedOrganicFertilizers, setOrganicFertilizers] = useState(props.b_fertilizers_organic); - const [selectedMineralFertilizers, setMineralFertilizers] = useState(props.b_fertilizers_mineral); const form = useRemixForm>({ mode: "onTouched", @@ -90,36 +77,9 @@ export function Farm(props: farmType) { - )} /> -
- - -
-
- - -
diff --git a/fdm-app/app/components/custom/combobox-fertilizers.tsx b/fdm-app/app/components/custom/combobox-fertilizers.tsx deleted file mode 100644 index 3a2d755bf..000000000 --- a/fdm-app/app/components/custom/combobox-fertilizers.tsx +++ /dev/null @@ -1,86 +0,0 @@ - - -import { Button } from "@/components/ui/button" -import { Separator } from "../ui/separator" -import { Input } from "../ui/input" -import { Label } from "../ui/label" - -import { Combobox } from "../custom/combobox" - -export function ComboboxFertilizers(props: { options: { value: string, label: string }[], defaultValue?: string }) { - - return ( -
-
-
- - -
-
- - -
-
- - -
-
- -
-
-
- -
- {/*
Meststoffen
*/} -
-
-
-

- Runderdrijfmest -

- {/*

m@example.com

*/} -
-
-

- 30 ton / ha -

-
-
-

- 2024-04-01 -

-
-
- -
- {/*
*/} -
-
-
-

- Runderdrijfmest -

- {/*

m@example.com

*/} -
-
-

- 30 ton / ha -

-
-
-

- 2024-04-01 -

-
-
- -
-
-
-
-
- - ) -} \ No newline at end of file diff --git a/fdm-app/app/components/custom/combobox.tsx b/fdm-app/app/components/custom/combobox.tsx index 7c88e51be..2a207d279 100644 --- a/fdm-app/app/components/custom/combobox.tsx +++ b/fdm-app/app/components/custom/combobox.tsx @@ -1,4 +1,4 @@ -import { useState } from "react" +import { ReactNode, useState } from "react" import { Button } from "@/components/ui/button" import { @@ -14,6 +14,14 @@ import { PopoverContent, PopoverTrigger, } from "@/components/ui/popover" +import { + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form" import { ChevronsUpDown, Check } from "lucide-react" import { cn } from "@/lib/utils" @@ -24,71 +32,76 @@ type optionType = { interface ComboboxProps { options: { value: string, label: string }[] - value?: string - defaultValue?: string - onChange?: (value: string) => void - onOpenChange?: (open: boolean) => void + form: any + name: string + label: ReactNode } export function Combobox({ options, - value: controlledValue, - defaultValue, - onChange, - onOpenChange + form, + name, + label }: ComboboxProps) { const [open, setOpen] = useState(false) - const [internalValue, setInternalValue] = useState(defaultValue ?? "") - - const value = controlledValue ?? internalValue - const handleValueChange = (newValue: string) => { - setInternalValue(newValue) - onChange?.(newValue) - } - const name = "combobox" return ( - - - - - - - - - Niks gevonden - - {options.map((option: optionType) => ( - { - setInternalValue(currentValue === value ? "" : currentValue) - setOpen(false) - }} + ( + + {label} + + + + + + + + + + + Niks gevonden + + {options.map((option: optionType) => ( + { + form.setValue(name, option.value) + setOpen(false) + }} + > +

{option.label}

+ +
+ ))} +
+
+
+
+
+ + +
+ )} + /> ) } \ No newline at end of file diff --git a/fdm-app/app/components/custom/fertilizer-applications.tsx b/fdm-app/app/components/custom/fertilizer-applications.tsx new file mode 100644 index 000000000..c574e30ed --- /dev/null +++ b/fdm-app/app/components/custom/fertilizer-applications.tsx @@ -0,0 +1,233 @@ +import { Form, useFetcher } from "react-router" +import { format } from "date-fns" +import { zodResolver } from "@hookform/resolvers/zod" +import { useRemixForm, RemixFormProvider } from "remix-hook-form" +import { z } from "zod" + +// Components +import { CalendarIcon } from "lucide-react" +import { Button } from "@/components/ui/button" +import { Separator } from "@/components/ui/separator" +import { Input } from "@/components/ui/input" +import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover" +import { Calendar } from "@/components/ui/calendar" +import { + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form" +import { Combobox } from "@/components/custom/combobox" + +import { cn } from "@/lib/utils" +import { LoadingSpinner } from "./loadingspinner" +import { useEffect } from "react" + +export const FormSchema = z.object({ + p_app_amount: z.coerce.number({ + required_error: "Hoeveelheid is verplicht", + invalid_type_error: "Hoeveelheid moet een getal zijn", + }).positive({ + message: "Hoeveelheid moet positief zijn", + }).finite({ + message: "Hoeveelheid moet een geheel getal zijn", + }).safe({ + message: "Hoeveelheid moet een safe getal zijn", + }), + p_app_date: z.coerce.date({ + required_error: "Datum is verplicht", + invalid_type_error: "Datum is ongeldig", + }), + p_id: z.coerce.string({ // TODO: Validate against the options that are available + required_error: "Keuze van meststof is verplicht", + invalid_type_error: "Meststof is ongeldig", + }) +}) +interface FertilizerApplication { + p_app_id: string; + p_app_ids: string[]; + p_name_nl: string; + p_app_amount: number; + p_app_date: Date; + } + + interface FertilizerOption { + value: string; + label: string; + } + + interface FertilizerApplicationsFormProps { + fertilizerApplications: FertilizerApplication[]; + options: FertilizerOption[]; + defaultValue?: string; + action: string; + } + +export function FertilizerApplicationsForm(props: FertilizerApplicationsFormProps) { + const fetcher = useFetcher(); + + const form = useRemixForm>({ + mode: "onTouched", + resolver: zodResolver(FormSchema), + defaultValues: { + p_app_amount: undefined, + p_app_date: new Date(), + } + }) + + useEffect(() => { + if (form.formState.isSubmitSuccessful) { + form.reset() + } + }, [form.formState]) + + const handleDelete = (p_app_ids: string[]) => { + if (fetcher.state === 'submitting') return; + + fetcher.submit( + { p_app_ids }, + { method: "delete", action: props.action } + ); + }; + + return ( +
+ +
+
+
+
+ {/* */} + Meststof*} + /> +
+
+ ( + + Hoeveelheid* + + + + + + + )} + /> +
+ +
+ ( + + Datum + + + + + + + + + // date > new Date() || date < new Date("1900-01-01") + // } + initialFocus + /> + + + + + + )} + /> +
+
+ +
+
+
+
+
+
+ +
+ {/*
Meststoffen
*/} +
+ {props.fertilizerApplications.map((application) => ( +
+
+

+ {application.p_name_nl} +

+ {/*

m@example.com

*/} +
+
+

+ {application.p_app_amount} ton / ha +

+
+
+

+ {format(application.p_app_date, "yyyy-MM-dd")} +

+
+
+ +
+ +
+ ))} +
+
+
+
+ ) +} \ No newline at end of file diff --git a/fdm-app/app/components/ui/pagination.tsx b/fdm-app/app/components/ui/pagination.tsx new file mode 100644 index 000000000..e9120dcc8 --- /dev/null +++ b/fdm-app/app/components/ui/pagination.tsx @@ -0,0 +1,116 @@ +import * as React from "react" +import { cn } from "~/lib/utils" +import { ButtonProps, buttonVariants } from "~/components/ui/button" +import { ChevronLeftIcon, ChevronRightIcon, DotsHorizontalIcon } from "@radix-ui/react-icons" + +const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => ( +