Skip to content
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

Lf 4483 create selected animals summary component #3530

Open
wants to merge 46 commits into
base: integration
Choose a base branch
from

Conversation

Duncan-Brain
Copy link
Collaborator

@Duncan-Brain Duncan-Brain commented Nov 16, 2024

Description

This creates the animal summary component -- found out yesterday Loic considers this a nice to have. But it is complete now so 🤷 It seems back in scope for read-only + completion views.

Notes:

  • There is a google maps crash on timeout + expanding item -- based on a previous encounter I think it will resolve in production as relating to react strict mode and the fact our google maps package is maybe out of maintenance - Nav menu styling fixes #3059 (comment)
  • Things I am not super comfortable with about the solution:
    • a) re-using the AnimalInventory container and making variants (views) of it, I think containers are meant to be single use for the most part so I might have preferred to split this up more.
    • b) double use of useAnimalInventory() -- one for ExpandableAnimalInventory to calculate animalCount and one for regular animal inventory use. I tried to conditionally render the expandable in a single component but the container height got twitchy when selecting an animal on previous animal selection screen.

Jira link: LF-4483

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration

  • Passes test case
  • UI components visually reviewed on desktop view
  • UI components visually reviewed on mobile view
  • Other (please explain)

Checklist:

  • I have commented my code, particularly in hard-to-understand areas
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • The precommit and linting ran successfully
  • I have added or updated language tags for text that's part of the UI
  • I have added "MISSING" for all new language tags to languages I don't speak
  • I have added the GNU General Public License to all new files

…route' into LF-4483-create-selected-animals-summary-component
…ement-task' into LF-4483-create-selected-animals-summary-component
…name the animal inventory type to avoid name clash
@antsgar
Copy link
Collaborator

antsgar commented Nov 20, 2024

@Duncan-Brain when you branch off of another feature branch, my suggestion is that you set that branch as target for your PR. That way it'll show the right diff and it can be reviewed even if the other PR hasn't been merged yet. Once the other PR is merged, GH will automatically change the target branch to integration for you 🙌

Copy link
Collaborator

@antsgar antsgar left a comment

Choose a reason for hiding this comment

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

Left a few suggestions re code structure but this is looking amazing, I love it!

Comment on lines 87 to 121
const viewConfig = () => {
switch (view) {
case View.TASK:
return {
tableMaxHeight: !isDesktop || !containerHeight ? undefined : containerHeight - usedHeight,
tableSpacerRowHeight: 0,
showInventorySelection: isAdmin,
showSearchBarAndFilter: true,
alternatingRowColor: true,
showTableHeader: isDesktop,
showActionFloaterButton: false,
};
case View.TASK_SUMMARY:
return {
tableMaxHeight: undefined,
tableSpacerRowHeight: 0,
showInventorySelection: false,
showSearchBarAndFilter: false,
alternatingRowColor: isDesktop ? false : true,
showTableHeader: false,
extraRowSpacing: isDesktop,
showActionFloaterButton: false,
};
default:
return {
tableMaxHeight: !isDesktop || !containerHeight ? undefined : containerHeight - usedHeight,
tableSpacerRowHeight: isDesktop ? 96 : 120,
showInventorySelection: isAdmin,
showSearchBarAndFilter: true,
alternatingRowColor: true,
showTableHeader: isDesktop,
showActionFloaterButton: isAdmin,
};
}
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think there's a cleaner way to do this both for container and component that would prevent having to add more combinations of these parameters as we go along (and also a more "React-y" way of doing things, if that term makes any sense 😅), would be to actually make these configurable parameters props for the component, and set a default for them. So everything in the "default" block here would be the default for these props, and then each parent component would have the power to override them to something different if needed. That way we'd just be making the component more flexible, instead of pre-defining a set of uses for it.

If we still thought it was useful to have a defined set of use cases for the component, we could then go ahead and define them as parent components. Something like this:

const AnimalsInventorySummary = () => {
  <AnimalsInventory
    tableMaxHeight={...}
    tableSpacerRowHeight={...}
    ...
  />
}

const AnimalsInventoryTaskSelection = () => {
  <AnimalsInventory
    tableMaxHeight={...}
    tableSpacerRowHeight={...}
    ...
   />
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah I hated this part of it the solution. Good call out. I will do that first suggestion.

My instinct was to make more containers and bundle the reused logic into a hook -- but it seemed liek it would take too long. But ideally we would reuse components and not containers. That would make components like KPI and FloatingActionBar not even be possible for task animals Inventory.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

So I am still not happy with the solution, but I think it is at least better if you could check it out.

selectedInventoryIds: string[],
) => {
if (showOnlySelected) {
return useMemo(() => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Doesn't this break the rules of hooks since you're calling a hook within a conditional? https://react.dev/reference/rules/rules-of-hooks#only-call-hooks-at-the-top-level

I think we could just add a condition to animalOrBatchMatches like so

const animalOrBatchMatches =
        showOnlySelected && selectedInventoryIds.includes(entity.id) ||
        isInactive(animalsOrBatchesFilter) ||
        (entity.batch
          ? animalsOrBatchesFilter[AnimalOrBatchKeys.BATCH]?.active
          : animalsOrBatchesFilter[AnimalOrBatchKeys.ANIMAL]?.active);

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Wow great point about breaking the hook rules that was silly of me. I dont know why I didn't get a warning either. Will do that!

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Tried it the suggested way, but the other matches returned extra results which was not desired.

Because selectedIds is likely to change more frequently I just moved it out of the conditional but kept its own separate useMemo.

@@ -288,4 +340,43 @@ function AnimalInventory({
);
}

export function ExpandableAnimalInventory(props: ExpandableAnimalInventoryProps) {
const { t } = useTranslation();
const { inventory } = useAnimalInventory();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Following up on the idea I mentioned above of having different parent components for the different "versions" of the inventory, we could set inventory as a prop for the AnimalInventory container, and then call useInventory from the parent components. So we'd end up with something like:

const AnimalsInventorySummary = () => {
  const { inventory, isLoading } = useAnimalInventory();
  const animalCount = ...;
  <ExpandableAnimalInventory
    ...
    expandedContent={
      <AnimalsInventory
        inventory={inventory}
        isLoading={isLoading}
        tableMaxHeight={...}
        tableSpacerRowHeight={...}
        ...
       />
    }
  />
}

const AnimalsInventoryTaskSelection = () => {
  const { inventory, isLoading } = useAnimalInventory();
  <AnimalsInventory
    inventory={inventory}
    isLoading={isLoading}
    tableMaxHeight={...}
    tableSpacerRowHeight={...}
    ...
   />
}

so the double call of useAnimalInventory would also be solved

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Let me know what you think of the newer refactor... its still not optimal. Theres just so much shared logic I found it hard to split away without making it look more complex.

Copy link
Collaborator

@kathyavini kathyavini left a comment

Choose a reason for hiding this comment

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

I think this is in progress based on the comments thread, and I'm not done reading the files either, but just wanted to leave a few small notes! It looks good!

@@ -1941,6 +1941,7 @@
"ADD_TASK_FLOW": "task creation",
"AMOUNT_TO_ALLOCATE": "Amount to allocate",
"ANIMAL_MOVING_TO_LOCATION": "Moving to:",
"ANIMAL_MOVEMENT_EXPANDING_SUMMARY_TITLE": "See detail list of animals to move",
Copy link
Collaborator

Choose a reason for hiding this comment

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

I hate to comment because I know it will have to go back around to Loïc, but... it's not grammatical, is it? Shouldn't it be "detailed list"?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think a list of details could be a "detail list" where "detail list" is the object of the sentence. "See a detailed list.. " makes just "list" the object of the sentence with detailed describing it. Its not common but not wrong either I don't think.

@Duncan-Brain Duncan-Brain added the new translations New translations to be sent to CrowdIn are present label Nov 26, 2024
@Duncan-Brain
Copy link
Collaborator Author

So I am still not super happy with the size of the AnimalInventory container -- it almost feels like I would rather duplicate code than have it be used for all these cases... But it works and I think it somewhat resembles TaskLocations style component switching.

Copy link
Collaborator

@kathyavini kathyavini left a comment

Choose a reason for hiding this comment

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

The component looks totally 🔥 (well except for the mobile header -- which will get fixed 😂 ) and it's hard to imagine how many CSS problems you had to solve to get this working! Personally I like how the Inventory variants are set up now -- agree its so much code in <AnimalInventory /> but I think each variant reads clearly. And they are definitely easy to consume, having tested them in the task readonly + complete 👍

Only thing which I thought needs a tweak is the useFilteredInventory logic (the other one is optional since I can add it on my PR).

@antsgar
Copy link
Collaborator

antsgar commented Nov 29, 2024

The refactor looks awesome, much better than before IMO! Excellent work 🔥 I'd take it one step further by letting the "variant" components own passing to BaseAnimalInventory the props that are specific to each variant and not common to all of them. I'm not sure if I'm explaining it clearly, so I pushed out an alternative branch showcasing this LF-4483-create-selected-animals-summary-component-2 (I haven't tested it thoroughly though so please do if you decide to move forward with that change)

@kathyavini
Copy link
Collaborator

kathyavini commented Nov 29, 2024

Sorry I think I missed something -- it might be what you referred to here

here is a google maps crash on timeout + expanding item

but I don't think so, because it is happening on the screens that don't include the expandable, and timeout doesn't seem to be required. Actually I'm not even sure what the error is because my console is only showing warnings but there is a full whitescreen on the location selecting step of tasks OTHER than movement, could you check if you see that?

(I was doing my custom tasks investigation when I ran into it, but I'm seeing this crash on all tasks except movement).

Screenshot 2024-11-29 at 11 29 52 AM

@Duncan-Brain
Copy link
Collaborator Author

Duncan-Brain commented Nov 29, 2024

@antsgar I merged your branch into mine -- seems good, thanks!

@kathyavini I was using logic for styles like it was className but doesnt work for style or classes obviously -- should be fixed in latest "merge commit" I got mixed up between branches again and committed to my local of Antos improvement.

…to LF-4483-create-selected-animals-summary-component
Copy link
Collaborator

@kathyavini kathyavini left a comment

Choose a reason for hiding this comment

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

I was using logic for styles like it was className but doesnt work for style or classes obviously

I actually got confused in the exact same way looking at the console from the crash! I saw the console warning related to the styling, but thought "that's not the reason for the crash; classnames can't crash" 😂 But I missed that it was a style object!

Looks great to me!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new translations New translations to be sent to CrowdIn are present
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants