Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
8cc8c2e
feat: Improve DatePickers and Forms to use contextual default dates b…
SvenVw Mar 9, 2026
719626f
fix: parsing dutch date notations
SvenVw Mar 9, 2026
4b9ebd1
refactor: Increase navigation progress time from 300 to 500ms
SvenVw Mar 9, 2026
ad1ebbf
fix: Do not show the NavigationProgress for pages with their own load…
SvenVw Mar 9, 2026
bb6703b
fix: going to Fertilizers page does not reset the selected calender y…
SvenVw Mar 9, 2026
06fafd1
fix: link for going back for fertilizer application modification goes…
SvenVw Mar 9, 2026
5ffc4b8
docs: fix typo
SvenVw Mar 9, 2026
e55337f
fix: potential NaN issue when calendar is non-numeric (e.g., "all")
SvenVw Mar 9, 2026
8fd47a6
fix: Make the saved fertilizer draft calendar-aware
SvenVw Mar 9, 2026
1284d9f
fix: Add hideProgress to the effect's dependency array
SvenVw Mar 9, 2026
c3dfb27
fix: useEffect dependency
SvenVw Mar 9, 2026
c6dfd07
feat: At the Sentry metric for NavigationProgress include a tag for t…
SvenVw Mar 9, 2026
ac0342d
fix: added a useEffect in useHarvestRemixForm
SvenVw Mar 9, 2026
b2d17cd
fix: set default date
SvenVw Mar 9, 2026
65ebf42
fix: farm nitrogen balance to exclude nitrate leaching
SvenVw Mar 9, 2026
4a3bd50
chore: bump version of packages for release
github-actions[bot] Mar 9, 2026
a70558c
refactor: implement review feedback
SvenVw Mar 9, 2026
9d5050a
Revert "chore: bump version of packages for release"
SvenVw Mar 9, 2026
7110a53
chore: bump version of packages for release
github-actions[bot] Mar 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions fdm-app/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
# Changelog fdm-app

## 0.28.1

### Patch Changes

- [#495](https://github.com/nmi-agro/fdm/pull/495) [`9d5050a`](https://github.com/nmi-agro/fdm/commit/9d5050aef5f70636be638d2f1a4027ccd22f4189) Thanks [@SvenVw](https://github.com/SvenVw)! - Do not show the NavigationProgress for pages with their own loaders, like uploading files

- [#495](https://github.com/nmi-agro/fdm/pull/495) [`9d5050a`](https://github.com/nmi-agro/fdm/commit/9d5050aef5f70636be638d2f1a4027ccd22f4189) Thanks [@SvenVw](https://github.com/SvenVw)! - Increase navigation progress time from 300 to 500ms

- [#495](https://github.com/nmi-agro/fdm/pull/495) [`9d5050a`](https://github.com/nmi-agro/fdm/commit/9d5050aef5f70636be638d2f1a4027ccd22f4189) Thanks [@SvenVw](https://github.com/SvenVw)! - Improve DatePickers and Forms to use contextual default dates based on the selected calendar year. Forms now default to domain-specific dates (e.g., March 1st for fertilizer and cultivation-specific harvest defaults in non-current years), and DatePickers now resolve partial text entries (like "15 april") to the active calendar year instead of the current real-world year.

- [#495](https://github.com/nmi-agro/fdm/pull/495) [`9d5050a`](https://github.com/nmi-agro/fdm/commit/9d5050aef5f70636be638d2f1a4027ccd22f4189) Thanks [@SvenVw](https://github.com/SvenVw)! - Fix that link for going back for fertilizer application modification goes back to rotation

- [#495](https://github.com/nmi-agro/fdm/pull/495) [`9d5050a`](https://github.com/nmi-agro/fdm/commit/9d5050aef5f70636be638d2f1a4027ccd22f4189) Thanks [@SvenVw](https://github.com/SvenVw)! - Fix that going to Fertilizers page does not reset the selected calendar year to current year

- [#495](https://github.com/nmi-agro/fdm/pull/495) [`9d5050a`](https://github.com/nmi-agro/fdm/commit/9d5050aef5f70636be638d2f1a4027ccd22f4189) Thanks [@SvenVw](https://github.com/SvenVw)! - At the Sentry metric for NavigationProgress include a tag for the page

- Updated dependencies [[`9d5050a`](https://github.com/nmi-agro/fdm/commit/9d5050aef5f70636be638d2f1a4027ccd22f4189)]:
- @nmi-agro/fdm-calculator@0.12.1

## 0.28.0

### Minor Changes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Plus } from "lucide-react"
import { useEffect, useRef, useState } from "react"
import { useFetcher, useLocation, useNavigation, useParams } from "react-router"
import { useFieldFertilizerFormStore } from "@/app/store/field-fertilizer-form"
import { useCalendarStore } from "~/store/calendar"
import { Button } from "~/components/ui/button"
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card"
import {
Expand Down Expand Up @@ -75,11 +76,13 @@ export function FertilizerApplicationCard({
}, [navigation.state])

const fieldFertilizerFormStore = useFieldFertilizerFormStore()
const { calendar } = useCalendarStore()
const savedFormValues =
params.b_id_farm && b_id_or_b_lu_catalogue
? fieldFertilizerFormStore.load(
params.b_id_farm,
b_id_or_b_lu_catalogue,
calendar,
)
: null

Expand All @@ -98,6 +101,7 @@ export function FertilizerApplicationCard({
fieldFertilizerFormStore.delete(
params.b_id_farm || "",
b_id_or_b_lu_catalogue || "",
calendar,
)
}
}, [
Expand Down Expand Up @@ -139,6 +143,7 @@ export function FertilizerApplicationCard({
fieldFertilizerFormStore.delete(
params.b_id_farm,
b_id_or_b_lu_catalogue,
calendar,
)
}

Expand Down
33 changes: 31 additions & 2 deletions fdm-app/app/components/blocks/fertilizer-applications/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import type { Navigation } from "react-router"
import { Form, useNavigate, useSearchParams } from "react-router"
import { RemixFormProvider, useRemixForm } from "remix-hook-form"
import { useFieldFertilizerFormStore } from "@/app/store/field-fertilizer-form"
import { useCalendarStore } from "~/store/calendar"
import { getContextualDate } from "~/lib/calendar"
import { Combobox } from "~/components/custom/combobox"
import { DatePicker } from "~/components/custom/date-picker-v2"
import { Button } from "~/components/ui/button"
Expand Down Expand Up @@ -78,6 +80,7 @@ export function FertilizerApplicationForm<T extends typeof FormSchemaPartial>({
const navigate = useNavigate()
const [searchParams] = useSearchParams()
const formId = useId()
const { calendar } = useCalendarStore()
const form = useRemixForm<FieldFertilizerFormValues>({
mode: "onTouched",
resolver: zodResolver(
Expand All @@ -94,7 +97,7 @@ export function FertilizerApplicationForm<T extends typeof FormSchemaPartial>({
? fertilizerApplication.p_app_date
: exampleFertilizerApplication
? undefined
: new Date(),
: getContextualDate(calendar, 3, 1),
},
submitConfig: {
method: fertilizerApplication ? "PUT" : "POST",
Expand All @@ -113,13 +116,32 @@ export function FertilizerApplicationForm<T extends typeof FormSchemaPartial>({
}
}, [p_id, fertilizerApplication, form.setValue])

useEffect(() => {
const currentValue = form.getValues("p_app_date")
const { isDirty } = form.getFieldState("p_app_date")
if (
!fertilizerApplication?.p_app_date &&
!exampleFertilizerApplication &&
!currentValue &&
!isDirty
) {
form.setValue("p_app_date", getContextualDate(calendar, 3, 1))
}
}, [
calendar,
exampleFertilizerApplication,
fertilizerApplication?.p_app_date,
form.setValue,
])
Comment thread
coderabbitai[bot] marked this conversation as resolved.

const fieldFertilizerFormStore = useFieldFertilizerFormStore()

useEffect(() => {
if (b_id_farm && b_id_or_b_lu_catalogue) {
const savedFormValues = fieldFertilizerFormStore.load(
b_id_farm,
b_id_or_b_lu_catalogue,
calendar,
Comment thread
coderabbitai[bot] marked this conversation as resolved.
)
if (savedFormValues) {
for (const [k, v] of Object.entries(savedFormValues)) {
Expand All @@ -137,6 +159,7 @@ export function FertilizerApplicationForm<T extends typeof FormSchemaPartial>({
b_id_or_b_lu_catalogue,
form.setValue,
fieldFertilizerFormStore.load,
calendar,
])

useEffect(() => {
Expand All @@ -156,13 +179,18 @@ export function FertilizerApplicationForm<T extends typeof FormSchemaPartial>({

useEffect(() => {
if (form.formState.isSubmitSuccessful) {
fieldFertilizerFormStore.delete(b_id_farm, b_id_or_b_lu_catalogue)
fieldFertilizerFormStore.delete(
b_id_farm,
b_id_or_b_lu_catalogue,
calendar,
)
}
}, [
form.formState.isSubmitSuccessful,
b_id_farm,
b_id_or_b_lu_catalogue,
fieldFertilizerFormStore.delete,
calendar,
])

function handleManageFertilizers(_e: MouseEvent<HTMLButtonElement>) {
Expand All @@ -171,6 +199,7 @@ export function FertilizerApplicationForm<T extends typeof FormSchemaPartial>({
b_id_farm,
b_id_or_b_lu_catalogue,
form.getValues(),
calendar,
)
}
navigate(
Expand Down
57 changes: 53 additions & 4 deletions fdm-app/app/components/blocks/harvest/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useEffect, useState } from "react"
import { Controller } from "react-hook-form"
import { Form, useFetcher, useNavigate } from "react-router"
import { RemixFormProvider, useRemixForm } from "remix-hook-form"
import type { UseRemixFormReturn } from "remix-hook-form"
import type { z } from "zod"
import { cn } from "@/app/lib/utils"
import { DatePicker } from "~/components/custom/date-picker-v2"
Expand Down Expand Up @@ -34,6 +35,7 @@ import {
} from "~/components/ui/field"
import { Input } from "~/components/ui/input"
import { Spinner } from "~/components/ui/spinner"
import { useCalendarStore } from "~/store/calendar"
import { getHarvestParameterLabel } from "./parameters"
import { FormSchema } from "./schema"

Expand All @@ -42,6 +44,7 @@ type HarvestFormDialogProps = {
exampleHarvestableAnalysis?: Partial<HarvestableAnalysis>
example_b_lu_harvest_date?: Date | null
b_lu_harvest_date: Date | string | null | undefined // Changed to allow Date or string
b_date_harvest_default?: string | null // MM-dd format from cultivation catalogue
b_lu_yield: number | undefined
b_lu_yield_fresh: number | undefined
b_lu_yield_bruto: number | undefined
Expand All @@ -62,6 +65,7 @@ type HarvestFormDialogProps = {
function useHarvestRemixForm({
harvestParameters,
b_lu_harvest_date,
b_date_harvest_default,
b_lu_yield,
b_lu_yield_fresh,
b_lu_yield_bruto,
Expand All @@ -77,6 +81,37 @@ function useHarvestRemixForm({
example_b_lu_harvest_date,
handleConfirmation,
}: HarvestFormDialogProps) {
const { calendar } = useCalendarStore()
const currentYear = new Date().getFullYear()
const parsedCalendar = calendar ? Number(calendar) : Number.NaN
const calendarYear = Number.isNaN(parsedCalendar)
? currentYear
: parsedCalendar
Comment thread
coderabbitai[bot] marked this conversation as resolved.

// Compute default harvest date from catalogue's MM-dd + calendar year
// Only apply when creating a new harvest (no existing date) and not in current year
function getDefaultHarvestDate(): Date | undefined {
if (b_lu_harvest_date) {
return new Date(b_lu_harvest_date)
}
if (example_b_lu_harvest_date) {
// Bulk edit: leave empty
return undefined
}
if (calendarYear === currentYear) {
// Current year: leave empty (calendar opens at today)
return undefined
}
if (b_date_harvest_default) {
// Parse MM-dd and combine with calendar year
const [month, day] = b_date_harvest_default.split("-").map(Number)
if (month && day) {
return new Date(calendarYear, month - 1, day)
}
}
return undefined
}

const form = useRemixForm<z.infer<typeof FormSchema>>({
mode: "onSubmit",
resolver: async (values, bypass, options) => {
Expand Down Expand Up @@ -115,9 +150,7 @@ function useHarvestRemixForm({
return validation
},
defaultValues: {
b_lu_harvest_date: b_lu_harvest_date
? new Date(b_lu_harvest_date)
: undefined,
b_lu_harvest_date: getDefaultHarvestDate(),
b_lu_yield: harvestParameters.includes("b_lu_yield")
? b_lu_yield
: undefined,
Expand Down Expand Up @@ -151,6 +184,22 @@ function useHarvestRemixForm({
},
})

// When the calendar store is populated after initial render, re-evaluate the
// default harvest date, but only if the user has not already entered a value.
useEffect(() => {
const currentValue = form.getValues("b_lu_harvest_date")
const { isDirty } = form.getFieldState("b_lu_harvest_date")
if (
!b_lu_harvest_date &&
!example_b_lu_harvest_date &&
!currentValue &&
!isDirty
) {
form.setValue("b_lu_harvest_date", getDefaultHarvestDate())
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [calendar])
Comment thread
coderabbitai[bot] marked this conversation as resolved.

return form
}

Expand All @@ -162,7 +211,7 @@ function HarvestFields({
example_b_lu_harvest_date,
b_lu_harvest_date,
}: HarvestFormDialogProps & {
form: ReturnType<typeof useHarvestRemixForm>
form: UseRemixFormReturn<z.infer<typeof FormSchema>>
className: React.ComponentProps<typeof FieldGroup>["className"]
}) {
const formatted_b_lu_harvest_date = example_b_lu_harvest_date
Expand Down
7 changes: 7 additions & 0 deletions fdm-app/app/components/blocks/soil/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import {
} from "~/components/ui/select"
import { Spinner } from "~/components/ui/spinner"
import { cn } from "~/lib/utils"
import { getContextualDate } from "~/lib/calendar"
import { useCalendarStore } from "~/store/calendar"

export function SoilAnalysisForm(props: {
soilAnalysis: SoilAnalysis | undefined
Expand All @@ -35,6 +37,7 @@ export function SoilAnalysisForm(props: {
}) {
const { soilAnalysis, soilParameterDescription, editable = true } = props

const { calendar } = useCalendarStore()
const defaultValues: {
[key: string]: string | number | Date | undefined | null
} = {}
Expand All @@ -50,6 +53,10 @@ export function SoilAnalysisForm(props: {
defaultValue = ""
}

if (defaultValue === undefined && x.type === "date" && !soilAnalysis) {
defaultValue = getContextualDate(calendar, 2, 1)
}

defaultValues[x.parameter] = defaultValue
}
defaultValues.a_id = undefined
Expand Down
Loading