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

Implemented Add new Institution scenario #52

Merged
merged 1 commit into from
Feb 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions components/InstitutionContainer/InstitutionContainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { FormHeader } from "~/FormHeader";
// TODO Fix keyboard openLayout
// TODO Update stories to suit use-form
export function InstitutionContainer({ institutionName, isInstitutionOpen }) {
// console.log("InstitutionContainer Rendered");
const { getValues, handlers: formHandlers } = useFormContext();

return (
Expand Down Expand Up @@ -109,6 +110,7 @@ const ExpandedHeader = () => {

const AssetsList = ({ isInstitutionOpen, institutionName }) => {
const arrayName = `${institutionName}.assets`;
// console.log("AssetsList rendered");
const {
fields: assets,
remove,
Expand All @@ -118,12 +120,8 @@ const AssetsList = ({ isInstitutionOpen, institutionName }) => {
});
const {
resetField,
getValues,
formState: { isDirty, dirtyFields, defaultValues },
formState: { dirtyFields, defaultValues },
} = useFormContext();
// const { fields: institutionFields } = useFieldArray({
// name: "institutions.0.assets.0",
// });

return (
<VStack
Expand Down
17 changes: 11 additions & 6 deletions components/InstitutionTab/InstitutionTab.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import classes from "./InstitutionTab.module.css";

export const InstitutionTab = forwardRef(
({ isDeleted = false, institutionName, ...props }, ref) => {
const { formState, getValues, control } = useFormContext();
const { formState, getValues, control, institutionsFieldArray } =
useFormContext();
const institutionFields =
institutionsFieldArray.fields[getInstitutionIndex(institutionName)];
const institutionDefaultValues =
formState.defaultValues.institutions[
getInstitutionIndex(institutionName)
Expand All @@ -16,11 +19,13 @@ export const InstitutionTab = forwardRef(
const isChanged =
JSON.stringify(institutionDefaultValues) !==
JSON.stringify(institutionCurrentValues);
const state = isChanged ? "updated" : null;
const name = useWatch({
control,
name: `${institutionName}.name`,
});
const isNew = institutionFields.name === "";
const state = isNew ? "new" : isChanged ? "updated" : null;
const name =
useWatch({
control,
name: `${institutionName}.name`,
}) || "New Institution";

return (
<Tab
Expand Down
17 changes: 8 additions & 9 deletions components/InstitutionTab/docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@
onRestore

//Context
+ fields from useFieldArray()
+ getValue
+ getFieldState
+ useFormContext()
```

### Listeners
Expand All @@ -27,8 +25,8 @@ stateDiagram-v2
direction LR

[*] --> existing
existing --> updated : prop changed
updated --> existing : prop changed
existing --> updated : defaultValues.institution[id] != getvalues(institution.id)
updated --> existing : defaultValues.institution[id] == getvalues(institution.id)
updated --> deleted : prop changed
existing --> deleted : prop changed
deleted --> updated : BUTTON_PRESS <br/> Do / setState
Expand All @@ -44,15 +42,16 @@ I want to minimize states number. By somehow derive from existing use-hook-form
Probably can be known via comparison between institution value and defaultValues(which are retrieved)
For this scenario probably the simplest reliable way is to generate unique ID for institution and store it in db.

*defaultValues* can be retrieved from `fields` https://react-hook-form.com/docs/usefieldarray#:~:text=Description-,fields,-object%20%26%20%7B%20id
Field values can be retrieved from `fields` https://react-hook-form.com/docs/usefieldarray#:~:text=Description-,fields,-object%20%26%20%7B%20id

if `institutions.ID.name` from `fields` === '' than institution is new

#### Deleted state
can be set by disabling institution fields
can be set by disabling institution fields??

#### Updated state
can be retrived from `isDirty`
~~can be retrived from `isDirty`~~
Retrieved by comparison between `defaulValues.institutions[id]` and current values of `institutions[id]`

### Text prop
`text`(`InstitutionName`) can be retrieved by `getValues()`, **but there is problem of retreiving value from disabled inputs**(which i planned to use for deleted state) https://github.com/orgs/react-hook-form/discussions/11533
`text`(`InstitutionName`) retrieved by `useWatch()`, **but there is problem of retreiving value from disabled inputs**(which i planned to use for deleted state) https://github.com/orgs/react-hook-form/discussions/11533
34 changes: 17 additions & 17 deletions components/InstitutionsList/InstitutionsList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,45 +5,45 @@ import { InstitutionContainer } from "../InstitutionContainer";
import { Tabs, TabPanels, TabPanel } from "@chakra-ui/react";
import { useVisualViewportSize } from "../../app/hooks";
import classes from "./InstitutionsList.module.css";
import { useFieldArray } from "react-hook-form";
import { useFormContext } from "react-hook-form";

function InstitutionsList({ simulateKeyboard = false, isIntitutionOpen }) {
function InstitutionsList({
simulateKeyboard = false,
isInstitutionOpen,
selectedInstitution,
}) {
const { height } = useVisualViewportSize();
const isKeyboardOpened = simulateKeyboard || height < 650;

const arrayName = `institutions`;
const { fields: institutions, remove } = useFieldArray({
name: arrayName,
});
const {
institutionsFieldArray: { fields: institutions },
handlers: { handleInstitutionCreate, handleTabsChange },
} = useFormContext();

return (
<Tabs
flexGrow={1}
minH="200px"
// className={classes.institutionsList}
index={selectedInstitution}
onChange={handleTabsChange}
h="100%"
// display="flex"
// flexDir="column"
variant="grid"
padding={isIntitutionOpen || 2}
padding={isInstitutionOpen || 2}
>
<TabPanels flexGrow={1} flexShrink={1} minH="200px">
{institutions.map((institution, index) => (
<TabPanel p={0} key={institution.id} h="100%">
<InstitutionContainer
institutionName={`institutions.${index}`}
isInstitutionOpen={isIntitutionOpen}
// institutionId={index}
// isExpanded={isExpanded}
// institution={institution}
isInstitutionOpen={isInstitutionOpen}
/>
</TabPanel>
))}
</TabPanels>
{isIntitutionOpen || (
{isInstitutionOpen || (
<InstitutionsTabsList
simulateKeyboard={isKeyboardOpened}
institutions={institutions}
institutionsArray={institutions}
onCreateInstitution={handleInstitutionCreate}
/>
)}
</Tabs>
Expand Down
33 changes: 33 additions & 0 deletions components/InstitutionsList/docs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
## InstitutionsList
### Props
```diff
// Props
- isCompact (bool)
- isOpenedInstitution (bool)
- institutions (array)
+ isInstitutionOpen (bool)

// Context
+ selectedInstitution (int)
+ { institutionsFieldArray: {fields: institutions}, handlers } =
+ useFormContext();
```

### States
- selectedInstitutionId (number)

```mermaid
---
title: InstitutionsList
---
stateDiagram-v2
direction LR

[*] --> compact
[*] --> expanded
compact --> openedInstitution : BUTTON_PRESS do / setIsOpenInstitution
compact --> expanded : window.visualViewport.height > 650px

expanded --> compact : window.visualViewport.height < 650px
openedInstitution --> compact : BUTTON_PRESS do / setIsOpenInstitution
```
75 changes: 38 additions & 37 deletions components/InstitutionsTabsList/InstitutionsTabsList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,19 @@
// TODO fix animation framer https://github.com/skorphil/nextjs-form/issues/25

import { InstitutionTab } from "../InstitutionTab";
import {
Tabs,
TabList,
Heading,
Button,
Box,
IconButton,
} from "@chakra-ui/react";
import { TabList, Heading, Button, Box, IconButton } from "@chakra-ui/react";

import classes from "./InstitutionsTabsList.module.css";
import { CgMathPlus } from "react-icons/cg";
import { useVisualViewportSize } from "../../app/hooks";
import { motion } from "framer-motion";
import { useFormContext } from "react-hook-form";

export function InstitutionsTabsList({
institutions,
simulateKeyboard = false,
}) {
export function InstitutionsTabsList({ simulateKeyboard = false }) {
const {
institutionsFieldArray: { fields: institutions },
handlers: { handleInstitutionCreate },
} = useFormContext();
const { height } = useVisualViewportSize();
const isKeyboardOpened =
simulateKeyboard || (window.innerHeight - height > 200 ? true : false);
Expand All @@ -38,39 +33,45 @@ export function InstitutionsTabsList({
key="tablist"
className={`${classes.grid} ${isKeyboardOpened ? classes.collapsed : classes.expanded}`}
>
{institutions.map((institution, id) => (
{institutions.map((institution, index) => (
<InstitutionTab
// transition="2s linear"
// as={motion.div}
// layout="position"
width={isKeyboardOpened && "180px"}
institutionName={`institutions.${id}`}
key={`institutionTab-${id}`}
name={institution.name}
state="new"
institutionName={`institutions.${index}`}
key={institution.id}
/>
))}
{isKeyboardOpened
? newInstitutionButtonCollapsed
: newInstitutionButtonExpanded}
{isKeyboardOpened ? (
<NewInstitutionButtonCollapsed
onCreateInstitution={handleInstitutionCreate}
/>
) : (
<NewInstitutionButtonExpanded
onCreateInstitution={handleInstitutionCreate}
/>
)}
</TabList>
</Box>
</Box>
);
}

const newInstitutionButtonExpanded = (
<Button variant="outline">
<Box as="span" overflow="hidden">
Add institution
</Box>
</Button>
);
function NewInstitutionButtonExpanded({ onCreateInstitution }) {
return (
<Button variant="outline" onClick={onCreateInstitution}>
<Box as="span" overflow="hidden">
Add institution
</Box>
</Button>
);
}

const newInstitutionButtonCollapsed = (
<IconButton
variant="outline"
aria-label="Add institution"
icon={<CgMathPlus />}
/>
);
function NewInstitutionButtonCollapsed({ onCreateInstitution }) {
return (
<IconButton
onClick={onCreateInstitution}
variant="outline"
aria-label="Add institution"
icon={<CgMathPlus />}
/>
);
}
33 changes: 33 additions & 0 deletions components/InstitutionsTabsList/docs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
## InstitutionsTabsList
### Props
```diff
// Props
- isCompact (bool) // renamed to isKeyboardOpened
- Institutions (array) // get from context
- onCreate (function) // get from context
- selectedInstitutionId (number) // not needed. Used by InstitutionsList
+ isKeyboardOpened

// Context
+ {
+ institutionsFieldArray: { fields: institutions },
+ handlers: { handleInstitutionCreate },
+ } = useFormContext()
```

### Listeners
- restoreButton click

### States
```mermaid
---
title: InstitutionsTabsList
---
stateDiagram-v2
direction LR

[*] --> expanded
[*] --> compact
expanded --> compact : prop + isKeyboardOpened changed
compact --> compact : prop + isKeyboardOpened changed
```
Loading