Migrate from Mapbox GL to MapLibre GL with dual provider support#359
Conversation
🦋 Changeset detectedLatest commit: 66da6d5 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
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 |
WalkthroughReplaces Mapbox with MapLibre across the app: imports, types, CSS, dependencies, runtime env and config shapes; adds getMapStyle() with MapTiler/OSM handling; rewrites geocoder and map controls to use MapLibre; updates many route loaders to return a unified mapStyle. Changes
Sequence Diagram(s)sequenceDiagram
actor Browser
participant Server
participant Config
participant MapService as getMapStyle
participant External as MapTiler/OSM
Browser->>Server: Request atlas route (loader)
Server->>Config: Read PUBLIC_MAP_PROVIDER / maptilerKey
Server->>MapService: getMapStyle(variant)
MapService->>External: Fetch style URL or return fallback
External-->>MapService: style URL or StyleSpecification
MapService-->>Server: return mapStyle
Server-->>Browser: loader payload { fields, mapStyle }
Browser->>MapLibrary: Init MapGL with mapLib=maplibregl and mapStyle
Browser->>GeocoderControl: forwardGeocode(query)
GeocoderControl->>External: geocode request (maptiler/osm)
External-->>GeocoderControl: geocode results
GeocoderControl-->>Browser: display results as features
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related issues
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Tip ✨ Issue Enrichment is now available for GitHub issues!CodeRabbit can now help you manage issues more effectively:
Disable automatic issue enrichmentTo disable automatic issue enrichment, add the following to your issue_enrichment:
auto_enrich:
enabled: falseThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## development #359 +/- ##
============================================
Coverage 87.62% 87.62%
============================================
Files 79 79
Lines 3959 3959
Branches 1145 1145
============================================
Hits 3469 3469
Misses 490 490
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
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 (2)
fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx (2)
36-42: Update outdated JSDoc to reflect MapLibre migration.The JSDoc comment still references "Mapbox configuration" and "Mapbox access token" but the implementation now uses MapLibre with
getMapStyle. Update the documentation to accurately describe the current behavior./** - * Loads field data and Mapbox configuration for rendering a farm field on the map. + * Loads field data and map configuration for rendering a farm field on the map. * - * This function retrieves a farm field's details using the field ID from the route parameters. It establishes a valid user session and uses it to fetch the corresponding field data. The retrieved field details are formatted into a GeoJSON FeatureCollection, and Mapbox configuration values (access token and style) are provided for map rendering. + * This function retrieves a farm field's details using the field ID from the route parameters. It establishes a valid user session and uses it to fetch the corresponding field data. The retrieved field details are formatted into a GeoJSON FeatureCollection, and map style configuration is provided for rendering. * - * @returns An object containing the field's GeoJSON FeatureCollection, Mapbox access token, and Mapbox style. + * @returns An object containing the field's GeoJSON FeatureCollection and map style. *
95-99: Update JSDoc to reflect MapLibre migration.The JSDoc still references "Mapbox map" but the implementation now uses MapLibre.
/** - * Renders a map view of a farm field. + * Renders a MapLibre map view of a farm field. * - * This component uses data retrieved from the loader to display a non-interactive Mapbox map with the field overlaid as a styled layer. It computes the view state and field styles, then conditionally renders the map on the client side with a skeleton fallback. + * This component uses data retrieved from the loader to display a non-interactive map with the field overlaid as a styled layer. It computes the view state and field styles, then conditionally renders the map on the client side with a skeleton fallback.
🧹 Nitpick comments (10)
fdm-app/app/components/blocks/atlas/atlas-styles.tsx (1)
23-23: Type cast toanybypasses type safety.The
as anycast circumvents TypeScript's type checking for the expression specification. While this may be necessary if MapLibre'sExpressionSpecificationtype doesn't accommodate the dynamic array construction, consider verifying whether a more type-safe approach exists.fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx (1)
91-103: Update JSDoc to reflect MapLibre migration.The JSDoc still references "Mapbox configuration (token and style)" at line 97, but the implementation now uses MapLibre. Consider updating the documentation to match the current implementation.
fdm-app/app/integrations/map.ts (2)
23-28: Consider using multiple OSM tile servers for improved reliability.Using only
a.tile.openstreetmap.orgmay cause load issues. OSM provides subdomainsa,b, andcfor load balancing.sources: { "osm": { type: "raster", - tiles: ["https://a.tile.openstreetmap.org/{z}/{x}/{y}.png"], + tiles: [ + "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png", + "https://b.tile.openstreetmap.org/{z}/{x}/{y}.png", + "https://c.tile.openstreetmap.org/{z}/{x}/{y}.png", + ], tileSize: 256, attribution: "© OpenStreetMap Contributors", }, },
14-15: Document the hard-coded MapTiler satellite style ID.The style ID
019aca7b-e3d9-7dc7-9b70-84318d91dc9ais not self-documenting. Consider adding a comment or extracting it to a named constant for clarity.+ // MapTiler Satellite Hybrid style + const MAPTILER_SATELLITE_STYLE_ID = "019aca7b-e3d9-7dc7-9b70-84318d91dc9a" if (variant === "standard") { return `https://api.maptiler.com/maps/streets/style.json?key=${maptilerKey}` } - return `https://api.maptiler.com/maps/019aca7b-e3d9-7dc7-9b70-84318d91dc9a/style.json?key=${maptilerKey}` + return `https://api.maptiler.com/maps/${MAPTILER_SATELLITE_STYLE_ID}/style.json?key=${maptilerKey}`fdm-app/app/components/blocks/atlas/atlas-geocoder.tsx (2)
54-54: Consider making the geocoder language configurable.The
accept-language=nlis hardcoded. If the app supports internationalization, consider deriving this from user locale or app configuration.
37-38: Consider adding types for geocoder config and features.Using
anyforconfigandfeaturesreduces type safety. Consider defining proper interfaces for the geocoder API configuration and feature structures.+interface GeocoderConfig { + query: string + limit?: number +} + +interface GeocoderFeature { + id: string | number + type: "Feature" + geometry: { type: "Point"; coordinates: [number, number] } + properties: Record<string, unknown> + place_name: string + place_type: string[] + text: string + center: [number, number] + bbox?: [number, number, number, number] +} + const geocoderApi = { - forwardGeocode: async (config: any) => { - const features: any[] = [] + forwardGeocode: async (config: GeocoderConfig) => { + const features: GeocoderFeature[] = []fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx (1)
70-81: Update JSDoc to reflect MapLibre migration.The JSDoc at lines 73, 77, and 81 still references "Mapbox token" and "Mapbox style". Update to reflect the current MapLibre implementation.
/** * Retrieves farm details and map configurations for rendering the farm map. * - * This loader function extracts the farm ID from route parameters, validates its presence, and uses the current session to fetch the corresponding farm details. It then retrieves the Mapbox token and style configuration, and returns these along with the farm's display name and a URL for available fields. Any errors encountered during processing are transformed using {@link handleLoaderError}. + * This loader function extracts the farm ID from route parameters, validates its presence, and uses the current session to fetch the corresponding farm details. It then retrieves the map style configuration, and returns these along with the farm's display name and a URL for available fields. Any errors encountered during processing are transformed using {@link handleLoaderError}. * * @throws {Response} When the farm ID is missing, the specified farm is not found, or another error occurs during data retrieval. * - * @returns An object containing the farm name, Mapbox token, Mapbox style, and the URL for available fields. + * @returns An object containing the farm name, map style, and the URL for available fields. */fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx (1)
74-82: Update JSDoc to reflect MapLibre migration.The JSDoc references "Mapbox token and style configuration" and "Mapbox token, Mapbox style" but the implementation now uses MapLibre with a unified
mapStyle.fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (1)
37-50: Update JSDoc to reflect MapLibre migration.Multiple JSDoc blocks reference "Mapbox" (lines 38, 43, 47-48, 108). Update to reflect the current MapLibre implementation.
/** - * Loads and processes farm field data along with Mapbox configuration for rendering the farm atlas. + * Loads and processes farm field data along with map configuration for rendering the farm atlas. * * This loader function extracts the farm ID from the route parameters and validates its presence, * retrieves the current user session, and fetches fields associated with the specified farm. * It converts these fields into a GeoJSON FeatureCollection—rounding the field area values for precision— - * and obtains the Mapbox access token and style configuration for map rendering. + * and obtains the map style configuration for rendering. * * @returns An object containing: * - savedFields: A GeoJSON FeatureCollection of the farm fields. - * - mapboxToken: The Mapbox access token. - * - mapboxStyle: The Mapbox style configuration. + * - mapStyle: The map style configuration.Also applies to: 108-109
fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx (1)
113-118: Consider proper typing instead ofas anycast.The
as anycast bypasses type safety. The bounds check is a good defensive guard, but consider defining a proper type for the view state that includes the optionalboundsandfitBoundsOptionsproperties.+interface ViewStateWithBounds { + bounds?: [[number, number], [number, number]] + fitBoundsOptions?: { padding?: number; duration?: number } + // ... other viewState properties +} + useEffect(() => { - const vs = viewState as any - if (vs.bounds) { - mapRef.current?.fitBounds(vs.bounds, vs.fitBoundsOptions) + const vs = viewState as ViewStateWithBounds + if (vs.bounds) { + mapRef.current?.fitBounds(vs.bounds, vs.fitBoundsOptions) } }, [viewState])Alternatively, update
getViewStateto return a properly typed object that includes these properties.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (4)
fdm-app/app/lib/cache.server.tsis excluded by!fdm-app/app/lib/**fdm-app/app/lib/config.server.tsis excluded by!fdm-app/app/lib/**fdm-app/app/lib/config.tsis excluded by!fdm-app/app/lib/**pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (20)
.changeset/metal-fans-brush.md(1 hunks)fdm-app/app/components/blocks/atlas/atlas-controls.tsx(4 hunks)fdm-app/app/components/blocks/atlas/atlas-geocoder.tsx(3 hunks)fdm-app/app/components/blocks/atlas/atlas-panels.tsx(1 hunks)fdm-app/app/components/blocks/atlas/atlas-sources.tsx(6 hunks)fdm-app/app/components/blocks/atlas/atlas-styles.tsx(2 hunks)fdm-app/app/integrations/map.ts(1 hunks)fdm-app/app/integrations/mapbox.ts(0 hunks)fdm-app/app/root.tsx(3 hunks)fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx(0 hunks)fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx(5 hunks)fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx(0 hunks)fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx(6 hunks)fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx(5 hunks)fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx(4 hunks)fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx(5 hunks)fdm-app/app/tailwind.css(1 hunks)fdm-app/app/types/config.d.ts(2 hunks)fdm-app/app/types/public-env.d.ts(1 hunks)fdm-app/package.json(3 hunks)
💤 Files with no reviewable changes (3)
- fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
- fdm-app/app/integrations/mapbox.ts
- fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
🧰 Additional context used
🧠 Learnings (26)
📓 Common learnings
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2025-06-10T13:10:03.154Z
Learning: When facing prop name inconsistencies with react-map-gl (like mapboxAccessToken vs mapboxApiAccessToken), using different import statements can resolve the issue more elegantly than changing prop names across multiple files.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: Map configuration in the application should be modularized using the `useMapConfig` hook and `MapControls` component to maintain consistency across all MapGL instances.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2024-11-25T14:42:26.660Z
Learning: In `fdm-app/app/components/blocks/field-map.tsx`, explicit cleanup of Mapbox GL resources is not necessary, as `react-map-gl` handles it automatically upon component unmount, and `MapRef` does not have a `remove` method.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: MapGL implementations should use the shared `useMapConfig` hook for configuration and `getLayerStyle` utility for consistent styling. The hook supports both interactive and non-interactive maps, handling bounds calculation and view state management.
📚 Learning: 2025-02-19T10:50:50.200Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 82
File: fdm-app/app/entry.client.tsx:13-13
Timestamp: 2025-02-19T10:50:50.200Z
Learning: Sentry DSN being public in client-side code is not a security concern as per Sentry documentation, but it can be made configurable using Vite's environment variables system with the `VITE_` prefix.
Applied to files:
fdm-app/app/types/public-env.d.tsfdm-app/app/root.tsx
📚 Learning: 2025-06-10T13:10:03.154Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2025-06-10T13:10:03.154Z
Learning: When facing prop name inconsistencies with react-map-gl (like mapboxAccessToken vs mapboxApiAccessToken), using different import statements can resolve the issue more elegantly than changing prop names across multiple files.
Applied to files:
fdm-app/app/root.tsxfdm-app/app/components/blocks/atlas/atlas-panels.tsxfdm-app/app/components/blocks/atlas/atlas-styles.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsxfdm-app/package.jsonfdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsxfdm-app/app/components/blocks/atlas/atlas-sources.tsxfdm-app/app/components/blocks/atlas/atlas-controls.tsxfdm-app/app/components/blocks/atlas/atlas-geocoder.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
📚 Learning: 2024-11-25T14:42:26.660Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2024-11-25T14:42:26.660Z
Learning: In `fdm-app/app/components/blocks/field-map.tsx`, explicit cleanup of Mapbox GL resources is not necessary, as `react-map-gl` handles it automatically upon component unmount, and `MapRef` does not have a `remove` method.
Applied to files:
fdm-app/app/root.tsxfdm-app/app/components/blocks/atlas/atlas-panels.tsxfdm-app/app/tailwind.cssfdm-app/app/components/blocks/atlas/atlas-styles.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsxfdm-app/package.jsonfdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsxfdm-app/app/components/blocks/atlas/atlas-sources.tsxfdm-app/app/components/blocks/atlas/atlas-controls.tsx.changeset/metal-fans-brush.mdfdm-app/app/components/blocks/atlas/atlas-geocoder.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
📚 Learning: 2025-06-10T12:20:38.360Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:68-68
Timestamp: 2025-06-10T12:20:38.360Z
Learning: In react-map-gl v8.0.4, the correct prop name for the Mapbox access token in the MapGL component is `mapboxApiAccessToken`, not `mapboxAccessToken` as verified by checking the MapboxProps interface.
Applied to files:
fdm-app/app/root.tsxfdm-app/app/components/blocks/atlas/atlas-panels.tsxfdm-app/app/components/blocks/atlas/atlas-styles.tsxfdm-app/app/types/config.d.tsfdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsxfdm-app/app/components/blocks/atlas/atlas-controls.tsxfdm-app/app/components/blocks/atlas/atlas-geocoder.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
📚 Learning: 2025-06-10T12:20:38.360Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:68-68
Timestamp: 2025-06-10T12:20:38.360Z
Learning: When using MapGL component from react-map-gl, the correct prop name for the Mapbox access token is `mapboxApiAccessToken` as verified by checking the MapboxProps interface. This should be consistent across all usages of the MapGL component.
Applied to files:
fdm-app/app/root.tsxfdm-app/app/components/blocks/atlas/atlas-panels.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsxfdm-app/app/components/blocks/atlas/atlas-controls.tsxfdm-app/app/components/blocks/atlas/atlas-geocoder.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
📚 Learning: 2025-01-31T16:06:33.810Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: Map configuration in the application should be modularized using the `useMapConfig` hook and `MapControls` component to maintain consistency across all MapGL instances.
Applied to files:
fdm-app/app/root.tsxfdm-app/app/components/blocks/atlas/atlas-panels.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsxfdm-app/app/components/blocks/atlas/atlas-sources.tsxfdm-app/app/components/blocks/atlas/atlas-controls.tsxfdm-app/app/components/blocks/atlas/atlas-geocoder.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._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/root.tsxfdm-app/app/components/blocks/atlas/atlas-sources.tsx
📚 Learning: 2025-07-24T08:29:44.044Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 198
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.balance.nitrogen.$b_id.tsx:146-148
Timestamp: 2025-07-24T08:29:44.044Z
Learning: In React Router v7, the defer() function has been removed. Instead, loaders can return promises directly in the response object, and components use Suspense and Await to handle them without needing defer().
Applied to files:
fdm-app/app/root.tsx
📚 Learning: 2025-01-31T14:29:37.599Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas.d.tsx:8-8
Timestamp: 2025-01-31T14:29:37.599Z
Learning: In the Atlas component's MapFieldsProps interface, mapStyle is intentionally restricted to "mapbox://styles/mapbox/satellite-streets-v12" as it's currently the only supported style option.
Applied to files:
fdm-app/app/root.tsxfdm-app/app/components/blocks/atlas/atlas-panels.tsxfdm-app/app/integrations/map.tsfdm-app/app/components/blocks/atlas/atlas-styles.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsxfdm-app/app/components/blocks/atlas/atlas-sources.tsxfdm-app/app/components/blocks/atlas/atlas-controls.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
📚 Learning: 2025-01-31T15:06:35.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas-sources.tsx:21-66
Timestamp: 2025-01-31T15:06:35.764Z
Learning: In react-map-gl components, when querying rendered features via map.queryRenderedFeatures(), the effect's dependency array must include any props that affect the map's rendered state (like source data) to ensure features are queried against the current map state.
Applied to files:
fdm-app/app/root.tsxfdm-app/app/components/blocks/atlas/atlas-panels.tsxfdm-app/app/components/blocks/atlas/atlas-styles.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsxfdm-app/app/components/blocks/atlas/atlas-sources.tsxfdm-app/app/components/blocks/atlas/atlas-controls.tsxfdm-app/app/components/blocks/atlas/atlas-geocoder.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._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/root.tsxfdm-app/app/components/blocks/atlas/atlas-sources.tsx
📚 Learning: 2025-01-31T15:41:43.741Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas-panels.tsx:28-28
Timestamp: 2025-01-31T15:41:43.741Z
Learning: When handling different map event types in react-map-gl v7.1.8, use MapLayerMouseEvent for mouse events (which have the point property) and ViewStateChangeEvent for view state changes. Use a type guard like 'point' in evt to safely access event-specific properties.
Applied to files:
fdm-app/app/components/blocks/atlas/atlas-panels.tsxfdm-app/app/components/blocks/atlas/atlas-styles.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsxfdm-app/app/components/blocks/atlas/atlas-sources.tsxfdm-app/app/components/blocks/atlas/atlas-controls.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
📚 Learning: 2025-01-31T16:06:33.810Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: MapGL implementations should use the shared `useMapConfig` hook for configuration and `getLayerStyle` utility for consistent styling. The hook supports both interactive and non-interactive maps, handling bounds calculation and view state management.
Applied to files:
fdm-app/app/integrations/map.tsfdm-app/app/components/blocks/atlas/atlas-styles.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsxfdm-app/app/components/blocks/atlas/atlas-sources.tsxfdm-app/app/components/blocks/atlas/atlas-controls.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._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/types/config.d.ts
📚 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.$b_id_farm.$calendar.field.new.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._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: The `FarmLayout` component in `components/custom/farm-layout.tsx` provides a reusable layout structure for farm-related pages, with support for farm selection dropdown, customizable breadcrumb titles, and flexible content rendering through either children or Outlet components.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
📚 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/routes/farm.$b_id_farm.$calendar.field.new.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._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 comprehensive farm layout system has been created in `components/custom/farm-layouts/` with `BaseFarmLayout` and `FarmSidebarLayout` components. The system supports both simple and sidebar-based layouts while maintaining consistent header and farm selection functionality across all farm routes.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
📚 Learning: 2025-06-02T10:31:27.097Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 151
File: fdm-app/app/routes/signin._index.tsx:101-101
Timestamp: 2025-06-02T10:31:27.097Z
Learning: In fdm-app/app/routes/signin._index.tsx, the redirect destinations are intentionally inconsistent by design: the component defaults new sign-ins to "/welcome" (line 101) while the loader redirects authenticated users to "/farm" (line 80) and the action uses "/farm" as fallback (line 434). This creates appropriate user flows where new users complete their profile via the welcome page, while existing authenticated users bypass it and go directly to the main application.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._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: The farm layout system has been reorganized into separate components (`FarmHeader`, `ContentLayout`, `PaginationLayout`) to support different navigation patterns (sidebar, pagination) while maintaining consistent styling. Each layout component is designed to be used independently or combined as needed.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._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/routes/farm.$b_id_farm.$calendar.field.new.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsxfdm-app/app/components/blocks/atlas/atlas-sources.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.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/package.json
📚 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/atlas/atlas-sources.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/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.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/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
🧬 Code graph analysis (5)
fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx (1)
fdm-app/app/integrations/map.ts (1)
getMapStyle(4-65)
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx (1)
fdm-app/app/integrations/map.ts (1)
getMapStyle(4-65)
fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx (1)
fdm-app/app/integrations/map.ts (1)
getMapStyle(4-65)
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx (1)
fdm-app/app/integrations/map.ts (1)
getMapStyle(4-65)
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (1)
fdm-app/app/integrations/map.ts (1)
getMapStyle(4-65)
⏰ Context from checks skipped due to timeout of 300000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: core (24)
🔇 Additional comments (22)
.changeset/metal-fans-brush.md (1)
1-5: LGTM!The changeset file is correctly formatted and appropriately documents the patch version bump for the Mapbox to MapLibre migration. The description clearly communicates the intent of the changes.
fdm-app/app/components/blocks/atlas/atlas-sources.tsx (1)
60-60: LGTM: Type safety and null checks improved.The explicit
MapLayerMouseEventtyping and property guards enhance type safety and prevent potential runtime errors during the MapLibre migration. The null checks forsetFieldsDataand property guards for feature comparisons are defensive coding best practices.Also applies to: 80-81, 117-130
fdm-app/package.json (1)
21-21: Let me also check the maplibre-gl version:
<function_calls>
maplibre-gl latest stable version npm registry 2025
</function_calls>And let me retrieve the actual package.json content to see the versions currently specified:
<function_calls>
#!/bin/bashFind all package.json files and show maplibre-related dependencies
find . -name "package.json" -path "/fdm-app/" -type f -exec grep -l "maplibre" {} ;
</function_calls>fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx (3)
15-16: LGTM on MapLibre import migration.The imports are correctly updated to use
react-map-gl/maplibreandmaplibre-glfor the MapLibre integration.
197-198: LGTM on loader data shape update.The loader correctly returns
mapStylefrom the centralizedgetMapStyleutility, aligning with the migration pattern across the codebase.Also applies to: 211-211
385-386: LGTM on MapGL props update.The MapGL component correctly receives
mapStyleandmapLib={maplibregl}, consistent with the MapLibre migration pattern. Based on learnings, using different import statements (react-map-gl/maplibre) resolves prop name inconsistencies elegantly.fdm-app/app/components/blocks/atlas/atlas-geocoder.tsx (2)
153-156: LGTM on MapLibre integration.The
onAddmethod correctly acceptsMapLibreMaptype and theas anycast for the geocoder's internalonAddis an acceptable workaround for library type mismatches.
36-48: The MapTiler response format is already correct and requires no transformation.Based on web search verification:
- MapTiler API natively returns a GeoJSON FeatureCollection with
type: "FeatureCollection"and afeaturesarray—the exact format that MapLibre GL geocoder expects.- OSM/Nominatim returns a plain JSON array, which is why the code wraps it as
{ features }to match the FeatureCollection format.Returning MapTiler's response directly (line 48:
return data) is correct. The apparent "inconsistency" with the OSM branch is intentional and necessary because the two APIs return different base structures. No additional transformation of the MapTiler response is needed.fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx (3)
18-19: LGTM on MapLibre imports.Imports correctly updated for MapLibre migration.
Also applies to: 49-49
171-172: LGTM on loader and MapGL integration.The loader correctly returns
mapStyleand the MapGL component properly usesmapStyleandmapLib={maplibregl}.Also applies to: 182-182, 300-301
351-356: Type cast workaround for Layer layout prop.The
as anycast is a reasonable workaround when merging layout into the style object. This pattern is consistent across the codebase.fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx (2)
22-23: LGTM on MapLibre imports.Imports correctly updated for MapLibre migration.
Also applies to: 53-53
161-162: LGTM on loader and MapGL integration.The migration is correctly implemented with
getMapStyle("satellite")in the loader and proper MapGL props.Also applies to: 170-170, 262-263
fdm-app/app/components/blocks/atlas/atlas-controls.tsx (2)
2-2: LGTM on MapLibre type and import updates.Types correctly updated from Mapbox to MapLibre.
Also applies to: 10-10
57-57: LGTM on MapLibre CSS class and type updates.CSS classes correctly migrated from
mapboxgl-*tomaplibregl-*, and_mapproperty type updated toMapLibreMap.Also applies to: 73-73, 82-82, 85-85
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (3)
9-10: LGTM on MapLibre imports.Imports correctly updated for MapLibre migration.
Also applies to: 19-19
94-95: LGTM on loader and MapGL integration.The migration is correctly implemented, consistent with the broader MapLibre migration pattern across the codebase.
Also applies to: 101-101, 164-165
190-192: Type cast workaround for Layer layout prop.The
as anycast is consistent with the pattern used in other files for merging layout into the style object.fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx (4)
4-5: LGTM! Clean migration to MapLibre imports.Using
react-map-gl/maplibreis the correct approach for MapLibre integration, which elegantly handles prop name differences compared to the Mapbox variant. Based on learnings, this import pattern resolves prop inconsistencies more cleanly than changing prop names across multiple files.
66-67: Good use ofas constfor type narrowing.Using
"Feature" as constensures the type is narrowed to the literal"Feature"rather thanstring, which is correct for GeoJSON typing.
140-145: VerifyinteractiveLayerIdsusage withinteractive={false}.The map is set to
interactive={false}butinteractiveLayerIdsis still specified. While this may be intentional (perhaps for future use or consistency with other map instances), consider removinginteractiveLayerIdsif the map will never be interactive, as it's unnecessary.
174-184: Action function validates but returns nothing.The action validates the presence of
b_idbut doesn't perform any action or return a value. If this is intentional (e.g., a placeholder for future functionality), consider adding a comment. Otherwise, verify if this action should be removed or if it's missing implementation.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
fdm-app/app/integrations/map.ts (1)
10-13: Consider extracting MapTiler style IDs as named constants.The satellite style uses a hardcoded UUID (
019aca7b-e3d9-7dc7-9b70-84318d91dc9a) which appears to be a custom MapTiler style. Consider extracting this to a named constant with a brief comment explaining what this style represents, improving maintainability.+// MapTiler style identifiers +const MAPTILER_STREETS_STYLE = "streets" +const MAPTILER_SATELLITE_STYLE = "019aca7b-e3d9-7dc7-9b70-84318d91dc9a" // Custom satellite hybrid style + export function getMapStyle(variant: "satellite" | "standard"): string | StyleSpecification { const { provider, maptilerKey } = clientConfig.integrations.map if (provider === "maptiler") { if (maptilerKey) { // MapTiler styles if (variant === "standard") { - return `https://api.maptiler.com/maps/streets/style.json?key=${maptilerKey}` + return `https://api.maptiler.com/maps/${MAPTILER_STREETS_STYLE}/style.json?key=${maptilerKey}` } - return `https://api.maptiler.com/maps/019aca7b-e3d9-7dc7-9b70-84318d91dc9a/style.json?key=${maptilerKey}` + return `https://api.maptiler.com/maps/${MAPTILER_SATELLITE_STYLE}/style.json?key=${maptilerKey}` }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
fdm-app/app/integrations/map.ts(1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: MapGL implementations should use the shared `useMapConfig` hook for configuration and `getLayerStyle` utility for consistent styling. The hook supports both interactive and non-interactive maps, handling bounds calculation and view state management.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: Map configuration in the application should be modularized using the `useMapConfig` hook and `MapControls` component to maintain consistency across all MapGL instances.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2025-06-10T13:10:03.154Z
Learning: When facing prop name inconsistencies with react-map-gl (like mapboxAccessToken vs mapboxApiAccessToken), using different import statements can resolve the issue more elegantly than changing prop names across multiple files.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas.d.tsx:8-8
Timestamp: 2025-01-31T14:29:37.599Z
Learning: In the Atlas component's MapFieldsProps interface, mapStyle is intentionally restricted to "mapbox://styles/mapbox/satellite-streets-v12" as it's currently the only supported style option.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2024-11-25T14:42:26.660Z
Learning: In `fdm-app/app/components/blocks/field-map.tsx`, explicit cleanup of Mapbox GL resources is not necessary, as `react-map-gl` handles it automatically upon component unmount, and `MapRef` does not have a `remove` method.
📚 Learning: 2025-01-31T14:29:37.599Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas.d.tsx:8-8
Timestamp: 2025-01-31T14:29:37.599Z
Learning: In the Atlas component's MapFieldsProps interface, mapStyle is intentionally restricted to "mapbox://styles/mapbox/satellite-streets-v12" as it's currently the only supported style option.
Applied to files:
fdm-app/app/integrations/map.ts
📚 Learning: 2025-01-31T16:06:33.810Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: MapGL implementations should use the shared `useMapConfig` hook for configuration and `getLayerStyle` utility for consistent styling. The hook supports both interactive and non-interactive maps, handling bounds calculation and view state management.
Applied to files:
fdm-app/app/integrations/map.ts
📚 Learning: 2025-06-10T12:20:38.360Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:68-68
Timestamp: 2025-06-10T12:20:38.360Z
Learning: When using MapGL component from react-map-gl, the correct prop name for the Mapbox access token is `mapboxApiAccessToken` as verified by checking the MapboxProps interface. This should be consistent across all usages of the MapGL component.
Applied to files:
fdm-app/app/integrations/map.ts
🔇 Additional comments (1)
fdm-app/app/integrations/map.ts (1)
21-44: Well-structured fallback with proper attribution.The fallback styles are correctly implemented with required attributions for OSM and Esri. The inline
StyleSpecificationobjects are valid and type-safe.One consideration: OpenStreetMap's tile usage policy requires that heavy usage (production apps) use a commercial provider or self-hosted tiles. Since this is a fallback path (when MapTiler key is missing), this should be acceptable for development/emergency use, but ensure production deployments have a valid MapTiler key configured.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (1)
190-192: Type assertion toanybypasses type checking.The
as anycast works around a type mismatch when mergingfieldsAvailableStylewith thelayoutproperty. While functional, this suppresses potential type errors.Consider defining a proper type or using a more specific assertion if the
Layercomponent's props type is available:-<Layer - {...({ ...fieldsAvailableStyle, layout: layerLayout } as any)} -/> +<Layer + {...fieldsAvailableStyle} + layout={layerLayout} +/>If the above doesn't compile due to type constraints, the current approach is acceptable as a pragmatic workaround for the library migration.
fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx (1)
114-117: Type assertion toanymasks potential type mismatch.The cast
viewState as anyto accessboundsandfitBoundsOptionssuggests thatgetViewStatereturns a type that doesn't expose these properties, even though the implementation may include them.Consider updating the return type of
getViewStateinatlas-viewstate.tsto properly exposeboundsandfitBoundsOptions, which would eliminate the need for this cast and improve type safety:-const vs = viewState as any -if (vs.bounds) { - mapRef.current?.fitBounds(vs.bounds, vs.fitBoundsOptions) -} +if ('bounds' in viewState && viewState.bounds) { + mapRef.current?.fitBounds( + viewState.bounds as LngLatBoundsLike, + viewState.fitBoundsOptions + ) +}Alternatively, update
getViewState's return type to includebounds?: LngLatBoundsLikeandfitBoundsOptions?: FitBoundsOptions.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
fdm-app/app/integrations/map.ts(1 hunks)fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx(6 hunks)fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx(7 hunks)fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx(6 hunks)fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx(5 hunks)fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx(6 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- fdm-app/app/integrations/map.ts
- fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
🧰 Additional context used
🧠 Learnings (19)
📓 Common learnings
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: Map configuration in the application should be modularized using the `useMapConfig` hook and `MapControls` component to maintain consistency across all MapGL instances.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: MapGL implementations should use the shared `useMapConfig` hook for configuration and `getLayerStyle` utility for consistent styling. The hook supports both interactive and non-interactive maps, handling bounds calculation and view state management.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2024-11-25T14:42:26.660Z
Learning: In `fdm-app/app/components/blocks/field-map.tsx`, explicit cleanup of Mapbox GL resources is not necessary, as `react-map-gl` handles it automatically upon component unmount, and `MapRef` does not have a `remove` method.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2025-06-10T13:10:03.154Z
Learning: When facing prop name inconsistencies with react-map-gl (like mapboxAccessToken vs mapboxApiAccessToken), using different import statements can resolve the issue more elegantly than changing prop names across multiple files.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas.d.tsx:8-8
Timestamp: 2025-01-31T14:29:37.599Z
Learning: In the Atlas component's MapFieldsProps interface, mapStyle is intentionally restricted to "mapbox://styles/mapbox/satellite-streets-v12" as it's currently the only supported style option.
📚 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.fields.$b_id._index.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2024-11-25T14:42:26.660Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2024-11-25T14:42:26.660Z
Learning: In `fdm-app/app/components/blocks/field-map.tsx`, explicit cleanup of Mapbox GL resources is not necessary, as `react-map-gl` handles it automatically upon component unmount, and `MapRef` does not have a `remove` method.
Applied to files:
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-06-10T13:10:03.154Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2025-06-10T13:10:03.154Z
Learning: When facing prop name inconsistencies with react-map-gl (like mapboxAccessToken vs mapboxApiAccessToken), using different import statements can resolve the issue more elegantly than changing prop names across multiple files.
Applied to files:
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.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: The `FarmLayout` component in `components/custom/farm-layout.tsx` provides a reusable layout structure for farm-related pages, with support for farm selection dropdown, customizable breadcrumb titles, and flexible content rendering through either children or Outlet components.
Applied to files:
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-06-02T10:31:27.097Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 151
File: fdm-app/app/routes/signin._index.tsx:101-101
Timestamp: 2025-06-02T10:31:27.097Z
Learning: In fdm-app/app/routes/signin._index.tsx, the redirect destinations are intentionally inconsistent by design: the component defaults new sign-ins to "/welcome" (line 101) while the loader redirects authenticated users to "/farm" (line 80) and the action uses "/farm" as fallback (line 434). This creates appropriate user flows where new users complete their profile via the welcome page, while existing authenticated users bypass it and go directly to the main application.
Applied to files:
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._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 comprehensive farm layout system has been created in `components/custom/farm-layouts/` with `BaseFarmLayout` and `FarmSidebarLayout` components. The system supports both simple and sidebar-based layouts while maintaining consistent header and farm selection functionality across all farm routes.
Applied to files:
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._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/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
📚 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/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
📚 Learning: 2025-01-31T14:29:37.599Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas.d.tsx:8-8
Timestamp: 2025-01-31T14:29:37.599Z
Learning: In the Atlas component's MapFieldsProps interface, mapStyle is intentionally restricted to "mapbox://styles/mapbox/satellite-streets-v12" as it's currently the only supported style option.
Applied to files:
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-01-31T15:06:35.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas-sources.tsx:21-66
Timestamp: 2025-01-31T15:06:35.764Z
Learning: In react-map-gl components, when querying rendered features via map.queryRenderedFeatures(), the effect's dependency array must include any props that affect the map's rendered state (like source data) to ensure features are queried against the current map state.
Applied to files:
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-01-31T15:41:43.741Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas-panels.tsx:28-28
Timestamp: 2025-01-31T15:41:43.741Z
Learning: When handling different map event types in react-map-gl v7.1.8, use MapLayerMouseEvent for mouse events (which have the point property) and ViewStateChangeEvent for view state changes. Use a type guard like 'point' in evt to safely access event-specific properties.
Applied to files:
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-01-31T16:06:33.810Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: MapGL implementations should use the shared `useMapConfig` hook for configuration and `getLayerStyle` utility for consistent styling. The hook supports both interactive and non-interactive maps, handling bounds calculation and view state management.
Applied to files:
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-01-31T16:06:33.810Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: Map configuration in the application should be modularized using the `useMapConfig` hook and `MapControls` component to maintain consistency across all MapGL instances.
Applied to files:
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-06-10T12:20:38.360Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:68-68
Timestamp: 2025-06-10T12:20:38.360Z
Learning: When using MapGL component from react-map-gl, the correct prop name for the Mapbox access token is `mapboxApiAccessToken` as verified by checking the MapboxProps interface. This should be consistent across all usages of the MapGL component.
Applied to files:
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-06-10T12:20:38.360Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:68-68
Timestamp: 2025-06-10T12:20:38.360Z
Learning: In react-map-gl v8.0.4, the correct prop name for the Mapbox access token in the MapGL component is `mapboxApiAccessToken`, not `mapboxAccessToken` as verified by checking the MapboxProps interface.
Applied to files:
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.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/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.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/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.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: The farm layout system has been reorganized into separate components (`FarmHeader`, `ContentLayout`, `PaginationLayout`) to support different navigation patterns (sidebar, pagination) while maintaining consistent styling. Each layout component is designed to be used independently or combined as needed.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
🧬 Code graph analysis (4)
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx (1)
fdm-app/app/integrations/map.ts (1)
getMapStyle(4-23)
fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx (1)
fdm-app/app/integrations/map.ts (1)
getMapStyle(4-23)
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (1)
fdm-app/app/integrations/map.ts (1)
getMapStyle(4-23)
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx (1)
fdm-app/app/integrations/map.ts (1)
getMapStyle(4-23)
🔇 Additional comments (13)
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx (3)
15-16: LGTM!The import migration from
react-map-gl/mapboxtoreact-map-gl/maplibreand addition ofmaplibreglimport is correctly implemented for the MapLibre integration.
197-198: LGTM!The loader correctly uses
getMapStyle("satellite")and returns the unifiedmapStyleproperty, aligning with the new MapLibre-based configuration pattern.Also applies to: 211-211
385-386: LGTM!The
MapGLcomponent correctly receivesmapStylefrom loader data andmapLib={maplibregl}as required by the MapLibre integration.fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (2)
9-10: LGTM!The import migration to
react-map-gl/maplibre,maplibregl, andgetMapStyleis correctly implemented.Also applies to: 19-19
94-95: LGTM!The loader correctly uses
getMapStyle("satellite")and returns the unifiedmapStyleproperty.Also applies to: 101-101
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx (4)
22-23: LGTM!The import migration to
react-map-gl/maplibre,maplibregl, andgetMapStyleis correctly implemented.Also applies to: 53-53
161-162: LGTM!The loader correctly uses
getMapStyle("satellite")and returns the unifiedmapStyleproperty, consistent with the migration pattern across other routes.Also applies to: 170-170
262-263: LGTM!The
MapGLcomponent correctly receivesmapStylefrom loader data andmapLib={maplibregl}.
311-316: Consistent use of type assertion for Layer props.Same
as anypattern as infarm.$b_id_farm.$calendar.atlas.fields._index.tsx. This is acceptable as a pragmatic workaround during the library migration.Also applies to: 326-331
fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx (4)
4-5: LGTM!The import migration to
react-map-gl/maplibre,maplibregl, andgetMapStyleis correctly implemented.Also applies to: 19-19
67-67: LGTM!Using
"Feature" as constfor the type property improves type narrowing and ensures TypeScript infers the literal type correctly.
82-83: LGTM!The loader correctly uses
getMapStyle("satellite")and returns the unifiedmapStyleproperty.Also applies to: 88-88
142-143: LGTM!The
MapGLcomponent correctly receivesmapStylefrom loader data andmapLib={maplibregl}.
There was a problem hiding this comment.
Actionable comments posted: 3
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/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx (1)
7-7: Remove unused import.
useLoaderDatais imported but never used in the component (the component only renders a placeholder message).- useLoaderData,
♻️ Duplicate comments (1)
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (1)
37-48: Align loader JSDoc with actual return shape and behaviorThe implementation now only fetches a style (no token) and returns it as
mapStyle, but the JSDoc still mentions an “access token” and listsMapStyle(capital M):
- Line 43: “obtains the Maplibre access token and style configuration” is stale.
- Line 47: Bullet label
MapStyledoesn’t match the returned keymapStyle.Suggested update:
- * and obtains the Maplibre access token and style configuration for map rendering. + * and obtains the MapLibre style configuration for map rendering. ... * @returns An object containing: * - savedFields: A GeoJSON FeatureCollection of the farm fields. - * - MapStyle: The Maplibre style configuration. + * - mapStyle: The MapLibre style configuration.This keeps the docs consistent with the loader’s current return object.
Also applies to: 93-101
🧹 Nitpick comments (5)
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx (1)
77-79: Loader data is fetched but never consumed.The loader returns field data, but the component (lines 90-107) renders only a placeholder message and doesn't use
useLoaderData(). If this route is intentionally a work-in-progress placeholder, consider removing the field-fetching logic until the elevation feature is implemented to avoid unnecessary database queries.If the elevation feature isn't ready, simplify the loader:
export async function loader({ request, params }: LoaderFunctionArgs) { try { - // Get the farm id const b_id_farm = params.b_id_farm if (!b_id_farm) { throw data("Farm ID is required", { status: 400, statusText: "Farm ID is required", }) } - - // Get the session - const session = await getSession(request) - - // Get timeframe from calendar store - const timeframe = getTimeframe(params) - - // Get the fields of the farm - const fields = await getFields( - fdm, - session.principal_id, - b_id_farm, - timeframe, - ) - const features = fields.map((field) => { - const feature = { - type: "Feature", - properties: { - b_id: field.b_id, - b_name: field.b_name, - b_area: Math.round(field.b_area * 10) / 10, - }, - geometry: field.b_geometry, - } - return feature - }) - - const featureCollection = { - type: "FeatureCollection", - features: features, - } - - // Return user information from loader - return { - fields: featureCollection, - } + + return {} } catch (error) { throw handleLoaderError(error) } }fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx (1)
82-84: Loader data is fetched but never consumed.The loader returns field data, but the component (lines 96-113) renders only a placeholder message and doesn't use
useLoaderData(). If this route is intentionally a work-in-progress placeholder, consider removing the field-fetching logic until the soil feature is implemented to avoid unnecessary database queries.If the soil feature isn't ready, simplify the loader:
export async function loader({ request, params }: LoaderFunctionArgs) { try { - // Get the farm id const b_id_farm = params.b_id_farm if (!b_id_farm) { throw data("Farm ID is required", { status: 400, statusText: "Farm ID is required", }) } - - // Get the session - const session = await getSession(request) - - // Get timeframe from calendar store - const timeframe = getTimeframe(params) - - // Get the fields of the farm - const fields = await getFields( - fdm, - session.principal_id, - b_id_farm, - timeframe, - ) - const features = fields.map((field) => { - const feature = { - type: "Feature", - properties: { - b_id: field.b_id, - b_name: field.b_name, - b_area: Math.round(field.b_area * 10) / 10, - }, - geometry: field.b_geometry, - } - return feature - }) - - const featureCollection = { - type: "FeatureCollection", - features: features, - } - - // Return user information from loader - return { - fields: featureCollection, - } + + return {} } catch (error) { throw handleLoaderError(error) } }fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (2)
4-11: MapLibre integration looks correct; you can probably drop the explicitmapLibwiringUsing
Map/Layer/types fromreact-map-gl/maplibreplusmapStyle={loaderData.mapStyle}matches the MapLibre wrapper API, andgetMapStyle("satellite")keeps the loader/view contract clean.Given the docs, when importing from
react-map-gl/maplibre,mapLibalready defaults toimport('maplibre-gl'), so you likely don't need:import maplibregl from "maplibre-gl" <MapGL ... mapLib={maplibregl} />Dropping the static import and
mapLibprop would simplify this file and may also reduce bundle size / avoid potential SSR issues with eagerly importingmaplibre-gl.Also applies to: 19-19, 159-165
189-191: Avoidas anyonLayerprops; prefer a typed layer style objectThe new pattern
<Layer {...({ ...fieldsAvailableStyle, layout: layerLayout } as any)} />works but throws away type safety and makes it easier to accidentally pass an invalid style.
If possible, prefer a typed style object and drop the
as any, e.g.:// Example sketch — exact type depends on what getFieldsStyle returns import type { FillLayer } from "react-map-gl/maplibre" const fieldsAvailableLayer: FillLayer = { ...fieldsAvailableStyle, layout: layerLayout, }and then:
<Layer {...fieldsAvailableLayer} />or, if the previous API still compiles with MapLibre types, simply revert to:
<Layer {...fieldsAvailableStyle} layout={layerLayout} />Either approach preserves type checking without changing runtime behavior.
fdm-app/app/components/blocks/atlas/atlas-panels.tsx (1)
4-8: Align hover handler event typing with MapLibre’s event model and guard onpoint.
MapLibreZoomEventis the type used forboxzoom*events in MapLibre, while your listener is wired to"zoom"and"load"(which use genericMapLibreEventand do not expose apointproperty). At the same time,updatePanelassumesevt.pointexists for all calls. This was already a bit shaky with Mapbox and remains so after the migration; given you’re touching the event types here, it’s a good moment to tighten this up by relying on mouse events only and guarding thepointaccess.Consider simplifying the signature to mouse events and adding a runtime guard before calling
queryRenderedFeatures:-import type { MapLibreZoomEvent } from "maplibre-gl" @@ -import type { MapLayerMouseEvent as MapMouseEvent } from "react-map-gl/maplibre" -import { useMap } from "react-map-gl/maplibre" +import type { MapLayerMouseEvent as MapMouseEvent } from "react-map-gl/maplibre" +import { useMap } from "react-map-gl/maplibre" @@ - function updatePanel(evt: MapMouseEvent | MapLibreZoomEvent) { + function updatePanel(evt: MapMouseEvent) { if (map) { // Set message about zoom level const zoom = map.getZoom() if (zoom && zoom > zoomLevelFields) { - const features = map.queryRenderedFeatures(evt.point, { + // Ignore non-mouse events (e.g. zoom/load) that do not carry a screen point + if (!evt.point) { + return + } + + const features = map.queryRenderedFeatures(evt.point, { @@ - const featuresExclude = map.queryRenderedFeatures( - evt.point, - { + const featuresExclude = map.queryRenderedFeatures( + evt.point, + {This keeps the MapLibre migration clean, avoids depending on
zoom/loadevents having apoint, and matches the earlier guidance to gate access to mouse-only properties via a guard. Based on learnings and MapLibre docs, this should be safer going forward.Also applies to: 37-59
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
fdm-app/app/lib/cache.server.tsis excluded by!fdm-app/app/lib/**
📒 Files selected for processing (10)
docker-compose.yml(1 hunks)fdm-app/.env.example(1 hunks)fdm-app/README.md(1 hunks)fdm-app/app/components/blocks/atlas/atlas-panels.tsx(2 hunks)fdm-app/app/root.tsx(4 hunks)fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx(1 hunks)fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx(6 hunks)fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx(1 hunks)fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.tsx(1 hunks)fdm-docs/docs/fdm-app/01-introduction-to-fdm-app.md(1 hunks)
✅ Files skipped from review due to trivial changes (2)
- fdm-docs/docs/fdm-app/01-introduction-to-fdm-app.md
- fdm-app/README.md
🧰 Additional context used
🧠 Learnings (31)
📓 Common learnings
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: Map configuration in the application should be modularized using the `useMapConfig` hook and `MapControls` component to maintain consistency across all MapGL instances.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: MapGL implementations should use the shared `useMapConfig` hook for configuration and `getLayerStyle` utility for consistent styling. The hook supports both interactive and non-interactive maps, handling bounds calculation and view state management.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2024-11-25T14:42:26.660Z
Learning: In `fdm-app/app/components/blocks/field-map.tsx`, explicit cleanup of Mapbox GL resources is not necessary, as `react-map-gl` handles it automatically upon component unmount, and `MapRef` does not have a `remove` method.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2025-06-10T13:10:03.154Z
Learning: When facing prop name inconsistencies with react-map-gl (like mapboxAccessToken vs mapboxApiAccessToken), using different import statements can resolve the issue more elegantly than changing prop names across multiple files.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas.d.tsx:8-8
Timestamp: 2025-01-31T14:29:37.599Z
Learning: In the Atlas component's MapFieldsProps interface, mapStyle is intentionally restricted to "mapbox://styles/mapbox/satellite-streets-v12" as it's currently the only supported style option.
📚 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.$b_id_farm.$calendar.atlas.elevation.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.tsx
📚 Learning: 2024-11-25T14:42:26.660Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2024-11-25T14:42:26.660Z
Learning: In `fdm-app/app/components/blocks/field-map.tsx`, explicit cleanup of Mapbox GL resources is not necessary, as `react-map-gl` handles it automatically upon component unmount, and `MapRef` does not have a `remove` method.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsxfdm-app/app/components/blocks/atlas/atlas-panels.tsxfdm-app/app/root.tsx
📚 Learning: 2025-06-02T10:31:27.097Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 151
File: fdm-app/app/routes/signin._index.tsx:101-101
Timestamp: 2025-06-02T10:31:27.097Z
Learning: In fdm-app/app/routes/signin._index.tsx, the redirect destinations are intentionally inconsistent by design: the component defaults new sign-ins to "/welcome" (line 101) while the loader redirects authenticated users to "/farm" (line 80) and the action uses "/farm" as fallback (line 434). This creates appropriate user flows where new users complete their profile via the welcome page, while existing authenticated users bypass it and go directly to the main application.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
📚 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/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.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: The `FarmLayout` component in `components/custom/farm-layout.tsx` provides a reusable layout structure for farm-related pages, with support for farm selection dropdown, customizable breadcrumb titles, and flexible content rendering through either children or Outlet components.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.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/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.tsx
📚 Learning: 2025-04-29T11:28:44.181Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 132
File: fdm-app/app/routes/farm.create.$b_id_farm.$calendar.access.tsx:54-68
Timestamp: 2025-04-29T11:28:44.181Z
Learning: In React Router v7, the `json()` function has been replaced with `data()` for creating responses in loaders and actions.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.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.$b_id_farm.$calendar.atlas.elevation.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.tsx
📚 Learning: 2025-04-29T11:28:44.181Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 132
File: fdm-app/app/routes/farm.create.$b_id_farm.$calendar.access.tsx:54-68
Timestamp: 2025-04-29T11:28:44.181Z
Learning: In React Router v7, the `json()` function has been deprecated and removed. Instead, either return plain JavaScript objects directly from loaders/actions, or use the `data()` function for responses with custom status codes and headers.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.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.$b_id_farm.$calendar.atlas.elevation.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsxfdm-app/app/root.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.$b_id_farm.$calendar.atlas.elevation.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
📚 Learning: 2025-07-24T08:29:44.044Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 198
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.balance.nitrogen.$b_id.tsx:146-148
Timestamp: 2025-07-24T08:29:44.044Z
Learning: In React Router v7, the defer() function has been removed. Instead, loaders can return promises directly in the response object, and components use Suspense and Await to handle them without needing defer().
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsxfdm-app/app/root.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/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsxfdm-app/app/root.tsx
📚 Learning: 2025-01-09T16:07:36.741Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes.ts:81-81
Timestamp: 2025-01-09T16:07:36.741Z
Learning: The route pattern "api/auth/:" in React Router is required for better-auth's handler to function correctly. The auth.handler() method in the route's loader and action functions expects this exact pattern to handle various authentication endpoints including OAuth callbacks, session management, and rate limiting.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
📚 Learning: 2025-07-24T08:29:44.044Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 198
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.balance.nitrogen.$b_id.tsx:146-148
Timestamp: 2025-07-24T08:29:44.044Z
Learning: React Router v7 supports Suspense patterns by returning promises directly from loaders. The pattern is: return { data: somePromise } from loader, then use <Suspense><Await resolve={loaderData.data}>{resolvedData => ...}</Await></Suspense> in components.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.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/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.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.$b_id_farm.$calendar.atlas.elevation.tsx
📚 Learning: 2025-06-10T13:10:03.154Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2025-06-10T13:10:03.154Z
Learning: When facing prop name inconsistencies with react-map-gl (like mapboxAccessToken vs mapboxApiAccessToken), using different import statements can resolve the issue more elegantly than changing prop names across multiple files.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsxfdm-app/app/components/blocks/atlas/atlas-panels.tsxfdm-app/app/root.tsx
📚 Learning: 2025-01-31T14:29:37.599Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas.d.tsx:8-8
Timestamp: 2025-01-31T14:29:37.599Z
Learning: In the Atlas component's MapFieldsProps interface, mapStyle is intentionally restricted to "mapbox://styles/mapbox/satellite-streets-v12" as it's currently the only supported style option.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsxfdm-app/app/root.tsx
📚 Learning: 2025-06-10T12:20:38.360Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:68-68
Timestamp: 2025-06-10T12:20:38.360Z
Learning: In react-map-gl v8.0.4, the correct prop name for the Mapbox access token in the MapGL component is `mapboxApiAccessToken`, not `mapboxAccessToken` as verified by checking the MapboxProps interface.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsxfdm-app/app/components/blocks/atlas/atlas-panels.tsxfdm-app/app/root.tsx
📚 Learning: 2025-06-10T12:20:38.360Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:68-68
Timestamp: 2025-06-10T12:20:38.360Z
Learning: When using MapGL component from react-map-gl, the correct prop name for the Mapbox access token is `mapboxApiAccessToken` as verified by checking the MapboxProps interface. This should be consistent across all usages of the MapGL component.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsxfdm-app/app/root.tsx
📚 Learning: 2025-01-31T16:06:33.810Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: Map configuration in the application should be modularized using the `useMapConfig` hook and `MapControls` component to maintain consistency across all MapGL instances.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsxfdm-app/app/components/blocks/atlas/atlas-panels.tsxfdm-app/app/root.tsx
📚 Learning: 2025-01-31T16:06:33.810Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: MapGL implementations should use the shared `useMapConfig` hook for configuration and `getLayerStyle` utility for consistent styling. The hook supports both interactive and non-interactive maps, handling bounds calculation and view state management.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsxfdm-app/app/components/blocks/atlas/atlas-panels.tsx
📚 Learning: 2025-01-31T15:41:43.741Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas-panels.tsx:28-28
Timestamp: 2025-01-31T15:41:43.741Z
Learning: When handling different map event types in react-map-gl v7.1.8, use MapLayerMouseEvent for mouse events (which have the point property) and ViewStateChangeEvent for view state changes. Use a type guard like 'point' in evt to safely access event-specific properties.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsxfdm-app/app/components/blocks/atlas/atlas-panels.tsx
📚 Learning: 2025-01-31T15:06:35.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas-sources.tsx:21-66
Timestamp: 2025-01-31T15:06:35.764Z
Learning: In react-map-gl components, when querying rendered features via map.queryRenderedFeatures(), the effect's dependency array must include any props that affect the map's rendered state (like source data) to ensure features are queried against the current map state.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsxfdm-app/app/components/blocks/atlas/atlas-panels.tsxfdm-app/app/root.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/routes/farm.$b_id_farm.$calendar.atlas.soil.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.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/routes/farm.create.$b_id_farm.$calendar.fields.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/routes/farm.create.$b_id_farm.$calendar.fields.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/routes/farm.create.$b_id_farm.$calendar.fields.tsx
📚 Learning: 2025-02-19T10:50:50.200Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 82
File: fdm-app/app/entry.client.tsx:13-13
Timestamp: 2025-02-19T10:50:50.200Z
Learning: Sentry DSN being public in client-side code is not a security concern as per Sentry documentation, but it can be made configurable using Vite's environment variables system with the `VITE_` prefix.
Applied to files:
fdm-app/app/root.tsx
🧬 Code graph analysis (1)
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (1)
fdm-app/app/integrations/map.ts (1)
getMapStyle(4-23)
🪛 ast-grep (0.40.0)
fdm-app/app/root.tsx
[warning] 130-130: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- https://cwe.mitre.org/data/definitions/79.html
(react-unsafe-html-injection)
🔇 Additional comments (6)
fdm-app/.env.example (1)
74-81: LGTM! Excellent documentation.The environment variable documentation is clear and comprehensive. The conditional requirement for
PUBLIC_MAPTILER_API_KEY(only whenPUBLIC_MAP_PROVIDERis "maptiler") is well-explained, and the default value of "osm" is sensible.fdm-app/app/root.tsx (3)
2-2: LGTM! Clean CSS migration.The import and link update from Mapbox GL to MapLibre GL CSS is correct and consistent with the library migration.
Also applies to: 30-30
53-54: LGTM! Runtime environment propagation updated correctly.The replacement of
PUBLIC_MAPBOX_TOKENwithPUBLIC_MAP_PROVIDERandPUBLIC_MAPTILER_API_KEYcorrectly propagates the new configuration to the client runtime.
130-134: LGTM! Safe global polyfill.The comment update to "Maplibre" is appropriate. The static analysis warning about
dangerouslySetInnerHTMLcan be safely ignored here—this is a standard, safe pattern for polyfillingglobalin browser environments with a hardcoded static string.docker-compose.yml (1)
16-17: ```shell
#!/bin/bashCheck config.d.ts and find where clientConfig is instantiated
echo "=== fdm-app/app/types/config.d.ts ==="
cat -n fdm-app/app/types/config.d.tsecho -e "\n=== Search for clientConfig instantiation/assignment ==="
rg -n 'clientConfig\s*=|const clientConfig|export.*clientConfig' --type=ts --type=js -C3echo -e "\n=== Check entry.client.tsx ==="
head -80 fdm-app/app/entry.client.tsx | cat -necho -e "\n=== Check store directory ==="
ls -la fdm-app/app/store/
</function_calls>#!/bin/bash # Continue searching for clientConfig definition echo "=== fdm-app/app/types/config.d.ts ===" cat -n fdm-app/app/types/config.d.ts echo -e "\n=== Search for clientConfig assignment ===" rg -n 'clientConfig' --type=ts --type=js | head -40 echo -e "\n=== Look for ~ alias in vite config ===" cat fdm-app/vite.config.ts | head -50fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (1)
108-112: Updated component-level description matches MapLibre usageThe doc comment now correctly describes this as a MapLibre-backed map consuming preloaded field data and controls. No further changes needed here.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx (1)
33-82: Consider simplifying or deferring the loader implementation.The loader fetches and transforms field data, but the component only renders a placeholder message indicating the elevation map isn't available yet. Since the loader data isn't currently consumed, you might consider either:
- Simplifying the loader to just validate the farm ID until the feature is implemented
- Keeping the current implementation if you plan to complete the elevation map feature soon
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx(1 hunks)fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx(1 hunks)fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.tsx
🧰 Additional context used
🧠 Learnings (18)
📓 Common learnings
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: Map configuration in the application should be modularized using the `useMapConfig` hook and `MapControls` component to maintain consistency across all MapGL instances.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: MapGL implementations should use the shared `useMapConfig` hook for configuration and `getLayerStyle` utility for consistent styling. The hook supports both interactive and non-interactive maps, handling bounds calculation and view state management.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2024-11-25T14:42:26.660Z
Learning: In `fdm-app/app/components/blocks/field-map.tsx`, explicit cleanup of Mapbox GL resources is not necessary, as `react-map-gl` handles it automatically upon component unmount, and `MapRef` does not have a `remove` method.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2025-06-10T13:10:03.154Z
Learning: When facing prop name inconsistencies with react-map-gl (like mapboxAccessToken vs mapboxApiAccessToken), using different import statements can resolve the issue more elegantly than changing prop names across multiple files.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas.d.tsx:8-8
Timestamp: 2025-01-31T14:29:37.599Z
Learning: In the Atlas component's MapFieldsProps interface, mapStyle is intentionally restricted to "mapbox://styles/mapbox/satellite-streets-v12" as it's currently the only supported style option.
📚 Learning: 2024-11-25T14:42:26.660Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2024-11-25T14:42:26.660Z
Learning: In `fdm-app/app/components/blocks/field-map.tsx`, explicit cleanup of Mapbox GL resources is not necessary, as `react-map-gl` handles it automatically upon component unmount, and `MapRef` does not have a `remove` method.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.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.$b_id_farm.$calendar.atlas.soil.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.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/routes/farm.$b_id_farm.$calendar.atlas.soil.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: The `FarmLayout` component in `components/custom/farm-layout.tsx` provides a reusable layout structure for farm-related pages, with support for farm selection dropdown, customizable breadcrumb titles, and flexible content rendering through either children or Outlet components.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.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/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
📚 Learning: 2025-06-02T10:31:27.097Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 151
File: fdm-app/app/routes/signin._index.tsx:101-101
Timestamp: 2025-06-02T10:31:27.097Z
Learning: In fdm-app/app/routes/signin._index.tsx, the redirect destinations are intentionally inconsistent by design: the component defaults new sign-ins to "/welcome" (line 101) while the loader redirects authenticated users to "/farm" (line 80) and the action uses "/farm" as fallback (line 434). This creates appropriate user flows where new users complete their profile via the welcome page, while existing authenticated users bypass it and go directly to the main application.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
📚 Learning: 2025-06-10T13:10:03.154Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2025-06-10T13:10:03.154Z
Learning: When facing prop name inconsistencies with react-map-gl (like mapboxAccessToken vs mapboxApiAccessToken), using different import statements can resolve the issue more elegantly than changing prop names across multiple files.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.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.$b_id_farm.$calendar.atlas.soil.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
📚 Learning: 2025-04-29T11:28:44.181Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 132
File: fdm-app/app/routes/farm.create.$b_id_farm.$calendar.access.tsx:54-68
Timestamp: 2025-04-29T11:28:44.181Z
Learning: In React Router v7, the `json()` function has been replaced with `data()` for creating responses in loaders and actions.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
📚 Learning: 2025-04-29T11:28:44.181Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 132
File: fdm-app/app/routes/farm.create.$b_id_farm.$calendar.access.tsx:54-68
Timestamp: 2025-04-29T11:28:44.181Z
Learning: In React Router v7, the `json()` function has been deprecated and removed. Instead, either return plain JavaScript objects directly from loaders/actions, or use the `data()` function for responses with custom status codes and headers.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
📚 Learning: 2025-01-09T16:07:36.741Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes.ts:81-81
Timestamp: 2025-01-09T16:07:36.741Z
Learning: The route pattern "api/auth/:" in React Router is required for better-auth's handler to function correctly. The auth.handler() method in the route's loader and action functions expects this exact pattern to handle various authentication endpoints including OAuth callbacks, session management, and rate limiting.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
📚 Learning: 2025-07-24T08:29:44.044Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 198
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.balance.nitrogen.$b_id.tsx:146-148
Timestamp: 2025-07-24T08:29:44.044Z
Learning: In React Router v7, the defer() function has been removed. Instead, loaders can return promises directly in the response object, and components use Suspense and Await to handle them without needing defer().
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.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/routes/farm.$b_id_farm.$calendar.atlas.soil.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.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/routes/farm.$b_id_farm.$calendar.atlas.soil.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.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.$b_id_farm.$calendar.atlas.soil.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
📚 Learning: 2025-07-24T08:29:44.044Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 198
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.balance.nitrogen.$b_id.tsx:146-148
Timestamp: 2025-07-24T08:29:44.044Z
Learning: React Router v7 supports Suspense patterns by returning promises directly from loaders. The pattern is: return { data: somePromise } from loader, then use <Suspense><Await resolve={loaderData.data}>{resolvedData => ...}</Await></Suspense> in components.
Applied to files:
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsxfdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.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.$b_id_farm.$calendar.atlas.elevation.tsx
🔇 Additional comments (3)
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx (2)
27-32: JSDoc now accurately reflects the loader's return value.The documentation has been correctly updated to remove references to map style configuration, addressing the previous review feedback. The description now accurately states that only the GeoJSON FeatureCollection of farm fields is returned.
89-106: LGTM!The placeholder component appropriately communicates that the elevation map feature is under development and provides clear navigation to an alternative view.
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx (1)
27-37: Docblock now matches loader behaviorThe updated JSDoc correctly describes that the loader only builds and returns a GeoJSON FeatureCollection (via the
fieldsproperty) and no longer mentions a map style configuration, resolving the earlier discrepancy between docs and implementation.
BoraIneviNMI
left a comment
There was a problem hiding this comment.
Looks good. These changes should ensure the independence from the business practices of the dependency authors.
Summary by CodeRabbit
New Features
Changes
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.