-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5f82b60
commit 0e5c7ab
Showing
7 changed files
with
323 additions
and
3 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains 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 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,59 @@ | ||
import React from 'react'; | ||
import { useFormikContext, FormikValues } from 'formik'; | ||
import { Label, HelperText } from 'flowbite-react'; | ||
|
||
interface FieldProps { | ||
name: string; | ||
label?: string; | ||
readonly?: boolean; | ||
children: React.ReactElement; | ||
} | ||
|
||
const Field: React.FC<FieldProps> = ({ name, label, readonly, children }) => { | ||
const { errors, touched, values, setFieldValue, setFieldTouched }: FormikValues = useFormikContext(); | ||
|
||
const isError: boolean = !!errors[name] && !!touched[name]; | ||
|
||
// Enforce a single child | ||
const child = React.Children.only(children); | ||
|
||
// Styles for the read-only value container | ||
const readOnlyValueStyles = "py-2 px-4 bg-gray-100 text-gray-800 rounded border border-gray-300"; | ||
|
||
if (readonly) { | ||
return ( | ||
<div className="mb-4"> | ||
{label && <Label htmlFor={name}>{label}</Label>} | ||
<div id={name} className={readOnlyValueStyles}> | ||
{values[name] || 'N/A'} {/* Display 'N/A' if the value is falsy */} | ||
</div> | ||
{isError && <HelperText>{errors[name]}</HelperText>} | ||
</div> | ||
); | ||
} | ||
|
||
// Enhance the single child component with additional Formik-related props | ||
const enhancedChild = React.cloneElement(child, { | ||
id: name, | ||
name, | ||
onChange: (e: React.ChangeEvent<any>) => { | ||
child.props.onChange?.(e); | ||
setFieldValue(name, e.target.value); | ||
}, | ||
onBlur: (e: React.FocusEvent<any>) => { | ||
child.props.onBlur?.(e); | ||
setFieldTouched(name, true); | ||
}, | ||
color: isError ? 'failure' : 'gray', | ||
}); | ||
|
||
return ( | ||
<div className="mb-4"> | ||
{label && <Label htmlFor={name}>{label}</Label>} | ||
{enhancedChild} | ||
{isError && <HelperText>{errors[name]}</HelperText>} | ||
</div> | ||
); | ||
}; | ||
|
||
export default Field; |
This file contains 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,49 @@ | ||
import React from 'react'; | ||
import { FieldArray, useFormikContext, FormikValues } from 'formik'; | ||
import { Button } from 'flowbite-react'; | ||
|
||
interface RepeaterProps { | ||
name: string; | ||
component: React.ReactElement; | ||
maxNumber?: number; | ||
minNumber?: number; | ||
} | ||
|
||
const Repeater: React.FC<RepeaterProps> = ({ name, component, maxNumber = 5, minNumber = 1 }) => { | ||
const { values }: FormikValues = useFormikContext(); | ||
const groups = values[name] || []; | ||
|
||
return ( | ||
<FieldArray | ||
name={name} | ||
render={(arrayHelpers) => ( | ||
<div> | ||
{groups.map((group: any, index: number) => ( | ||
<div key={index} className="mb-4 flex items-center"> | ||
{/* Clone the component for each group and pass in the adjusted name prop */} | ||
{React.cloneElement(component, { name: `${name}[${index}]` })} | ||
|
||
{/* Remove button for each group */} | ||
<Button | ||
color="failure" | ||
onClick={() => arrayHelpers.remove(index)} | ||
disabled={groups.length <= minNumber} // Disable if minNumber reached | ||
> | ||
Remove | ||
</Button> | ||
</div> | ||
))} | ||
|
||
{/* Add button - shown if maxNumber hasn't been reached */} | ||
{groups.length < maxNumber && ( | ||
<Button onClick={() => arrayHelpers.push({})}> | ||
Add | ||
</Button> | ||
)} | ||
</div> | ||
)} | ||
/> | ||
); | ||
}; | ||
|
||
export default Repeater; |
This file contains 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,25 @@ | ||
import React from 'react'; | ||
import { TextInput } from 'flowbite-react'; | ||
import Field from './Field'; // Make sure the import path is correct | ||
|
||
interface AddressGroupProps { | ||
name: string; // Base name for the group, used to construct field names | ||
} | ||
|
||
const AddressGroup: React.FC<AddressGroupProps> = ({ name }) => { | ||
return ( | ||
<div className="space-y-2"> | ||
<Field name={`${name}.street`} label="Street"> | ||
<TextInput placeholder="123 Main St" /> | ||
</Field> | ||
<Field name={`${name}.city`} label="City"> | ||
<TextInput placeholder="Anytown" /> | ||
</Field> | ||
<Field name={`${name}.zipCode`} label="Zip Code"> | ||
<TextInput placeholder="12345" /> | ||
</Field> | ||
</div> | ||
); | ||
}; | ||
|
||
export default AddressGroup; |
Oops, something went wrong.