Skip to content

Enable updating of fertilizer applications#311

Merged
SvenVw merged 15 commits into
developmentfrom
FDM307
Oct 31, 2025
Merged

Enable updating of fertilizer applications#311
SvenVw merged 15 commits into
developmentfrom
FDM307

Conversation

@BoraIneviNMI
Copy link
Copy Markdown
Collaborator

@BoraIneviNMI BoraIneviNMI commented Oct 28, 2025

New features:

  • The user can use the new edit button to adjust the details of an existing fertilizer application event.
  • The aim is to reduce the chances of making errors, which could happen since the users previously had to delete an existing application and fill all the details even if they didn't want to change them.

Closes #307

Summary by CodeRabbit

  • New Features

    • Edit existing fertilizer applications per row and in bulk; forms pre-fill when editing and save uses update requests.
  • UI/Style

    • Added per-row "Wijzig" button, increased grid space; dialog title/description and button copy switch between add vs. edit modes.
  • Behavior

    • Drafts load conditionally and stale drafts are cleaned up; edit flows preserve/restore amount and method and clear state on close.
  • Chores

    • Release bump noting edit capability.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Oct 28, 2025

🦋 Changeset detected

Latest commit: 518aaf7

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@svenvw/fdm-app Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Oct 28, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Adds edit/update support for fertilizer applications: UI gains per-row edit controls and dialog/edit state; form accepts an optional fertilizerApplication and uses FormSchemaModify for PUT updates; schemas/types updated; route handlers added PUT flows calling updateFertilizerApplication.

Changes

Cohort / File(s) Summary
Card / UI
fdm-app/app/components/blocks/fertilizer-applications/card.tsx
Adds editedFertilizerApplication state and handleEdit, per-row "Wijzig" button, expands grid to 6 columns, conditional dialog open (edit vs add), clears edited state on dialog close and idle navigation, and passes fertilizerApplication to the form.
Form component
fdm-app/app/components/blocks/fertilizer-applications/form.tsx
Adds fertilizerApplication prop; switches resolver/schema to FormSchemaModify when editing and FormSchema when creating; pre-fills p_app_id, p_id, p_app_method, p_app_amount, p_app_date; uses PUT for edits and POST for creates; updates effects and submit label.
Schemas & types
fdm-app/app/components/blocks/fertilizer-applications/formschema.tsx
Adds FormSchemaModify (extends FormSchema with required p_app_id) and exports FieldFertilizerFormValues including optional p_app_id.
Store typing
fdm-app/app/store/field-fertilizer-form.tsx
Replaces local schema-derived FieldFertilizerFormValues type with import from formschema.
Route handlers (field)
fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx
Adds PUT handling using FormSchemaModify, validates p_app_id, calls updateFertilizerApplication, and returns localized success message alongside existing POST/DELETE logic.
Route handlers (create/aggregate)
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
Adds PUT handling to update multiple p_app_ids, maps catalogue IDs to farm p_id when aggregating, imports FormSchemaModify and updateFertilizerApplication, and exposes FormSchemaModify in exports.
Core API usage
@svenvw/fdm-core
Adds/uses updateFertilizerApplication for update flows invoked by PUT handlers.
Changeset
.changeset/free-onions-rest.md
Bumps package version and documents edit support for fertilizer applications.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Card as Card component
    participant Dialog as FertilizerApplicationForm
    participant Route as Route handler
    participant Core as fdm-core

    rect rgb(232,255,240)
    Note over User,Card: Edit flow
    User->>Card: Click "Wijzig" on a row
    Card->>Card: set editedFertilizerApplication
    Card->>Dialog: Open dialog with fertilizerApplication prop
    User->>Dialog: Modify fields & submit (PUT)
    Dialog->>Route: PUT /... (FormSchemaModify incl. p_app_id)
    Route->>Core: updateFertilizerApplication(p_app_id, values)
    Core-->>Route: Success
    Route-->>Dialog: Redirect / Toast
    Dialog->>Card: Clear editedFertilizerApplication
    end

    rect rgb(230,240,255)
    Note over User,Card: Create flow
    User->>Card: Click "Voeg toe"
    Card->>Dialog: Open empty form
    User->>Dialog: Submit (POST)
    Dialog->>Route: POST /... (FormSchema)
    Route->>Core: addFertilizerApplication(values)
    Core-->>Route: Success
    Route-->>Dialog: Redirect / Toast
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pay extra attention to: conditional resolver/schema selection and default values in form.tsx; propagation and clearing of editedFertilizerApplication and dialog open/idle logic in card.tsx; correct parsing/validation of p_app_id and bulk update logic in both route handlers; import/type updates after moving FieldFertilizerFormValues.

Possibly related PRs

Suggested reviewers

  • gerardhros

Poem

🐰 I nibble keys and hop to code delight,
Rows pre-filled now glow in soft moonlight.
Click "Wijzig", change, then save with cheer—
No more delete-and-recreate here. 🌱✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "Enable updating of fertilizer applications" directly and clearly describes the primary objective of the pull request. It accurately reflects the main change—implementing edit functionality for fertilizer applications. The title is concise, specific, and avoids vague terms. It would allow a teammate scanning commit history to immediately understand that this change adds update/edit capability to the fertilizer application feature.
Linked Issues Check ✅ Passed The pull request successfully addresses the core requirements from issue #307. The implementation enables users to click an edit button on existing fertilizer applications, which opens a dialog with a pre-populated form. The form component now accepts a fertilizerApplication prop and conditionally uses FormSchemaModify for edits versus FormSchema for creates. The route handlers have been extended with PUT support that calls updateFertilizerApplication from fdm-core, matching the proposed solution. The submit button dynamically shows "Opslaan" (Save) when in edit mode, and the form pre-fills all relevant fields from the existing application, fulfilling the requirement to pre-populate the form with current values.
Out of Scope Changes Check ✅ Passed All changes in the pull request are directly related to enabling fertilizer application updates as specified in issue #307. The modifications to card.tsx, form.tsx, formschema.tsx, and route handlers all support the edit workflow. The type refactoring in formschema.tsx and field-fertilizer-form.tsx (moving FieldFertilizerFormValues to a shared module) is a necessary structural change that supports the new edit functionality. The addition of PUT support to both individual and bulk fertilizer routes is a direct extension of the same feature. No unrelated changes to formatting, infrastructure, dependencies, or other features are present.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d414e92 and 518aaf7.

📒 Files selected for processing (2)
  • fdm-app/app/components/blocks/fertilizer-applications/form.tsx (6 hunks)
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx (3 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot added branch:development Issue only affecting development, not the main branch (yet) enhancement New feature or request fdm-app labels Oct 28, 2025
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (2)
fdm-app/app/components/blocks/fertilizer-applications/formschema.tsx (1)

27-33: Validate p_app_id is non-empty (and format, if known).

Ensure no empty string sneaks through; optionally enforce UUID/ULID if applicable.

Apply:

 export const PatchFormSchema = FormSchema.extend({
-    p_app_id: z.string({
-        // TODO: Validate against the options that are available
-        required_error: "Bemesting id is verplicht",
-        invalid_type_error: "Bemesting id is ongeldig",
-    }),
+    p_app_id: z
+        .string({
+            // TODO: Validate against the options that are available
+            required_error: "Bemesting id is verplicht",
+            invalid_type_error: "Bemesting id is ongeldig",
+        })
+        .min(1, "Bemesting id is verplicht"),
 })

If these IDs follow a specific format, confirm and we can switch to a stricter check (e.g., .uuid()).

fdm-app/app/store/field-fertilizer-form.tsx (1)

6-8: Export FieldFertilizerFormValues for reuse.

Helps avoid ad-hoc/unions in consumers (e.g., form.tsx).

-type FieldFertilizerFormValues = z.infer<typeof FormSchema> & {
+export type FieldFertilizerFormValues = z.infer<typeof FormSchema> & {
     p_app_id?: string | undefined
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3b03e49 and c5e90f9.

📒 Files selected for processing (5)
  • fdm-app/app/components/blocks/fertilizer-applications/card.tsx (8 hunks)
  • fdm-app/app/components/blocks/fertilizer-applications/form.tsx (5 hunks)
  • fdm-app/app/components/blocks/fertilizer-applications/formschema.tsx (1 hunks)
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx (3 hunks)
  • fdm-app/app/store/field-fertilizer-form.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-23T10:02:32.123Z
Learnt from: BoraIneviNMI
PR: SvenVw/fdm#272
File: fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue.manage.$p_id.tsx:151-164
Timestamp: 2025-09-23T10:02:32.123Z
Learning: The getFertilizer function from svenvw/fdm-core throws an exception if the fertilizer doesn't exist, rather than returning null or undefined.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx
📚 Learning: 2025-09-25T15:10:59.708Z
Learnt from: SvenVw
PR: SvenVw/fdm#272
File: fdm-app/app/store/field-fertilizer-form.tsx:45-47
Timestamp: 2025-09-25T15:10:59.708Z
Learning: In the FDM application, Zustand stores with persist middleware using sessionStorage/localStorage don't require SSR hardening guards. The existing store patterns in fdm-app work without typeof window checks or memory storage fallbacks, as evidenced by the changelog store using createJSONStorage(() => localStorage) directly.

Applied to files:

  • fdm-app/app/store/field-fertilizer-form.tsx
🧬 Code graph analysis (3)
fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx (2)
fdm-app/app/lib/form.ts (1)
  • extractFormValuesFromRequest (17-75)
fdm-app/app/components/blocks/fertilizer-applications/formschema.tsx (1)
  • PatchFormSchema (27-33)
fdm-app/app/components/blocks/fertilizer-applications/card.tsx (2)
fdm-core/src/db/schema.ts (1)
  • fertilizerApplication (182-199)
fdm-app/app/store/field-fertilizer-form.tsx (1)
  • useFieldFertilizerFormStore (26-51)
fdm-app/app/components/blocks/fertilizer-applications/form.tsx (3)
fdm-app/app/components/blocks/fertilizer-applications/types.d.tsx (2)
  • FertilizerOption (12-19)
  • FertilizerApplication (3-10)
fdm-app/app/components/blocks/fertilizer-applications/formschema.tsx (2)
  • PatchFormSchema (27-33)
  • FormSchema (3-25)
fdm-core/src/db/schema.ts (1)
  • fertilizerApplication (182-199)
🔇 Additional comments (4)
fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx (2)

20-23: Imports align with edit flow.

Importing PatchFormSchema is correct and consistent with the new action branch.


216-245: PUT/PATCH mismatch identified, but proposed diff is incorrect.

The mismatch is real: client sends PUT for edits (form.tsx:72), but server only handles PATCH at line 216. However, the proposed diff removes p_app_id validation, which is critical—this field is required to identify which record to update. Removing it would break updates.

Apply only the method condition fix:

-        if (request.method === "PATCH") {
+        if (request.method === "PATCH" || request.method === "PUT") {

Keep the p_app_id validation intact. Do not modify the validation block or return statement format unless there's a separate, deliberate refactor reason for consistency.

Likely an incorrect or invalid review comment.

fdm-app/app/components/blocks/fertilizer-applications/form.tsx (1)

156-162: Hidden p_app_id input is correct.

Ensures identifier is sent on edit.

fdm-app/app/components/blocks/fertilizer-applications/card.tsx (1)

318-328: Edit button wiring looks good.

Opens dialog with the selected application and disables during delete.

Confirm UX: disabling edit while a delete is in-flight is desired.

Comment thread fdm-app/app/components/blocks/fertilizer-applications/card.tsx
Comment thread fdm-app/app/components/blocks/fertilizer-applications/form.tsx
Comment thread fdm-app/app/components/blocks/fertilizer-applications/form.tsx Outdated
Comment on lines +71 to 73
submitConfig: {
method: fertilizerApplication ? "PUT" : "POST",
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Use PATCH to match the server (or accept both).

Align client method to server-side handling.

-        submitConfig: {
-            method: fertilizerApplication ? "PUT" : "POST",
-        },
+        submitConfig: {
+            method: fertilizerApplication ? "PATCH" : "POST",
+        },

If you prefer PUT, keep this as PUT and rely on the server change from my other comment.


I need to verify the server-side expectations for the HTTP method used when updating fertilizer applications. Let me search the codebase for API endpoint definitions and related documentation.


🏁 Script executed:

#!/bin/bash
# Search for fertilizer application related API routes or endpoint definitions
rg -n -i 'fertilizer.*application' --type=ts --type=js --type=tsx --type=jsx -C3 | head -50

Length of output: 27


🏁 Script executed:

#!/bin/bash
# Search for PUT or PATCH method handling in routes
rg -n '(PUT|PATCH)' --type=ts --type=js -C2 | grep -i 'fertilizer\|application' -C2 | head -50

Length of output: 1077


🏁 Script executed:

#!/bin/bash
# Search for API endpoint definitions
fd -e ts -e js -e tsx -e jsx | xargs grep -l 'router\.\(put\|patch\)' | head -10

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Look for server/API related files
fd -path '*/api/*' -o -path '*/server/*' -o -path '*/routes/*' | grep -i fertilizer | head -20

Length of output: 168


🏁 Script executed:

#!/bin/bash
# Search for any documentation or comments about this endpoint
rg -n 'fertilizerApplication' --type=ts --type=tsx -C2 | head -50

Length of output: 27


🏁 Script executed:

#!/bin/bash
# Check if there are type definitions or interfaces for the fertilizer endpoint
rg -n 'fertilizer' --type=ts --type=tsx | grep -i 'endpoint\|method\|api' | head -20

Length of output: 27


🏁 Script executed:

#!/bin/bash
# Look for submitConfig usage patterns
rg -n 'submitConfig.*method' --type=ts --type=tsx -C1 | head -30

Length of output: 27


🏁 Script executed:

#!/bin/bash
# Search for any API documentation files
fd -e md -o -e txt | xargs grep -l -i 'fertilizer' 2>/dev/null | head -10

Length of output: 116


🏁 Script executed:

#!/bin/bash
# Check the form.tsx file context around line 71-73
fd 'form.tsx' | xargs grep -n 'submitConfig\|method.*PUT\|method.*POST' -B5 -A5

Length of output: 1324


🏁 Script executed:

#!/bin/bash
# Search for other references to PUT vs PATCH in the codebase
rg -n '"PUT"|"PATCH"' --type=ts --type=tsx | head -30

Length of output: 27


🏁 Script executed:

#!/bin/bash
# Look for Swagger/OpenAPI specs that might document the API
fd -e json -e yaml | xargs grep -l -i 'fertilizer' 2>/dev/null | head -10

Length of output: 441


🏁 Script executed:

#!/bin/bash
# Check for environment files or config that might have API definitions
find . -name '*.env*' -o -name '*.config.*' -o -name '*api*config*' | head -20

Length of output: 369


🏁 Script executed:

#!/bin/bash
# Search for the actual form component to understand the complete context
cat fdm-app/app/components/blocks/fertilizer-applications/form.tsx | head -100

Length of output: 3370


🏁 Script executed:

#!/bin/bash
# Look for PUT handler in the server code
rg -n '\.put\(|router\.put' --type=ts --type=js -C3 | head -50

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Check package.json to understand the tech stack
cat package.json | grep -A5 -B5 'fertilizer\|axios\|fetch\|http'

Length of output: 306


🏁 Script executed:

#!/bin/bash
# Search for PATCH handler in the server code
rg -n '\.patch\(|router\.patch' --type=ts --type=js -C3 | head -50

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Look for any migration files or changelogs mentioning this
fd -e md -e txt -e sql | xargs grep -l -i 'http.*method\|PUT\|PATCH' 2>/dev/null | head -10

Length of output: 354


🏁 Script executed:

#!/bin/bash
# Check if there's a specific API client or service file
fd 'api\|service' -type f | grep -i fertilizer

Length of output: 170


🏁 Script executed:

#!/bin/bash
# Search for any tests that might clarify the expected behavior
fd -e test.ts -e test.tsx -e spec.ts | xargs grep -l 'fertilizer' 2>/dev/null | head -10

Length of output: 501


🏁 Script executed:

#!/bin/bash
# Look for constants or enums related to HTTP methods
rg -n 'HTTP_METHOD\|REQUEST_METHOD' --type=ts --type=tsx -C2 | head -30

Length of output: 27


🏁 Script executed:

#!/bin/bash
# Check git history for related changes (non-heavy command)
git log --oneline --all -i --grep='fertilizer\|PATCH\|PUT' | head -20

Length of output: 1376


🏁 Script executed:

#!/bin/bash
# Search for any error handling related to the fertilizer endpoint
rg -n 'fertilizerApplication' --type=ts --type=tsx -A10 -B10 | grep -i 'error\|method\|PUT\|PATCH' -C2 | head -50

Length of output: 27


🏁 Script executed:

#!/bin/bash
# Look for the actual server implementation
fd -path '*/src/server/*' -o -path '*/api/*' -type f | grep -v node_modules | head -20

Length of output: 168


🏁 Script executed:

#!/bin/bash
# Check if there's an API route definition file
find . -name '*route*' -o -name '*endpoint*' | grep -v node_modules | head -20

Length of output: 77


🏁 Script executed:

#!/bin/bash
# Search for form submission handlers
rg -n 'onSubmit\|submit' fdm-app/app/components/blocks/fertilizer-applications/form.tsx -C3

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Look at the complete form.tsx file
wc -l fdm-app/app/components/blocks/fertilizer-applications/form.tsx && echo "---" && cat fdm-app/app/components/blocks/fertilizer-applications/form.tsx

Length of output: 13068


🏁 Script executed:

#!/bin/bash
# Search for any API specs or documentation
fd -name '*.openapi*' -o -name '*.swagger*' -o -name '*api*.json' -o -name '*api*.yaml' | head -10

Length of output: 230


Change PUT to PATCH to align with server-side route handler.

The server at fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx:216 explicitly checks if (request.method === "PATCH"), but the client currently sends PUT for updates. This mismatch will cause the update request to fail server-side processing.

-        submitConfig: {
-            method: fertilizerApplication ? "PUT" : "POST",
-        },
+        submitConfig: {
+            method: fertilizerApplication ? "PATCH" : "POST",
+        },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
submitConfig: {
method: fertilizerApplication ? "PUT" : "POST",
},
submitConfig: {
method: fertilizerApplication ? "PATCH" : "POST",
},
🤖 Prompt for AI Agents
In fdm-app/app/components/blocks/fertilizer-applications/form.tsx around lines
71 to 73, the submitConfig.method uses "PUT" for updates but the server route
checks for "PATCH"; change the conditional so updates send "PATCH" (i.e.,
method: fertilizerApplication ? "PATCH" : "POST") to match the server-side
handler and ensure update requests are processed.

@codecov
Copy link
Copy Markdown

codecov Bot commented Oct 28, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.35%. Comparing base (1a0c29f) to head (518aaf7).
⚠️ Report is 56 commits behind head on development.

Additional details and impacted files
@@             Coverage Diff              @@
##           development     #311   +/-   ##
============================================
  Coverage        93.35%   93.35%           
============================================
  Files               91       91           
  Lines            15028    15028           
  Branches          1523     1523           
============================================
  Hits             14030    14030           
  Misses             996      996           
  Partials             2        2           
Flag Coverage Δ
fdm-calculator 95.43% <ø> (ø)
fdm-core 91.77% <ø> (ø)
fdm-data 94.04% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
fdm-app/app/components/blocks/fertilizer-applications/card.tsx (1)

164-168: Fix bulk delete payload when deleting grouped applications.

Server expects a single p_app_id string; join arrays before submit.

-    const handleDelete = (p_app_id: string | string[]) => {
+    const handleDelete = (p_app_id: string | string[]) => {
         if (fetcher.state === "submitting") return
-        fetcher.submit({ p_app_id }, { method: "DELETE" })
+        const payload =
+            Array.isArray(p_app_id) ? p_app_id.join(",") : p_app_id
+        fetcher.submit({ p_app_id: payload }, { method: "DELETE" })
     }

Also applies to: 349-357

♻️ Duplicate comments (2)
fdm-app/app/components/blocks/fertilizer-applications/form.tsx (2)

73-75: Use PATCH for updates (server accepts both).

Keeps the shared form compatible with routes that handle PATCH.

-        submitConfig: {
-            method: fertilizerApplication ? "PUT" : "POST",
-        },
+        submitConfig: {
+            method: fertilizerApplication ? "PATCH" : "POST",
+        },

2-2: Make fertilizerApplication optional and use the UI type (includes p_app_ids).

Prevents TS mismatch and supports “add” flow where prop is undefined.

-import type { FertilizerApplication } from "@svenvw/fdm-core"
+import type { FertilizerApplication as UIFertilizerApplication } from "./types.d"
@@
-    fertilizerApplication,
+    fertilizerApplication,
 }: {
@@
-    fertilizerApplication: FertilizerApplication
+    fertilizerApplication?: UIFertilizerApplication
 })

Also applies to: 48-56

🧹 Nitpick comments (2)
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx (1)

75-82: p_id fallback may desync UI/dose when farm fertilizer is missing.

If a catalogue ID lacks a farm acquiring ID, you fallback to p_id_catalogue. Ensure calculateDose and Combobox options still resolve correctly; otherwise the edit form may render without a selected fertilizer and dose may undercount. Recommend logging a warning/flagging those entries or surfacing a “missing in farm list” state.

Also applies to: 142-148

fdm-app/app/components/blocks/fertilizer-applications/card.tsx (1)

203-221: Tighten effect dependencies (satisfy linter, avoid needless re-runs).

Add b_id_or_b_lu_catalogue; remove unused params.b_id and extraneous deps.

-    }, [
-        applicationToEdit,
-        params.b_id_farm,
-        params.b_id,
-        savedFormValues,
-        fertilizerApplications,
-        editedFertilizerApplication,
-        fieldFertilizerFormStore.delete,
-    ])
+    }, [
+        applicationToEdit,
+        params.b_id_farm,
+        b_id_or_b_lu_catalogue,
+        savedFormValues,
+        editedFertilizerApplication,
+    ])
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c5e90f9 and a4931cd.

📒 Files selected for processing (6)
  • fdm-app/app/components/blocks/fertilizer-applications/card.tsx (8 hunks)
  • fdm-app/app/components/blocks/fertilizer-applications/form.tsx (5 hunks)
  • fdm-app/app/components/blocks/fertilizer-applications/formschema.tsx (1 hunks)
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx (3 hunks)
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx (5 hunks)
  • fdm-app/app/store/field-fertilizer-form.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • fdm-app/app/components/blocks/fertilizer-applications/formschema.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-09-23T12:29:34.184Z
Learnt from: SvenVw
PR: SvenVw/fdm#274
File: fdm-app/app/routes/farm.$b_id_farm._index.tsx:160-163
Timestamp: 2025-09-23T12:29:34.184Z
Learning: In the FDM application, the fertilizer application route intentionally uses `${calendar}/field/fertilizer` instead of the originally planned `/farm/{farmId}/add/fertilizer` structure. This design decision prioritizes starting from the field list view to provide better field selection workflow before applying fertilizer, rather than direct dashboard-to-action navigation.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
📚 Learning: 2025-05-09T14:41:43.484Z
Learnt from: SvenVw
PR: SvenVw/fdm#138
File: fdm-app/app/components/custom/fertilizer-applications/form.tsx:6-6
Timestamp: 2025-05-09T14:41:43.484Z
Learning: The project uses React Router v7 which exports a Form component directly from the "react-router" package, not from "remix-run/react".

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
📚 Learning: 2025-05-09T14:41:43.484Z
Learnt from: SvenVw
PR: SvenVw/fdm#138
File: fdm-app/app/components/custom/fertilizer-applications/form.tsx:6-6
Timestamp: 2025-05-09T14:41:43.484Z
Learning: The project uses React Router v7 which exports a Form component directly from the "react-router" package, making importing from "remix-run/react" unnecessary.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
📚 Learning: 2025-05-09T14:53:44.578Z
Learnt from: SvenVw
PR: SvenVw/fdm#138
File: fdm-app/app/components/custom/combobox.tsx:34-37
Timestamp: 2025-05-09T14:53:44.578Z
Learning: In the context of this React Router v7 project, it's important to follow the pattern of importing only the types (like UseFormReturn) from "react-hook-form" while importing the Form component from "react-router" to avoid naming conflicts.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
📚 Learning: 2025-05-09T14:58:10.465Z
Learnt from: SvenVw
PR: SvenVw/fdm#138
File: fdm-app/app/components/custom/combobox.tsx:34-37
Timestamp: 2025-05-09T14:58:10.465Z
Learning: When updating React components that use both react-hook-form and React Router v7, it's important to only import types (like UseFormReturn, FieldValues) from react-hook-form to avoid naming conflicts with React Router's Form component. Use `import type { ... } from 'react-hook-form'` syntax to ensure only types are imported.

Applied to files:

  • fdm-app/app/components/blocks/fertilizer-applications/form.tsx
🧬 Code graph analysis (3)
fdm-app/app/components/blocks/fertilizer-applications/card.tsx (2)
fdm-core/src/db/schema.ts (1)
  • fertilizerApplication (182-199)
fdm-app/app/store/field-fertilizer-form.tsx (1)
  • useFieldFertilizerFormStore (22-47)
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx (2)
fdm-app/app/lib/form.ts (1)
  • extractFormValuesFromRequest (17-75)
fdm-app/app/components/blocks/fertilizer-applications/formschema.tsx (1)
  • PatchFormSchema (27-33)
fdm-app/app/components/blocks/fertilizer-applications/form.tsx (2)
fdm-app/app/components/blocks/fertilizer-applications/types.d.tsx (2)
  • FertilizerOption (12-19)
  • FertilizerApplication (3-10)
fdm-app/app/components/blocks/fertilizer-applications/formschema.tsx (3)
  • FieldFertilizerFormValues (35-37)
  • PatchFormSchema (27-33)
  • FormSchema (3-25)
🪛 Biome (2.1.2)
fdm-app/app/components/blocks/fertilizer-applications/card.tsx

[error] 203-203: This hook does not specify its dependency on b_id_or_b_lu_catalogue.

This dependency is being used here, but is not specified in the hook dependency list.

Unsafe fix: Add the missing dependency to the list.

(lint/correctness/useExhaustiveDependencies)


[error] 203-203: This hook specifies more dependencies than necessary: params.b_id, fertilizerApplications

This dependency can be removed from the list.

Outer scope values aren't valid dependencies because mutating them doesn't re-render the component.

Unsafe fix: Remove the extra dependencies from the list.

(lint/correctness/useExhaustiveDependencies)

🔇 Additional comments (2)
fdm-app/app/store/field-fertilizer-form.tsx (1)

3-3: LGTM — shared value type import improves consistency.

fdm-app/app/components/blocks/fertilizer-applications/card.tsx (1)

291-292: Prop type alignment with form.

After updating the form prop to UIFertilizerApplication | undefined, this usage is correct. No code change needed; ensure imports/types are consistent.

Comment on lines +251 to +283
if (request.method === "PUT") {
console.log("PUT request")
const formValues = await extractFormValuesFromRequest(
request,
PatchFormSchema,
)
console.log(formValues)
const rawAppIds = formValues.p_app_id

if (!rawAppIds || typeof rawAppIds !== "string") {
throw new Error("invalid: p_app_id")
}

const p_app_ids = rawAppIds.split(",")

const { p_id, p_app_amount, p_app_date, p_app_method } = formValues

await Promise.all(
p_app_ids.map((p_app_id: string) =>
updateFertilizerApplication(
fdm,
session.principal_id,
p_app_id,
p_id,
p_app_amount,
p_app_method,
p_app_date,
),
),
)

return dataWithSuccess({}, { message: "Bemesting is gewijzigd" })
}
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Accept PATCH and drop debug logs.

Clients elsewhere send PATCH; accept both here and remove server-side console logs.
[architectural-consideration]

-        if (request.method === "PUT") {
-            console.log("PUT request")
+        if (request.method === "PUT" || request.method === "PATCH") {
             const formValues = await extractFormValuesFromRequest(
                 request,
                 PatchFormSchema,
             )
-            console.log(formValues)
             const rawAppIds = formValues.p_app_id

Also applies to: 252-257

🤖 Prompt for AI Agents
In
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
around lines 251-283 (also apply same change for 252-257), the handler currently
only accepts PUT and contains server-side console.log debug statements; update
the condition to accept both PUT and PATCH (e.g., check request.method === "PUT"
|| request.method === "PATCH") and remove all console.log lines, leaving the
form extraction, validation and update logic unchanged so PATCH clients are
supported and no debug logs are emitted.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does the client send PATCH exactly?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the form component to see what HTTP method is used for submissions
cat fdm-app/app/components/blocks/fertilizer-applications/form.tsx | grep -A5 -B5 "method"

Length of output: 2867


🏁 Script executed:

#!/bin/bash
# Search for any PATCH method usage in fertilizer-related files
rg -n "PATCH" fdm-app/app/components/blocks/fertilizer-applications/ fdm-app/app/routes/ --type=tsx --type=ts -C3

Length of output: 27


🏁 Script executed:

#!/bin/bash
# Search for fetcher.submit calls in the fertilizer card component
rg -n "fetcher\.submit" fdm-app/app/components/blocks/fertilizer-applications/card.tsx -A5 -B2

Length of output: 322


🏁 Script executed:

#!/bin/bash
# Check what methods are used in similar fertilizer application routes
rg -n "request\.method" fdm-app/app/routes/ --glob="*fertilizer*" -C2

Length of output: 4481


@BoraIneviNMI You're absolutely right to question that—I made an error. The client does not send PATCH.

Looking at the form component, it explicitly uses:

method: fertilizerApplication ? "PUT" : "POST"

So the form sends PUT for edits and POST for creates. There's no PATCH being used anywhere in the fertilizer application flow.

I apologize for the confusion in my original suggestion. The current request.method === "PUT" check is correct and doesn't need to also accept PATCH.

However, the console.log statements on lines 252 and 257 should still be removed since they're debug code that shouldn't be in production:

-            console.log("PUT request")
             const formValues = await extractFormValuesFromRequest(
                 request,
                 PatchFormSchema,
             )
-            console.log(formValues)

🧬 Code Graph Analysis Results

[filename: fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx]

  • Summary: The action handler in this file implements POST, PUT, and DELETE methods for managing fertilizer applications. There is no handling for PATCH in this route. Specifically:

    • POST: adds fertilizer applications to all fields of the targeted cultivation.
    • PUT: updates existing fertilizer applications (expects p_app_id values).
    • DELETE: removes fertilizer applications (accepts one or more p_app_id values).
    • If PATCH is invoked, it will fall through to the final error handling: "PATCH is not supported" (no dedicated PATCH branch).
  • Relevant detail (based on code behavior):

    • POST path collects form values via extractFormValuesFromRequest with FormSchema, then applies addFertilizerApplication to each field in the cultivation plan, and returns a success message.
    • PUT path uses PatchFormSchema to extract values, expects p_app_id(s), and calls updateFertilizerApplication for each id, returning a success message.
    • DELETE path reads p_app_id(s) from formData, and calls removeFertilizerApplication for each id, returning a success message.
    • All error handling is routed through handleActionError.

[filename: fdm-app/app/components/blocks/fertilizer-applications/formschema.tsx]

  • Snippet: PatchFormSchema (full, as provided)
    • Purpose: Extends the base FormSchema to include a p_app_id field for identifying which fertilizer application(s) to update.
    • Description:
      • PatchFormSchema = FormSchema.extend({
        p_app_id: z.string({
        // TODO: Validate against the options that are available
        required_error: "Bemesting id is verplicht",
        invalid_type_error: "Bemesting id is ongeldig",
        }),
        })
    • Parameters: none beyond the underlying FormSchema.
    • Return: a schema that requires p_app_id as a string when performing PATCH-like updates.
    • Exceptions / Validation: relies on zod validation from FormSchema; adds required string for p_app_id.
    • Important implementation detail: used by extractFormValuesFromRequest when the method is PUT to update existing fertilizer applications.

🧠 Learnings used
Learnt from: SvenVw
PR: SvenVw/fdm#274
File: fdm-app/app/routes/farm.$b_id_farm._index.tsx:160-163
Timestamp: 2025-09-23T12:29:34.184Z
Learning: In the FDM application, the fertilizer application route intentionally uses `${calendar}/field/fertilizer` instead of the originally planned `/farm/{farmId}/add/fertilizer` structure. This design decision prioritizes starting from the field list view to provide better field selection workflow before applying fertilizer, rather than direct dashboard-to-action navigation.

Learnt from: SvenVw
PR: SvenVw/fdm#274
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.field._index.tsx:113-148
Timestamp: 2025-09-23T12:37:58.711Z
Learning: In the FDM application, the current field data fetching implementation using Promise.all with individual API calls (getCultivations, getFertilizerApplications, getCurrentSoilData) performs acceptably even with farms containing 90+ fields. No performance issues have been observed in practice with this approach.

Learnt from: SvenVw
PR: SvenVw/fdm#71
File: fdm-app/app/routes/farm.create.$b_id_farm.cultivations.$b_lu_catalogue.crop.harvest._index.tsx:111-135
Timestamp: 2025-02-13T09:03:11.890Z
Learning: When adding multiple harvests in fdm-app, use Promise.all instead of Promise.allSettled to ensure atomic behavior - if one harvest addition fails, all should fail and rollback to maintain data consistency.

Learnt from: SvenVw
PR: SvenVw/fdm#0
File: :0-0
Timestamp: 2025-08-13T10:33:05.313Z
Learning: In the fdm project, fdm-calculator integration for new features like b_lu_variety is handled in separate updates from the core data model changes. When fdm-core functions are updated to support new fields, fdm-calculator can consume these enhanced APIs without requiring changes in the same PR that introduces the core functionality.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
fdm-app/app/components/blocks/fertilizer-applications/card.tsx (1)

203-220: Consider removing fieldFertilizerFormStore.delete from dependencies.

The effect correctly handles stale saved forms by deleting them when the application no longer exists. However, fieldFertilizerFormStore.delete is a Zustand store method that should be stable and doesn't need to be in the dependency array—you're calling it as a side effect, not reading from it.

Apply this diff:

     }, [
         applicationToEdit,
         params.b_id_farm,
         b_id_or_b_lu_catalogue,
         savedFormValues,
         editedFertilizerApplication,
-        fieldFertilizerFormStore.delete,
     ])
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a4931cd and de0bae4.

📒 Files selected for processing (3)
  • .changeset/free-onions-rest.md (1 hunks)
  • fdm-app/app/components/blocks/fertilizer-applications/card.tsx (8 hunks)
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx (5 hunks)
🧰 Additional context used
🧠 Learnings (18)
📓 Common learnings
Learnt from: SvenVw
PR: SvenVw/fdm#274
File: fdm-app/app/routes/farm.$b_id_farm._index.tsx:160-163
Timestamp: 2025-09-23T12:29:34.184Z
Learning: In the FDM application, the fertilizer application route intentionally uses `${calendar}/field/fertilizer` instead of the originally planned `/farm/{farmId}/add/fertilizer` structure. This design decision prioritizes starting from the field list view to provide better field selection workflow before applying fertilizer, rather than direct dashboard-to-action navigation.
Learnt from: SvenVw
PR: SvenVw/fdm#274
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.field._index.tsx:113-148
Timestamp: 2025-09-23T12:37:58.711Z
Learning: In the FDM application, the current field data fetching implementation using Promise.all with individual API calls (getCultivations, getFertilizerApplications, getCurrentSoilData) performs acceptably even with farms containing 90+ fields. No performance issues have been observed in practice with this approach.
📚 Learning: 2025-09-23T12:29:34.184Z
Learnt from: SvenVw
PR: SvenVw/fdm#274
File: fdm-app/app/routes/farm.$b_id_farm._index.tsx:160-163
Timestamp: 2025-09-23T12:29:34.184Z
Learning: In the FDM application, the fertilizer application route intentionally uses `${calendar}/field/fertilizer` instead of the originally planned `/farm/{farmId}/add/fertilizer` structure. This design decision prioritizes starting from the field list view to provide better field selection workflow before applying fertilizer, rather than direct dashboard-to-action navigation.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
  • fdm-app/app/components/blocks/fertilizer-applications/card.tsx
  • .changeset/free-onions-rest.md
📚 Learning: 2025-09-23T12:37:58.711Z
Learnt from: SvenVw
PR: SvenVw/fdm#274
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.field._index.tsx:113-148
Timestamp: 2025-09-23T12:37:58.711Z
Learning: In the FDM application, the current field data fetching implementation using Promise.all with individual API calls (getCultivations, getFertilizerApplications, getCurrentSoilData) performs acceptably even with farms containing 90+ fields. No performance issues have been observed in practice with this approach.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
  • .changeset/free-onions-rest.md
📚 Learning: 2025-02-13T09:03:11.890Z
Learnt from: SvenVw
PR: SvenVw/fdm#71
File: fdm-app/app/routes/farm.create.$b_id_farm.cultivations.$b_lu_catalogue.crop.harvest._index.tsx:111-135
Timestamp: 2025-02-13T09:03:11.890Z
Learning: When adding multiple harvests in fdm-app, use Promise.all instead of Promise.allSettled to ensure atomic behavior - if one harvest addition fails, all should fail and rollback to maintain data consistency.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
📚 Learning: 2025-08-13T10:33:05.313Z
Learnt from: SvenVw
PR: SvenVw/fdm#0
File: :0-0
Timestamp: 2025-08-13T10:33:05.313Z
Learning: In the fdm project, fdm-calculator integration for new features like b_lu_variety is handled in separate updates from the core data model changes. When fdm-core functions are updated to support new fields, fdm-calculator can consume these enhanced APIs without requiring changes in the same PR that introduces the core functionality.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
📚 Learning: 2025-09-24T14:02:48.574Z
Learnt from: BoraIneviNMI
PR: SvenVw/fdm#272
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer.manage.new.$p_id.tsx:85-101
Timestamp: 2025-09-24T14:02:48.574Z
Learning: The getFertilizer function in svenvw/fdm-core does not perform authorization checks, unlike getFertilizers which includes a checkPermission call to verify farm access. This means getFertilizer(fdm, p_id) can potentially return fertilizer details for any fertilizer ID without validating user permissions.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
📚 Learning: 2025-09-23T10:02:32.123Z
Learnt from: BoraIneviNMI
PR: SvenVw/fdm#272
File: fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue.manage.$p_id.tsx:151-164
Timestamp: 2025-09-23T10:02:32.123Z
Learning: The getFertilizer function from svenvw/fdm-core throws an exception if the fertilizer doesn't exist, rather than returning null or undefined.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
📚 Learning: 2025-09-24T14:02:48.574Z
Learnt from: BoraIneviNMI
PR: SvenVw/fdm#272
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer.manage.new.$p_id.tsx:85-101
Timestamp: 2025-09-24T14:02:48.574Z
Learning: Both getFertilizer and getFertilizers functions in svenvw/fdm-core perform authorization checks using the user's principal_id to verify farm access before returning fertilizer data.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
📚 Learning: 2025-05-09T14:41:43.484Z
Learnt from: SvenVw
PR: SvenVw/fdm#138
File: fdm-app/app/components/custom/fertilizer-applications/form.tsx:6-6
Timestamp: 2025-05-09T14:41:43.484Z
Learning: The project uses React Router v7 which exports a Form component directly from the "react-router" package, not from "remix-run/react".

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
📚 Learning: 2025-05-09T14:41:43.484Z
Learnt from: SvenVw
PR: SvenVw/fdm#138
File: fdm-app/app/components/custom/fertilizer-applications/form.tsx:6-6
Timestamp: 2025-05-09T14:41:43.484Z
Learning: The project uses React Router v7 which exports a Form component directly from the "react-router" package, making importing from "remix-run/react" unnecessary.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
📚 Learning: 2025-05-09T14:53:44.578Z
Learnt from: SvenVw
PR: SvenVw/fdm#138
File: fdm-app/app/components/custom/combobox.tsx:34-37
Timestamp: 2025-05-09T14:53:44.578Z
Learning: In the context of this React Router v7 project, it's important to follow the pattern of importing only the types (like UseFormReturn) from "react-hook-form" while importing the Form component from "react-router" to avoid naming conflicts.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
📚 Learning: 2025-05-09T14:58:10.465Z
Learnt from: SvenVw
PR: SvenVw/fdm#138
File: fdm-app/app/components/custom/combobox.tsx:34-37
Timestamp: 2025-05-09T14:58:10.465Z
Learning: When updating React components that use both react-hook-form and React Router v7, it's important to only import types (like UseFormReturn, FieldValues) from react-hook-form to avoid naming conflicts with React Router's Form component. Use `import type { ... } from 'react-hook-form'` syntax to ensure only types are imported.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
📚 Learning: 2025-04-18T13:49:17.029Z
Learnt from: SvenVw
PR: SvenVw/fdm#124
File: fdm-app/app/components/custom/farm/farm-title.tsx:3-3
Timestamp: 2025-04-18T13:49:17.029Z
Learning: In the fdm project, NavLink and other routing components can be imported from either "react-router" or "react-router-dom" as react-router-dom is included in react-router.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
📚 Learning: 2025-01-14T16:06:21.832Z
Learnt from: SvenVw
PR: SvenVw/fdm#45
File: fdm-app/app/routes/farm.$b_id_farm.settings._index.tsx:1-1
Timestamp: 2025-01-14T16:06:21.832Z
Learning: In the fdm project, `redirect` and other routing utilities should be imported from `react-router` instead of `react-router-dom`.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
📚 Learning: 2025-01-14T16:06:24.294Z
Learnt from: SvenVw
PR: SvenVw/fdm#45
File: fdm-app/app/routes/farm.$b_id_farm._index.tsx:1-1
Timestamp: 2025-01-14T16:06:24.294Z
Learning: In the fdm-app codebase, the `redirect` function should be imported from `react-router`, not `react-router-dom`.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
📚 Learning: 2024-12-16T10:56:07.561Z
Learnt from: SvenVw
PR: SvenVw/fdm#16
File: fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx:1-1
Timestamp: 2024-12-16T10:56:07.561Z
Learning: The project uses `react-router` v7, and the `data` function is exported and used for error handling in loaders and actions.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
📚 Learning: 2025-09-23T12:27:07.391Z
Learnt from: SvenVw
PR: SvenVw/fdm#274
File: fdm-app/app/routes/farm.$b_id_farm._index.tsx:151-204
Timestamp: 2025-09-23T12:27:07.391Z
Learning: In the FDM application, field overview functionality is implemented as a dedicated page accessible via `farm/{farmId}/{calendar}/field` rather than as a direct listing on the dashboard. The dashboard includes a "Perceelsoverzicht" quick action card that provides navigation to this comprehensive field management interface.

Applied to files:

  • fdm-app/app/components/blocks/fertilizer-applications/card.tsx
  • .changeset/free-onions-rest.md
📚 Learning: 2025-09-26T08:34:50.413Z
Learnt from: SvenVw
PR: SvenVw/fdm#279
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.norms.tsx:277-283
Timestamp: 2025-09-26T08:34:50.413Z
Learning: In the fdm project, fdm-core and fdm-app are updated together as part of a monorepo structure, which eliminates legacy data concerns when new fields like b_isproductive are introduced. Both packages are synchronized, so there's no need for defensive coding against undefined values for newly introduced database fields.

Applied to files:

  • .changeset/free-onions-rest.md
🧬 Code graph analysis (2)
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx (2)
fdm-app/app/lib/form.ts (1)
  • extractFormValuesFromRequest (17-75)
fdm-app/app/components/blocks/fertilizer-applications/formschema.tsx (1)
  • PatchFormSchema (27-33)
fdm-app/app/components/blocks/fertilizer-applications/card.tsx (5)
fdm-core/src/index.ts (1)
  • FertilizerApplication (92-92)
fdm-core/src/db/schema.ts (1)
  • fertilizerApplication (182-199)
fdm-app/app/store/field-fertilizer-form.tsx (1)
  • useFieldFertilizerFormStore (22-47)
fdm-app/app/components/ui/dialog.tsx (2)
  • DialogTitle (120-120)
  • DialogDescription (121-121)
fdm-app/app/components/ui/button.tsx (1)
  • Button (58-58)
🔇 Additional comments (10)
.changeset/free-onions-rest.md (1)

1-5: LGTM!

The changeset appropriately documents the new editing capability as a minor version bump with a clear user-facing description.

fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx (4)

8-8: LGTM!

The imports for updateFertilizerApplication and PatchFormSchema are correctly added to support the edit functionality.

Also applies to: 19-22


74-82: LGTM!

The mapping from catalogue IDs to acquiring IDs is correctly constructed and enables proper fertilizer ID resolution when aggregating applications by cultivation type.


142-148: LGTM!

The accumulator correctly maps fertilizer IDs using the mapping created earlier, falling back to the catalogue ID when no acquiring ID exists. The p_app_ids array enables bulk update operations.


251-281: Authorization is properly enforced in updateFertilizerApplication.

The function includes a checkPermission call that validates the user has write access to the specific fertilizer application before any database operation occurs. The bulk update implementation correctly maintains atomicity through Promise.all while ensuring each operation is authorized.

fdm-app/app/components/blocks/fertilizer-applications/card.tsx (5)

158-159: LGTM!

The editedFertilizerApplication state and handleEdit function are correctly implemented using a higher-order function pattern for the click handler.

Also applies to: 170-173


181-181: LGTM!

The navigation state tracking correctly clears the edited application when the form submission completes, and saved form values are loaded with proper null guards.

Also applies to: 189-194


222-233: LGTM!

The dialog opening logic correctly prevents accidental creation of new applications when a saved edit form references an application that no longer exists. The dependency array is appropriate for this behavior.


245-247: LGTM!

The dialog state management correctly clears the edited application on close, and the UI copy appropriately reflects both add and edit modes with conditional rendering.

Also applies to: 258-260, 272-279


290-290: LGTM!

The form integration correctly passes the edited application data, the grid layout properly accommodates the new edit button, and the button styling and behavior are consistent with existing patterns.

Also applies to: 300-300, 330-340

@BoraIneviNMI BoraIneviNMI requested a review from SvenVw October 30, 2025 14:02
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (2)
fdm-app/app/components/blocks/fertilizer-applications/form.tsx (2)

48-48: Make fertilizerApplication optional.

The prop is still required but callers pass undefined in create mode, causing type errors.

-    fertilizerApplication,
+    fertilizerApplication,
 }: {
     options: FertilizerOption[]
     action: string
     navigation: Navigation
     b_id_farm: string
     b_id_or_b_lu_catalogue: string
-    fertilizerApplication: FertilizerApplication
+    fertilizerApplication?: FertilizerApplication
 })

Also applies to: 55-55


73-75: Change PUT to PATCH to align with server.

The server route handler explicitly checks for "PATCH", but the client sends "PUT" for updates, causing the request to fail server-side.

-        submitConfig: {
-            method: fertilizerApplication ? "PUT" : "POST",
-        },
+        submitConfig: {
+            method: fertilizerApplication ? "PATCH" : "POST",
+        },
🧹 Nitpick comments (1)
fdm-app/app/components/blocks/fertilizer-applications/form.tsx (1)

64-72: Consider simplifying p_app_id default value.

The logic handles both p_app_ids array and p_app_id string, but this complexity could be encapsulated in a helper function for clarity.

+const getDefaultAppId = (app?: FertilizerApplication) => {
+    if (!app) return undefined
+    return app.p_app_ids ? app.p_app_ids.join(",") : app.p_app_id
+}
+
 const form = useRemixForm<FieldFertilizerFormValues>({
     mode: "onTouched",
     resolver: zodResolver(
         fertilizerApplication ? FormSchemaModify : FormSchema,
     ),
     defaultValues: {
-        p_app_id: fertilizerApplication?.p_app_ids
-            ? fertilizerApplication.p_app_ids.join(",")
-            : fertilizerApplication?.p_app_id,
+        p_app_id: getDefaultAppId(fertilizerApplication),
         p_id: fertilizerApplication?.p_id,
         p_app_method: fertilizerApplication?.p_app_method,
         p_app_amount: undefined,
         p_app_date: fertilizerApplication?.p_app_date ?? new Date(),
     },
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between de0bae4 and d414e92.

📒 Files selected for processing (4)
  • fdm-app/app/components/blocks/fertilizer-applications/form.tsx (6 hunks)
  • fdm-app/app/components/blocks/fertilizer-applications/formschema.tsx (1 hunks)
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx (3 hunks)
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • fdm-app/app/components/blocks/fertilizer-applications/formschema.tsx
🧰 Additional context used
🧠 Learnings (32)
📓 Common learnings
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 274
File: fdm-app/app/routes/farm.$b_id_farm._index.tsx:160-163
Timestamp: 2025-09-23T12:29:34.184Z
Learning: In the FDM application, the fertilizer application route intentionally uses `${calendar}/field/fertilizer` instead of the originally planned `/farm/{farmId}/add/fertilizer` structure. This design decision prioritizes starting from the field list view to provide better field selection workflow before applying fertilizer, rather than direct dashboard-to-action navigation.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 274
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.field._index.tsx:113-148
Timestamp: 2025-09-23T12:37:58.711Z
Learning: In the FDM application, the current field data fetching implementation using Promise.all with individual API calls (getCultivations, getFertilizerApplications, getCurrentSoilData) performs acceptably even with farms containing 90+ fields. No performance issues have been observed in practice with this approach.
📚 Learning: 2025-09-23T12:29:34.184Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 274
File: fdm-app/app/routes/farm.$b_id_farm._index.tsx:160-163
Timestamp: 2025-09-23T12:29:34.184Z
Learning: In the FDM application, the fertilizer application route intentionally uses `${calendar}/field/fertilizer` instead of the originally planned `/farm/{farmId}/add/fertilizer` structure. This design decision prioritizes starting from the field list view to provide better field selection workflow before applying fertilizer, rather than direct dashboard-to-action navigation.

Applied to files:

  • fdm-app/app/components/blocks/fertilizer-applications/form.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx
📚 Learning: 2024-11-25T12:42:32.783Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/vite.config.ts:5-9
Timestamp: 2024-11-25T12:42:32.783Z
Learning: In the `fdm-app` project, SvenVw is preparing for migration to Remix v3 and may include type declarations or configurations for v3 features in advance, such as in `vite.config.ts`.

Applied to files:

  • fdm-app/app/components/blocks/fertilizer-applications/form.tsx
📚 Learning: 2025-09-26T08:34:50.413Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 279
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.norms.tsx:277-283
Timestamp: 2025-09-26T08:34:50.413Z
Learning: In the fdm project, fdm-core and fdm-app are updated together as part of a monorepo structure, which eliminates legacy data concerns when new fields like b_isproductive are introduced. Both packages are synchronized, so there's no need for defensive coding against undefined values for newly introduced database fields.

Applied to files:

  • fdm-app/app/components/blocks/fertilizer-applications/form.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
📚 Learning: 2025-09-23T12:27:07.391Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 274
File: fdm-app/app/routes/farm.$b_id_farm._index.tsx:151-204
Timestamp: 2025-09-23T12:27:07.391Z
Learning: In the FDM application, field overview functionality is implemented as a dedicated page accessible via `farm/{farmId}/{calendar}/field` rather than as a direct listing on the dashboard. The dashboard includes a "Perceelsoverzicht" quick action card that provides navigation to this comprehensive field management interface.

Applied to files:

  • fdm-app/app/components/blocks/fertilizer-applications/form.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
📚 Learning: 2025-09-23T10:02:32.123Z
Learnt from: BoraIneviNMI
Repo: SvenVw/fdm PR: 272
File: fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue.manage.$p_id.tsx:151-164
Timestamp: 2025-09-23T10:02:32.123Z
Learning: The getFertilizer function from svenvw/fdm-core throws an exception if the fertilizer doesn't exist, rather than returning null or undefined.

Applied to files:

  • fdm-app/app/components/blocks/fertilizer-applications/form.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx
📚 Learning: 2025-08-13T11:05:40.105Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 237
File: fdm-data/src/cultivations/catalogues/brp.ts:65-68
Timestamp: 2025-08-13T11:05:40.105Z
Learning: In fdm-app Select components, using `undefined` instead of empty string (`""`) as fallback value prevents empty strings from being submitted as form values. This approach fixes the issue at the UI source rather than requiring backend validation.

Applied to files:

  • fdm-app/app/components/blocks/fertilizer-applications/form.tsx
📚 Learning: 2025-02-13T08:35:59.306Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 71
File: fdm-app/app/routes/farm.$b_id_farm.field.$b_id.cultivation.$b_lu.harvest.$b_id_harvesting.tsx:114-124
Timestamp: 2025-02-13T08:35:59.306Z
Learning: The HarvestForm component in fdm-app expects undefined (not 0) for b_lu_yield when no yield information is available, as 0 would incorrectly imply that yield data exists.

Applied to files:

  • fdm-app/app/components/blocks/fertilizer-applications/form.tsx
📚 Learning: 2025-01-31T15:34:20.850Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.fields.$b_id.tsx:601-610
Timestamp: 2025-01-31T15:34:20.850Z
Learning: The `updateField` function in fdm-core has optional parameters that don't need to be passed as undefined. Only `fdm` and `b_id` are required.

Applied to files:

  • fdm-app/app/components/blocks/fertilizer-applications/form.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx
📚 Learning: 2025-08-11T11:55:26.053Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 233
File: fdm-app/app/integrations/nmi.ts:54-0
Timestamp: 2025-08-11T11:55:26.053Z
Learning: The NMI API Estimates endpoint (`https://api.nmi-agro.nl/estimates`) always returns the fields `b_gwl_ghg`, `b_gwl_glg`, and `cultivations` according to its specification. These fields should be kept as required (not optional) in the TypeScript return type and Zod validation schema in `fdm-app/app/integrations/nmi.ts`.

Applied to files:

  • fdm-app/app/components/blocks/fertilizer-applications/form.tsx
📚 Learning: 2025-01-31T15:05:14.310Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.fields.$b_id.tsx:601-610
Timestamp: 2025-01-31T15:05:14.310Z
Learning: The `updateField` function in fdm-core has optional parameters after `fdm` and `b_id`. The TypeScript definitions might show 8 required parameters due to a potential version mismatch.

Applied to files:

  • fdm-app/app/components/blocks/fertilizer-applications/form.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx
📚 Learning: 2025-08-11T12:24:32.200Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 233
File: fdm-app/app/components/blocks/atlas-fields/cultivation-history.tsx:53-53
Timestamp: 2025-08-11T12:24:32.200Z
Learning: In `fdm-app/app/components/blocks/atlas-fields/cultivation-history.tsx`, the NMI API for cultivations guarantees that each year will be unique in the cultivation history data, so using `cultivation.year` as a React list key is safe and won't cause duplicate key warnings.

Applied to files:

  • fdm-app/app/components/blocks/fertilizer-applications/form.tsx
📚 Learning: 2025-09-24T14:02:48.574Z
Learnt from: BoraIneviNMI
Repo: SvenVw/fdm PR: 272
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer.manage.new.$p_id.tsx:85-101
Timestamp: 2025-09-24T14:02:48.574Z
Learning: The getFertilizer function in svenvw/fdm-core does not perform authorization checks, unlike getFertilizers which includes a checkPermission call to verify farm access. This means getFertilizer(fdm, p_id) can potentially return fertilizer details for any fertilizer ID without validating user permissions.

Applied to files:

  • fdm-app/app/components/blocks/fertilizer-applications/form.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx
📚 Learning: 2024-12-16T11:28:58.089Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 16
File: fdm-app/app/components/custom/combobox.tsx:35-37
Timestamp: 2024-12-16T11:28:58.089Z
Learning: When using `UseRemixFormReturn` from `remix-hook-form`, it is not a generic type and should be used without type parameters.

Applied to files:

  • fdm-app/app/components/blocks/fertilizer-applications/form.tsx
📚 Learning: 2024-12-16T10:56:33.616Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 16
File: fdm-app/app/components/custom/combobox.tsx:35-37
Timestamp: 2024-12-16T10:56:33.616Z
Learning: When using `useRemixForm`, the correct type for the `form` prop is `UseRemixFormReturn<T>` from `remix-hook-form`, not `UseFormReturn` from `react-hook-form`.

Applied to files:

  • fdm-app/app/components/blocks/fertilizer-applications/form.tsx
📚 Learning: 2025-05-09T14:58:10.465Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/combobox.tsx:34-37
Timestamp: 2025-05-09T14:58:10.465Z
Learning: When updating React components that use both react-hook-form and React Router v7, it's important to only import types (like UseFormReturn, FieldValues) from react-hook-form to avoid naming conflicts with React Router's Form component. Use `import type { ... } from 'react-hook-form'` syntax to ensure only types are imported.

Applied to files:

  • fdm-app/app/components/blocks/fertilizer-applications/form.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx
📚 Learning: 2025-05-09T14:53:44.578Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/combobox.tsx:34-37
Timestamp: 2025-05-09T14:53:44.578Z
Learning: In the context of this React Router v7 project, it's important to follow the pattern of importing only the types (like UseFormReturn) from "react-hook-form" while importing the Form component from "react-router" to avoid naming conflicts.

Applied to files:

  • fdm-app/app/components/blocks/fertilizer-applications/form.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx
📚 Learning: 2025-05-09T14:41:43.484Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/fertilizer-applications/form.tsx:6-6
Timestamp: 2025-05-09T14:41:43.484Z
Learning: The project uses React Router v7 which exports a Form component directly from the "react-router" package, making importing from "remix-run/react" unnecessary.

Applied to files:

  • fdm-app/app/components/blocks/fertilizer-applications/form.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx
📚 Learning: 2025-05-09T14:41:43.484Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/fertilizer-applications/form.tsx:6-6
Timestamp: 2025-05-09T14:41:43.484Z
Learning: The project uses React Router v7 which exports a Form component directly from the "react-router" package, not from "remix-run/react".

Applied to files:

  • fdm-app/app/components/blocks/fertilizer-applications/form.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx
📚 Learning: 2025-09-23T12:37:58.711Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 274
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.field._index.tsx:113-148
Timestamp: 2025-09-23T12:37:58.711Z
Learning: In the FDM application, the current field data fetching implementation using Promise.all with individual API calls (getCultivations, getFertilizerApplications, getCurrentSoilData) performs acceptably even with farms containing 90+ fields. No performance issues have been observed in practice with this approach.

Applied to files:

  • fdm-app/app/components/blocks/fertilizer-applications/form.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx
📚 Learning: 2025-08-13T10:33:05.313Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 0
File: :0-0
Timestamp: 2025-08-13T10:33:05.313Z
Learning: In the fdm project, fdm-calculator integration for new features like b_lu_variety is handled in separate updates from the core data model changes. When fdm-core functions are updated to support new fields, fdm-calculator can consume these enhanced APIs without requiring changes in the same PR that introduces the core functionality.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
📚 Learning: 2025-02-13T09:03:11.890Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 71
File: fdm-app/app/routes/farm.create.$b_id_farm.cultivations.$b_lu_catalogue.crop.harvest._index.tsx:111-135
Timestamp: 2025-02-13T09:03:11.890Z
Learning: When adding multiple harvests in fdm-app, use Promise.all instead of Promise.allSettled to ensure atomic behavior - if one harvest addition fails, all should fail and rollback to maintain data consistency.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
📚 Learning: 2025-04-04T14:27:39.518Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 116
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx:111-154
Timestamp: 2025-04-04T14:27:39.518Z
Learning: In the FDM application, cultivation retrieval logic should be centralized in utility functions rather than duplicated across loader and action functions to improve maintainability and ensure consistent behavior.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
📚 Learning: 2025-01-09T16:03:37.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes/farm/_b_id_farm/layout.tsx:46-95
Timestamp: 2025-01-09T16:03:37.764Z
Learning: A shared layout component `FarmLayoutBase` has been created in `components/custom/farm-layout-base.tsx` to maintain consistency across farm-related pages. The component handles farm selection dropdown, breadcrumb navigation, and provides a common layout structure.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
📚 Learning: 2025-09-24T14:02:48.574Z
Learnt from: BoraIneviNMI
Repo: SvenVw/fdm PR: 272
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer.manage.new.$p_id.tsx:85-101
Timestamp: 2025-09-24T14:02:48.574Z
Learning: Both getFertilizer and getFertilizers functions in svenvw/fdm-core perform authorization checks using the user's principal_id to verify farm access before returning fertilizer data.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx
📚 Learning: 2025-04-18T13:49:17.029Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-app/app/components/custom/farm/farm-title.tsx:3-3
Timestamp: 2025-04-18T13:49:17.029Z
Learning: In the fdm project, NavLink and other routing components can be imported from either "react-router" or "react-router-dom" as react-router-dom is included in react-router.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx
📚 Learning: 2025-01-14T16:06:21.832Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 45
File: fdm-app/app/routes/farm.$b_id_farm.settings._index.tsx:1-1
Timestamp: 2025-01-14T16:06:21.832Z
Learning: In the fdm project, `redirect` and other routing utilities should be imported from `react-router` instead of `react-router-dom`.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx
📚 Learning: 2025-01-14T16:06:24.294Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 45
File: fdm-app/app/routes/farm.$b_id_farm._index.tsx:1-1
Timestamp: 2025-01-14T16:06:24.294Z
Learning: In the fdm-app codebase, the `redirect` function should be imported from `react-router`, not `react-router-dom`.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx
📚 Learning: 2024-12-16T10:56:07.561Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 16
File: fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx:1-1
Timestamp: 2024-12-16T10:56:07.561Z
Learning: The project uses `react-router` v7, and the `data` function is exported and used for error handling in loaders and actions.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx
📚 Learning: 2025-01-31T15:05:14.310Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.fields.$b_id.tsx:601-610
Timestamp: 2025-01-31T15:05:14.310Z
Learning: When using `updateField` from fdm-core, all 8 parameters must be provided in order: fdm, b_id, b_name, b_geometry, b_area, b_id_source, b_id_farm, and b_id_farm_source.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx
📚 Learning: 2025-01-31T15:05:14.310Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.fields.$b_id.tsx:601-610
Timestamp: 2025-01-31T15:05:14.310Z
Learning: The `updateField` function in fdm-core requires 8 parameters: fdm, b_id (required), and 6 optional parameters (b_name, b_id_source, b_geometry, b_acquiring_date, b_acquiring_method, b_discarding_date).

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx
📚 Learning: 2024-12-16T10:48:27.598Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 16
File: fdm-app/package.json:40-40
Timestamp: 2024-12-16T10:48:27.598Z
Learning: In the `fdm-app/package.json` file, `remix-toast` and `sonner` are not duplicate dependencies. `remix-toast` manages toast generation and handling within the Remix framework, while `sonner` provides the actual implementation and UI of the toast notifications. They serve different purposes and are intended to be used together in the project.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx
🧬 Code graph analysis (3)
fdm-app/app/components/blocks/fertilizer-applications/form.tsx (3)
fdm-app/app/components/blocks/fertilizer-applications/types.d.tsx (2)
  • FertilizerOption (12-19)
  • FertilizerApplication (3-10)
fdm-app/app/components/blocks/fertilizer-applications/formschema.tsx (3)
  • FieldFertilizerFormValues (35-37)
  • FormSchemaModify (27-33)
  • FormSchema (3-25)
fdm-core/src/db/schema.ts (1)
  • fertilizerApplication (185-202)
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx (3)
fdm-core/src/db/schema.ts (1)
  • fertilizers (136-144)
fdm-app/app/lib/form.ts (1)
  • extractFormValuesFromRequest (17-75)
fdm-app/app/components/blocks/fertilizer-applications/formschema.tsx (1)
  • FormSchemaModify (27-33)
fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx (2)
fdm-app/app/lib/form.ts (1)
  • extractFormValuesFromRequest (17-75)
fdm-app/app/components/blocks/fertilizer-applications/formschema.tsx (1)
  • FormSchemaModify (27-33)
🔇 Additional comments (8)
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fertilizers.$b_lu_catalogue._index.tsx (2)

75-81: LGTM - Mapping enables correct fertilizer selection in edit forms.

The new mapping logic correctly translates catalogue IDs to farm-specific acquiring IDs, which is essential for the edit workflow. When aggregating similar applications, the accumulator now includes the appropriate p_id (preferring the farm's acquiring ID, falling back to the catalogue ID if no mapping exists), ensuring the edit form can properly pre-select the fertilizer.

Also applies to: 142-148


251-281: LGTM - Bulk update implementation is consistent and atomic.

The PUT handler correctly:

  • Validates and parses form data using FormSchemaModify
  • Splits comma-separated p_app_id values for bulk updates
  • Uses Promise.all to ensure atomic updates (all succeed or all fail)
  • Follows the same pattern as the existing DELETE handler
fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx (1)

9-9: LGTM - Imports correctly updated.

The imports properly add updateFertilizerApplication from fdm-core and FormSchemaModify from the form schema module, consistent with the update feature requirements.

Also applies to: 20-23

fdm-app/app/components/blocks/fertilizer-applications/form.tsx (5)

2-2: LGTM!

The new imports properly support edit functionality: FertilizerApplication for type safety, useId for unique form IDs, and the schema types for validation.

Also applies to: 5-5, 35-39


59-63: LGTM!

The form typing and conditional resolver correctly handle both create and edit modes using the appropriate schemas.


82-88: LGTM!

The conditional logic correctly clears p_app_method only when the fertilizer changes, preserving the pre-selected method in edit mode.


116-120: LGTM!

The effect correctly initializes p_app_amount in edit mode, separating the initialization from defaultValues to handle the blank-value behavior in the amount input field.


295-296: LGTM!

The conditional button label correctly shows "Opslaan" (Save) in edit mode and "Voeg toe" (Add) in create mode, improving user clarity.

Comment thread fdm-app/app/components/blocks/fertilizer-applications/form.tsx Outdated
Comment on lines +216 to +245
if (request.method === "PUT") {
// Collect form entry
const formValues = await extractFormValuesFromRequest(
request,
FormSchemaModify,
)
const { p_app_id, p_id, p_app_amount, p_app_date, p_app_method } =
formValues

if (!p_app_id || typeof p_app_id !== "string") {
return dataWithError(
"Invalid or missing p_app_id value",
"Helaas, er is wat misggegaan. Probeer het later opnieuw of neem contact op met ondersteuning.",
)
}

await updateFertilizerApplication(
fdm,
session.principal_id,
p_app_id,
p_id,
p_app_amount,
p_app_method,
p_app_date,
)

return dataWithSuccess("Date edited successfully", {
message: "Bemesting is gewijzigd",
})
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix typos in user-facing messages.

The PUT handler logic is correct, but there are two minor typos:

  1. Line 228: "misggegaan" should be "misgegaan" (one 'g')
  2. Line 242: "Date edited successfully" should likely be "Data edited successfully" (to match the pattern used elsewhere in the codebase)

Apply this diff:

                 return dataWithError(
                     "Invalid or missing p_app_id value",
-                    "Helaas, er is wat misggegaan. Probeer het later opnieuw of neem contact op met ondersteuning.",
+                    "Helaas, er is wat misgegaan. Probeer het later opnieuw of neem contact op met ondersteuning.",
                 )
             }

             await updateFertilizerApplication(
                 fdm,
                 session.principal_id,
                 p_app_id,
                 p_id,
                 p_app_amount,
                 p_app_method,
                 p_app_date,
             )

-            return dataWithSuccess("Date edited successfully", {
+            return dataWithSuccess("Data edited successfully", {
                 message: "Bemesting is gewijzigd",
             })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (request.method === "PUT") {
// Collect form entry
const formValues = await extractFormValuesFromRequest(
request,
FormSchemaModify,
)
const { p_app_id, p_id, p_app_amount, p_app_date, p_app_method } =
formValues
if (!p_app_id || typeof p_app_id !== "string") {
return dataWithError(
"Invalid or missing p_app_id value",
"Helaas, er is wat misggegaan. Probeer het later opnieuw of neem contact op met ondersteuning.",
)
}
await updateFertilizerApplication(
fdm,
session.principal_id,
p_app_id,
p_id,
p_app_amount,
p_app_method,
p_app_date,
)
return dataWithSuccess("Date edited successfully", {
message: "Bemesting is gewijzigd",
})
}
if (request.method === "PUT") {
// Collect form entry
const formValues = await extractFormValuesFromRequest(
request,
FormSchemaModify,
)
const { p_app_id, p_id, p_app_amount, p_app_date, p_app_method } =
formValues
if (!p_app_id || typeof p_app_id !== "string") {
return dataWithError(
"Invalid or missing p_app_id value",
"Helaas, er is wat misgegaan. Probeer het later opnieuw of neem contact op met ondersteuning.",
)
}
await updateFertilizerApplication(
fdm,
session.principal_id,
p_app_id,
p_id,
p_app_amount,
p_app_method,
p_app_date,
)
return dataWithSuccess("Data edited successfully", {
message: "Bemesting is gewijzigd",
})
}
🤖 Prompt for AI Agents
In
fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.fertilizer._index.tsx
around lines 216 to 245, there are two typos in the user-facing messages: change
"Helaas, er is wat misggegaan. Probeer het later opnieuw of neem contact op met
ondersteuning." to "Helaas, er is wat misgegaan. Probeer het later opnieuw of
neem contact op met ondersteuning." (fix double g to single g) and change the
success message "Date edited successfully" to "Data edited successfully" so it
matches the codebase pattern; keep all other logic unchanged.

@SvenVw SvenVw merged commit 73609a1 into development Oct 31, 2025
9 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

branch:development Issue only affecting development, not the main branch (yet) enhancement New feature or request fdm-app fdm-core

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enable updating of fertilizer applications

2 participants