-
Notifications
You must be signed in to change notification settings - Fork 4
Add balances to Organization #515
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
52 commits
Select commit
Hold shift + click to select a range
0f41a5b
Add prototype for organization balance page
BoraIneviNMI 6d4a418
Use batched computation of farm nitrogen balances for organizations
BoraIneviNMI b62603b
Move the multiple-farm calculation function into fdm-calculator
BoraIneviNMI 6429005
Adapt fdm-app to changes
BoraIneviNMI d5bd97a
Add testing WIP
BoraIneviNMI 0160200
Fix tests
BoraIneviNMI a5f0570
Update organization nitrogen balance page
BoraIneviNMI dea8ba4
Merge branch 'development' into FDM493
SvenVw 3f04292
Add sidebar and adjust text in organization nitrogen balance chart
BoraIneviNMI b5d00ff
Move aggregation of farm results to fdm-calculator
BoraIneviNMI 8a1053d
Add tests
BoraIneviNMI 81b658c
Add tests for farm nitrogen balance input
BoraIneviNMI 74d060e
Reuse the batch logic for calculateNitrogenBalance
BoraIneviNMI 40afd8e
Fix failing test
BoraIneviNMI 0e271a8
Move fertilizer chunking logic to fdm-core and test it
BoraIneviNMI 08bdc11
Add more tests and fix some
BoraIneviNMI 0d6e09b
Rename some things and clean up
BoraIneviNMI 35322ea
Add organic matter balance for organisations
BoraIneviNMI 5a040f2
Remove mock email sending
BoraIneviNMI bed80e5
Nitpicks
BoraIneviNMI d53bc11
Improve navigation
BoraIneviNMI 430f01a
Move farm select dialog into a separate component
BoraIneviNMI dcb2e74
fix: cache input inconsistency between one farm and multiple farms
BoraIneviNMI a8d4e4b
Test getCultivationsOfFarmsFromCatalogue a bit better
BoraIneviNMI e69e9df
Change the not technically-correct comment about the use(...) hook
BoraIneviNMI 261d0be
fix: dialog does not close when there is no change in the selection o…
BoraIneviNMI 5fe82e0
Typecheck fix
BoraIneviNMI f4a5904
Address nitpicks
BoraIneviNMI 7f15a84
Sure
BoraIneviNMI 87bb6c6
Merge branch 'development' into FDM493
BoraIneviNMI 3ed182d
Replace getFertilizersOfFarms with getFertilizersFromCatalogueForFarms
BoraIneviNMI 4e04875
Make fertilizer type derivation logic shared
BoraIneviNMI 558a32f
Nitpicks
BoraIneviNMI 3fac203
Replace getCultivationsOfFarmsFromCatalogue with getCultivationsFromC…
BoraIneviNMI a437b11
Add internal directive to some JSDoc comments
BoraIneviNMI 9d3a4ab
Address nitpicks
BoraIneviNMI 1ca596f
Fix mock fdm
BoraIneviNMI 68c9f1a
Include all farm IDs for getFertilizersFromCatalogueForFarms and getC…
BoraIneviNMI 406c638
Make sure results are sorted by area
BoraIneviNMI 2fdadcc
Nitpicks
BoraIneviNMI ad92a6e
Display farm areas on the farm select dialog
BoraIneviNMI 6e4e216
Validate farmIds
BoraIneviNMI ae7d3c9
Add changeset
BoraIneviNMI 3e44624
Merge branch 'development' into FDM493
SvenVw 3403720
Merge branch 'development' into FDM493
SvenVw 83b3970
fix: use "Organische stof" consistent
SvenVw eeedde8
refactor: improve the new backend functions
SvenVw 48ec6bb
chore: update the changesets
SvenVw fa074dc
fix: address code review findings in org OM balance route and calcula…
SvenVw 427728e
fix: address code review findings
SvenVw 548af95
fix: db insert in case of race condition
SvenVw 8de9d8a
refactor: address code review comments
SvenVw File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@nmi-agro/fdm-core": minor | ||
| --- | ||
|
|
||
| Added `getEnabledCultivationCataloguesForFarms` and `getEnabledFertilizerCataloguesForFarms` to retrieve the enabled catalogues for multiple farms in one query. Added `getCultivationsFromCatalogues` and `getFertilizersFromCatalogues` to fetch catalogue items for a given list of catalogue source IDs. These composable building blocks replace the removed `getCultivationsFromCatalogueForFarms` and `getFertilizersFromCatalogueForFarms` functions. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@nmi-agro/fdm-app": minor | ||
| --- | ||
|
|
||
| Added organization-level nitrogen and organic matter balance plots with option to exclude certain farms from the calculation. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@nmi-agro/fdm-calculator": minor | ||
| --- | ||
|
|
||
| Added `collectInputForNitrogenBalanceForFarms` and `collectInputForOrganicMatterBalanceForFarms` to collect balance inputs for multiple farms, reducing database lookups by deduplicating catalogue queries across farms. The functions use a composable pattern: first fetch enabled catalogues for all farms in one query, then fetch catalogue items once per unique catalogue, then process each farm individually. |
136 changes: 136 additions & 0 deletions
136
fdm-app/app/components/blocks/balance/farm-select-dialog.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,136 @@ | ||
| import { useRef } from "react" | ||
| import { useSearchParams } from "react-router" | ||
| import { Button } from "~/components/ui/button" | ||
| import { Checkbox } from "~/components/ui/checkbox" | ||
| import { | ||
| Dialog, | ||
| DialogClose, | ||
| DialogContent, | ||
| DialogDescription, | ||
| DialogFooter, | ||
| DialogHeader, | ||
| DialogTitle, | ||
| DialogTrigger, | ||
| } from "~/components/ui/dialog" | ||
|
|
||
| /** | ||
| * Renders a button which, when clicked, shows a dialog where the user can change selection of farms included in balance calculation. | ||
| * | ||
| * - `farms` should be the complete list of farms that the user can select or ignore. | ||
| * - `defaultSelectedFarmIds` should be coming from the loader data after validation, and is used to set the initial state of the checkboxes. | ||
| * | ||
| * The dialog will set the `farmIds` search param directly when the selection changes. | ||
| * | ||
| * @param param0 component props | ||
| * @returns a React node | ||
| */ | ||
| export function FarmSelectDialog({ | ||
| farms, | ||
| defaultSelectedFarmIds, | ||
| }: { | ||
| farms: { | ||
| b_id_farm: string | ||
| b_name_farm: string | null | ||
| b_area_farm: number | ||
| }[] | ||
| defaultSelectedFarmIds: string[] | ||
| }) { | ||
| const formRef = useRef<HTMLFormElement | null>(null) | ||
| const [, setSearchParams] = useSearchParams() | ||
|
|
||
| return ( | ||
| <Dialog> | ||
| <DialogTrigger asChild> | ||
| <Button variant="outline">Wijzig selectie</Button> | ||
| </DialogTrigger> | ||
| <DialogContent> | ||
| <DialogHeader> | ||
| <DialogTitle>Wijzig selectie van bedrijven</DialogTitle> | ||
| <DialogDescription> | ||
| De geselecteerde bedrijven zijn uitgesloten in de | ||
| berekening. | ||
| </DialogDescription> | ||
| </DialogHeader> | ||
| <form | ||
| ref={formRef} | ||
| className="space-y-4 max-h-50 overflow-y-scroll" | ||
| > | ||
| {farms.flatMap((farm) => { | ||
| const b_id_farm = farm.b_id_farm | ||
| const currentValue = defaultSelectedFarmIds.includes( | ||
| farm.b_id_farm, | ||
| ) | ||
| return ( | ||
| <div | ||
| key={farm.b_id_farm} | ||
| className="flex flex-row items-center gap-4" | ||
| > | ||
| <Checkbox | ||
| name={b_id_farm} | ||
| defaultChecked={!!currentValue} | ||
| /> | ||
| <div className="grow"> | ||
| {farm.b_name_farm ?? "Onbekend"} | ||
| </div> | ||
| <div className="text-muted-foreground"> | ||
| {Math.round(farm.b_area_farm * 10) / 10} ha | ||
| </div> | ||
| </div> | ||
| ) | ||
| })} | ||
| </form> | ||
| <DialogFooter> | ||
| <DialogClose | ||
| asChild | ||
| onClick={() => { | ||
| const form = formRef.current | ||
|
|
||
| const newlySelectedFarmIds: string[] = [] | ||
| if (form) { | ||
| const formData = new FormData(form) | ||
| for (const [ | ||
| b_id_farm, | ||
| selected, | ||
| ] of formData.entries()) { | ||
| if (selected) { | ||
| newlySelectedFarmIds.push(b_id_farm) | ||
| } | ||
| } | ||
| } | ||
| const sortedDefaultSelectedFarmIds = [ | ||
| ...defaultSelectedFarmIds, | ||
| ].sort() | ||
| newlySelectedFarmIds.sort() | ||
| if ( | ||
| sortedDefaultSelectedFarmIds.length !== | ||
| newlySelectedFarmIds.length || | ||
| newlySelectedFarmIds.some( | ||
| (selected_id, index) => | ||
| selected_id !== | ||
| sortedDefaultSelectedFarmIds[index], | ||
| ) | ||
| ) { | ||
| setSearchParams((searchParams) => { | ||
| const newSearchParams = new URLSearchParams( | ||
| searchParams, | ||
| ) | ||
| if (newlySelectedFarmIds.length > 0) { | ||
| newSearchParams.set( | ||
| "farmIds", | ||
| newlySelectedFarmIds.join(","), | ||
| ) | ||
| } else { | ||
| newSearchParams.delete("farmIds") | ||
| } | ||
| return newSearchParams | ||
| }) | ||
| } | ||
| }} | ||
| > | ||
| <Button variant="outline">Opslaan</Button> | ||
| </DialogClose> | ||
| </DialogFooter> | ||
| </DialogContent> | ||
| </Dialog> | ||
| ) | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
36 changes: 36 additions & 0 deletions
36
fdm-app/app/components/blocks/organization/no-farms-message.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| import { NavLink } from "react-router" | ||
| import { Button } from "~/components/ui/button" | ||
| import { | ||
| Empty, | ||
| EmptyContent, | ||
| EmptyDescription, | ||
| EmptyHeader, | ||
| EmptyTitle, | ||
| } from "~/components/ui/empty" | ||
|
|
||
| export function NoFarmsMessage({ | ||
| action, | ||
| }: { | ||
| action?: { label: string; to: string } | ||
| }) { | ||
| return ( | ||
| <Empty className="border-none"> | ||
| <EmptyHeader> | ||
| <EmptyTitle> | ||
| Het lijkt erop dat je organisatie geen toegang heeft tot | ||
| bedrijven. :( | ||
| </EmptyTitle> | ||
| <EmptyDescription> | ||
| Neem contact op met bedrijven om toegang tot hen te krijgen. | ||
| </EmptyDescription> | ||
| </EmptyHeader> | ||
| {action && ( | ||
| <EmptyContent> | ||
| <Button asChild> | ||
| <NavLink to={action.to}>{action.label}</NavLink> | ||
| </Button> | ||
| </EmptyContent> | ||
| )} | ||
| </Empty> | ||
| ) | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.