hospital portal
This commit is contained in:
19
frontend/hospital-portal/src/components/hook-form/FormProvider.tsx
Executable file
19
frontend/hospital-portal/src/components/hook-form/FormProvider.tsx
Executable file
@@ -0,0 +1,19 @@
|
||||
import { ReactNode } from 'react';
|
||||
// form
|
||||
import { FormProvider as Form, UseFormReturn } from 'react-hook-form';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
type Props = {
|
||||
children: ReactNode;
|
||||
methods: UseFormReturn<any>;
|
||||
onSubmit?: VoidFunction;
|
||||
};
|
||||
|
||||
export default function FormProvider({ children, onSubmit, methods }: Props) {
|
||||
return (
|
||||
<Form {...methods}>
|
||||
<form onSubmit={onSubmit}>{children}</form>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
41
frontend/hospital-portal/src/components/hook-form/RHFAutocomplete.tsx
Executable file
41
frontend/hospital-portal/src/components/hook-form/RHFAutocomplete.tsx
Executable file
@@ -0,0 +1,41 @@
|
||||
import { Autocomplete, TextField, TextFieldProps } from '@mui/material';
|
||||
import { useState } from 'react';
|
||||
import { Controller, useFormContext } from 'react-hook-form';
|
||||
|
||||
interface IProps {
|
||||
options: any[];
|
||||
name: string;
|
||||
label?: string;
|
||||
}
|
||||
|
||||
export default function RHFAutocomplete({ name, options, label, ...other }: IProps & TextFieldProps) {
|
||||
const { control } = useFormContext();
|
||||
console.log(control)
|
||||
|
||||
const [value, setValue] = useState<string | null>(options[0]);
|
||||
const [inputValue, setInputValue] = useState('');
|
||||
|
||||
return (
|
||||
<Controller
|
||||
name={name}
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<Autocomplete
|
||||
{...field}
|
||||
options={options}
|
||||
value={value}
|
||||
onChange={(event: any, newValue: string | null) => {
|
||||
// console.log('fuck', newValue)
|
||||
setValue(newValue.id);
|
||||
}}
|
||||
inputValue={inputValue}
|
||||
onInputChange={(event, newInputValue) => {
|
||||
setInputValue(newInputValue);
|
||||
}}
|
||||
renderInput={(params) => <TextField {...params} label={label ?? name} />}
|
||||
{...other}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
115
frontend/hospital-portal/src/components/hook-form/RHFCheckbox.tsx
Executable file
115
frontend/hospital-portal/src/components/hook-form/RHFCheckbox.tsx
Executable file
@@ -0,0 +1,115 @@
|
||||
// form
|
||||
import { useFormContext, Controller } from 'react-hook-form';
|
||||
// @mui
|
||||
import { Checkbox, FormControlLabel, FormGroup, FormControlLabelProps } from '@mui/material';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
interface RHFCheckboxProps extends Omit<FormControlLabelProps, 'control'> {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export function RHFCheckbox({ name, ...other }: RHFCheckboxProps) {
|
||||
const { control } = useFormContext();
|
||||
|
||||
return (
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Controller
|
||||
name={name}
|
||||
control={control}
|
||||
render={({ field }) => <Checkbox {...field} checked={field.value} />}
|
||||
/>
|
||||
}
|
||||
{...other}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
interface RHFMultiCheckboxProps extends Omit<FormControlLabelProps, 'control' | 'label'> {
|
||||
name: string;
|
||||
options: string[];
|
||||
}
|
||||
|
||||
export function RHFMultiCheckbox({ name, options, ...other }: RHFMultiCheckboxProps) {
|
||||
const { control } = useFormContext();
|
||||
|
||||
return (
|
||||
<Controller
|
||||
name={name}
|
||||
control={control}
|
||||
render={({ field }) => {
|
||||
const onSelected = (option: string) =>
|
||||
field.value.includes(option)
|
||||
? field.value.filter((value: string) => value !== option)
|
||||
: [...field.value, option];
|
||||
|
||||
return (
|
||||
<FormGroup>
|
||||
{options.map((option) => (
|
||||
<FormControlLabel
|
||||
key={option}
|
||||
control={
|
||||
<Checkbox
|
||||
checked={field.value.includes(option)}
|
||||
onChange={() => field.onChange(onSelected(option))}
|
||||
/>
|
||||
}
|
||||
label={option}
|
||||
{...other}
|
||||
/>
|
||||
))}
|
||||
</FormGroup>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
interface optionsCustomInterface {
|
||||
value: string;
|
||||
label: string;
|
||||
}
|
||||
interface RHFCustomMultiCheckboxProps {
|
||||
name: string;
|
||||
options: optionsCustomInterface[];
|
||||
}
|
||||
|
||||
export function RHFCustomMultiCheckbox({ name, options, ...other }: RHFCustomMultiCheckboxProps) {
|
||||
const { control } = useFormContext();
|
||||
|
||||
return (
|
||||
<Controller
|
||||
name={name}
|
||||
control={control}
|
||||
render={({ field }) => {
|
||||
const onSelected = (option: optionsCustomInterface) =>
|
||||
field.value.includes(option.value)
|
||||
? field.value.filter((value: string) => value !== option.value)
|
||||
: [...field.value, option.value];
|
||||
|
||||
return (
|
||||
<FormGroup>
|
||||
{options.map((option, index) => (
|
||||
<FormControlLabel
|
||||
key={index}
|
||||
control={
|
||||
<Checkbox
|
||||
checked={field.value.includes(option.value)}
|
||||
onChange={() => field.onChange(onSelected(option))}
|
||||
/>
|
||||
}
|
||||
label={option.label}
|
||||
{...other}
|
||||
/>
|
||||
))}
|
||||
</FormGroup>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
65
frontend/hospital-portal/src/components/hook-form/RHFDatepicker.tsx
Executable file
65
frontend/hospital-portal/src/components/hook-form/RHFDatepicker.tsx
Executable file
@@ -0,0 +1,65 @@
|
||||
// form
|
||||
import { useFormContext, Controller } from 'react-hook-form';
|
||||
import * as React from 'react';
|
||||
|
||||
// @mui
|
||||
import { IconButton, TextField, TextFieldProps } from '@mui/material';
|
||||
import { LocalizationProvider, MobileDatePicker } from '@mui/x-date-pickers';
|
||||
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
|
||||
|
||||
import { DesktopDatePicker } from '@mui/x-date-pickers/DesktopDatePicker';
|
||||
|
||||
import InputAdornment from '@mui/material/InputAdornment';
|
||||
import EventIcon from '@mui/icons-material/Event';
|
||||
import { fPostFormat } from '../../utils/formatTime';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
interface IProps {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export default function RHFDatepicker({ name, ...other }: IProps & TextFieldProps) {
|
||||
const { control } = useFormContext();
|
||||
|
||||
return (
|
||||
<Controller
|
||||
name={name}
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<LocalizationProvider dateAdapter={AdapterDateFns}>
|
||||
<MobileDatePicker
|
||||
inputFormat="yyyy-MM-dd"
|
||||
value={field.value}
|
||||
onChange={(value) => {
|
||||
field.onChange(fPostFormat(value));
|
||||
}}
|
||||
renderInput={(field) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fullWidth
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<EventIcon />
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
error={!!error}
|
||||
helperText={error?.message}
|
||||
{...other}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{/* <DesktopDatePicker
|
||||
value={field.value}
|
||||
onChange={(value) => {
|
||||
field.onChange(fPostFormat(value));
|
||||
}}
|
||||
renderInput={(params) => <TextField {...params} fullWidth />}
|
||||
/> */}
|
||||
</LocalizationProvider>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
38
frontend/hospital-portal/src/components/hook-form/RHFEditor.tsx
Executable file
38
frontend/hospital-portal/src/components/hook-form/RHFEditor.tsx
Executable file
@@ -0,0 +1,38 @@
|
||||
// form
|
||||
import { useFormContext, Controller } from 'react-hook-form';
|
||||
// @mui
|
||||
import { FormHelperText } from '@mui/material';
|
||||
//
|
||||
import Editor, { Props as EditorProps } from '../editor';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
interface Props extends EditorProps {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export default function RHFEditor({ name, ...other }: Props) {
|
||||
const { control } = useFormContext();
|
||||
|
||||
return (
|
||||
<Controller
|
||||
name={name}
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<Editor
|
||||
id={name}
|
||||
value={field.value}
|
||||
onChange={field.onChange}
|
||||
error={!!error}
|
||||
simple={true}
|
||||
helperText={
|
||||
<FormHelperText error sx={{ px: 2, textTransform: 'capitalize' }}>
|
||||
{error?.message}
|
||||
</FormHelperText>
|
||||
}
|
||||
{...other}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
54
frontend/hospital-portal/src/components/hook-form/RHFRadioGroup.tsx
Executable file
54
frontend/hospital-portal/src/components/hook-form/RHFRadioGroup.tsx
Executable file
@@ -0,0 +1,54 @@
|
||||
// form
|
||||
import { useFormContext, Controller } from 'react-hook-form';
|
||||
// @mui
|
||||
import {
|
||||
Radio,
|
||||
RadioGroup,
|
||||
FormHelperText,
|
||||
RadioGroupProps,
|
||||
FormControlLabel,
|
||||
} from '@mui/material';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
interface IProps {
|
||||
name: string;
|
||||
options: string[];
|
||||
getOptionLabel?: string[];
|
||||
}
|
||||
|
||||
export default function RHFRadioGroup({
|
||||
name,
|
||||
options,
|
||||
getOptionLabel,
|
||||
...other
|
||||
}: IProps & RadioGroupProps) {
|
||||
const { control } = useFormContext();
|
||||
|
||||
return (
|
||||
<Controller
|
||||
name={name}
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<div>
|
||||
<RadioGroup {...field} row {...other}>
|
||||
{options.map((option, index) => (
|
||||
<FormControlLabel
|
||||
key={option}
|
||||
value={option}
|
||||
control={<Radio />}
|
||||
label={getOptionLabel?.length ? getOptionLabel[index] : option}
|
||||
/>
|
||||
))}
|
||||
</RadioGroup>
|
||||
|
||||
{!!error && (
|
||||
<FormHelperText error sx={{ px: 2 }}>
|
||||
{error.message}
|
||||
</FormHelperText>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
35
frontend/hospital-portal/src/components/hook-form/RHFSelect.tsx
Executable file
35
frontend/hospital-portal/src/components/hook-form/RHFSelect.tsx
Executable file
@@ -0,0 +1,35 @@
|
||||
// form
|
||||
import { useFormContext, Controller } from 'react-hook-form';
|
||||
// @mui
|
||||
import { TextField, TextFieldProps } from '@mui/material';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
interface IProps {
|
||||
name: string;
|
||||
children: any;
|
||||
}
|
||||
|
||||
export default function RHFSelect({ name, children, ...other }: IProps & TextFieldProps) {
|
||||
const { control } = useFormContext();
|
||||
|
||||
return (
|
||||
<Controller
|
||||
name={name}
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
select
|
||||
fullWidth
|
||||
SelectProps={{ native: true }}
|
||||
error={!!error}
|
||||
helperText={error?.message}
|
||||
{...other}
|
||||
>
|
||||
{children}
|
||||
</TextField>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
56
frontend/hospital-portal/src/components/hook-form/RHFSwitch.tsx
Executable file
56
frontend/hospital-portal/src/components/hook-form/RHFSwitch.tsx
Executable file
@@ -0,0 +1,56 @@
|
||||
// form
|
||||
import { useFormContext, Controller } from 'react-hook-form';
|
||||
// @mui
|
||||
import { Switch, FormControlLabel, FormControlLabelProps } from '@mui/material';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
type IProps = Omit<FormControlLabelProps, 'control'>;
|
||||
|
||||
interface Props extends IProps {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export default function RHFSwitch({ name, ...other }: Props) {
|
||||
const { control } = useFormContext();
|
||||
|
||||
return (
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Controller
|
||||
name={name}
|
||||
control={control}
|
||||
render={({ field }) => <Switch {...field} checked={field.value} />}
|
||||
/>
|
||||
}
|
||||
{...other}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// interface Props extends IProps {
|
||||
// valueTrue: any,
|
||||
// valueFalse: any,
|
||||
// }
|
||||
|
||||
// export function RHFSwitchEnum({ name, valueTrue, valueFalse, ...other}: Props) {
|
||||
// const { control } = useFormContext();
|
||||
// const [isChecked, setIsChecked] = useState(valueTrue === field.value);
|
||||
// useEffect(() => {
|
||||
// // setIsChecked()
|
||||
// }, [])
|
||||
|
||||
// return (
|
||||
// <FormControlLabel
|
||||
// control={
|
||||
// <Controller
|
||||
// name={name}
|
||||
// control={control}
|
||||
// render={({ field }) => <Switch {...field} checked={field.value} />}
|
||||
// />
|
||||
// }
|
||||
// {...other}
|
||||
// />
|
||||
// );
|
||||
// }
|
||||
24
frontend/hospital-portal/src/components/hook-form/RHFTextField.tsx
Executable file
24
frontend/hospital-portal/src/components/hook-form/RHFTextField.tsx
Executable file
@@ -0,0 +1,24 @@
|
||||
// form
|
||||
import { useFormContext, Controller } from 'react-hook-form';
|
||||
// @mui
|
||||
import { TextField, TextFieldProps } from '@mui/material';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
interface IProps {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export default function RHFTextField({ name, ...other }: IProps & TextFieldProps) {
|
||||
const { control } = useFormContext();
|
||||
|
||||
return (
|
||||
<Controller
|
||||
name={name}
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<TextField {...field} fullWidth error={!!error} helperText={error?.message} {...other} />
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
110
frontend/hospital-portal/src/components/hook-form/RHFUpload.tsx
Executable file
110
frontend/hospital-portal/src/components/hook-form/RHFUpload.tsx
Executable file
@@ -0,0 +1,110 @@
|
||||
// form
|
||||
import { useFormContext, Controller } from 'react-hook-form';
|
||||
// @mui
|
||||
import { FormHelperText } from '@mui/material';
|
||||
// type
|
||||
import {
|
||||
UploadAvatar,
|
||||
UploadMultiFile,
|
||||
UploadSingleFile,
|
||||
UploadProps,
|
||||
UploadMultiFileProps,
|
||||
} from '../upload';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
interface Props extends Omit<UploadProps, 'file'> {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export function RHFUploadAvatar({ name, ...other }: Props) {
|
||||
const { control } = useFormContext();
|
||||
|
||||
return (
|
||||
<Controller
|
||||
name={name}
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
const checkError = !!error && !field.value;
|
||||
return (
|
||||
<div>
|
||||
<UploadAvatar error={checkError} {...other} file={field.value} />
|
||||
{checkError && (
|
||||
<FormHelperText error sx={{ px: 2, textAlign: 'center' }}>
|
||||
{error.message}
|
||||
</FormHelperText>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export function RHFUploadSingleFile({ name, ...other }: Props) {
|
||||
const { control } = useFormContext();
|
||||
|
||||
return (
|
||||
<Controller
|
||||
name={name}
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
const checkError = !!error && !field.value;
|
||||
|
||||
return (
|
||||
<UploadSingleFile
|
||||
accept="image/*"
|
||||
file={field.value}
|
||||
error={checkError}
|
||||
helperText={
|
||||
checkError && (
|
||||
<FormHelperText error sx={{ px: 2 }}>
|
||||
{error.message}
|
||||
</FormHelperText>
|
||||
)
|
||||
}
|
||||
{...other}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
interface RHFUploadMultiFileProps extends Omit<UploadMultiFileProps, 'files'> {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export function RHFUploadMultiFile({ name, ...other }: RHFUploadMultiFileProps) {
|
||||
const { control } = useFormContext();
|
||||
|
||||
return (
|
||||
<Controller
|
||||
name={name}
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
const checkError = !!error && field.value?.length === 0;
|
||||
|
||||
return (
|
||||
<UploadMultiFile
|
||||
accept="image/*"
|
||||
files={field.value}
|
||||
error={checkError}
|
||||
helperText={
|
||||
checkError && (
|
||||
<FormHelperText error sx={{ px: 2 }}>
|
||||
{error?.message}
|
||||
</FormHelperText>
|
||||
)
|
||||
}
|
||||
{...other}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
11
frontend/hospital-portal/src/components/hook-form/index.ts
Executable file
11
frontend/hospital-portal/src/components/hook-form/index.ts
Executable file
@@ -0,0 +1,11 @@
|
||||
export * from './RHFCheckbox';
|
||||
export * from './RHFUpload';
|
||||
|
||||
export { default as FormProvider } from './FormProvider';
|
||||
|
||||
export { default as RHFSwitch } from './RHFSwitch';
|
||||
export { default as RHFSelect } from './RHFSelect';
|
||||
export { default as RHFEditor } from './RHFEditor';
|
||||
export { default as RHFTextField } from './RHFTextField';
|
||||
export { default as RHFRadioGroup } from './RHFRadioGroup';
|
||||
export { default as RHFDatepicker } from './RHFDatepicker';
|
||||
Reference in New Issue
Block a user