2024-07-01 12:33:55 +05:30
|
|
|
import {
|
|
|
|
|
FormControl,
|
|
|
|
|
FormLabel,
|
|
|
|
|
Input,
|
|
|
|
|
Textarea,
|
|
|
|
|
Select,
|
|
|
|
|
Checkbox,
|
|
|
|
|
RadioGroup,
|
|
|
|
|
Radio,
|
|
|
|
|
Stack,
|
|
|
|
|
Box,
|
|
|
|
|
Heading,
|
|
|
|
|
FormHelperText,
|
|
|
|
|
Kbd,
|
|
|
|
|
Image,
|
|
|
|
|
Text,
|
|
|
|
|
} from "@chakra-ui/react";
|
|
|
|
|
import { Controller } from "react-hook-form";
|
|
|
|
|
import { TiWarning } from "react-icons/ti";
|
|
|
|
|
import { motion } from "framer-motion";
|
|
|
|
|
import { AddIcon, CloseIcon } from "@chakra-ui/icons";
|
2024-06-24 12:08:21 +05:30
|
|
|
|
|
|
|
|
const FormField = ({
|
2024-06-27 11:50:59 +05:30
|
|
|
label,
|
|
|
|
|
control,
|
|
|
|
|
name,
|
2024-07-01 12:33:55 +05:30
|
|
|
id,
|
2024-06-27 11:50:59 +05:30
|
|
|
type = "text",
|
|
|
|
|
options = [],
|
|
|
|
|
errors,
|
|
|
|
|
isRequired,
|
|
|
|
|
rules,
|
|
|
|
|
arabic,
|
|
|
|
|
placeHolder,
|
|
|
|
|
helperText,
|
|
|
|
|
multiple,
|
|
|
|
|
handleImageChange,
|
2024-07-01 12:33:55 +05:30
|
|
|
selectedImageData,
|
|
|
|
|
setSelectedImageData,
|
|
|
|
|
removeImage,
|
|
|
|
|
imageData ,
|
2024-06-27 11:50:59 +05:30
|
|
|
...props
|
|
|
|
|
}) => (
|
2024-07-01 12:33:55 +05:30
|
|
|
<FormControl
|
|
|
|
|
w={"49%"}
|
|
|
|
|
isInvalid={errors[name]}
|
|
|
|
|
isRequired={isRequired}
|
|
|
|
|
className="mb-3"
|
|
|
|
|
>
|
2024-07-03 12:13:09 +05:30
|
|
|
<FormLabel textAlign={arabic ? "right" : "left"} fontSize={"sm"} fontWeight={'400'}>
|
2024-07-01 12:33:55 +05:30
|
|
|
{label}
|
|
|
|
|
</FormLabel>
|
2024-06-27 11:50:59 +05:30
|
|
|
<Controller
|
|
|
|
|
control={control}
|
|
|
|
|
name={name}
|
|
|
|
|
defaultValue=""
|
|
|
|
|
rules={rules}
|
|
|
|
|
render={({ field }) => {
|
2024-07-01 12:33:55 +05:30
|
|
|
if (type === "select") {
|
2024-06-27 11:50:59 +05:30
|
|
|
return (
|
|
|
|
|
<Select
|
|
|
|
|
focusBorderColor="forestGreen.300"
|
|
|
|
|
size={"sm"}
|
|
|
|
|
{...field}
|
|
|
|
|
{...props}
|
2024-07-01 12:33:55 +05:30
|
|
|
cursor={"pointer"}
|
|
|
|
|
placeholder={placeHolder ? placeHolder : label}
|
2024-06-27 11:50:59 +05:30
|
|
|
textAlign={arabic ? "right" : "left"}
|
2024-07-03 12:13:09 +05:30
|
|
|
_placeholder={{fontSize:'xs'}}
|
|
|
|
|
borderRadius={'4px'}
|
2024-06-27 11:50:59 +05:30
|
|
|
>
|
|
|
|
|
{options.map((option, index) => (
|
2024-07-01 12:33:55 +05:30
|
|
|
<option key={index} value={option.value}>
|
|
|
|
|
{option.label}
|
|
|
|
|
</option>
|
2024-06-27 11:50:59 +05:30
|
|
|
))}
|
|
|
|
|
</Select>
|
|
|
|
|
);
|
2024-07-01 12:33:55 +05:30
|
|
|
} else if (type === "textarea") {
|
2024-06-27 11:50:59 +05:30
|
|
|
return (
|
|
|
|
|
<Textarea
|
|
|
|
|
focusBorderColor="forestGreen.400"
|
|
|
|
|
size={"sm"}
|
|
|
|
|
{...field}
|
|
|
|
|
{...props}
|
2024-07-01 12:33:55 +05:30
|
|
|
placeholder={placeHolder ? placeHolder : label}
|
2024-06-27 11:50:59 +05:30
|
|
|
textAlign={arabic ? "right" : "left"}
|
2024-07-03 12:13:09 +05:30
|
|
|
_placeholder={{fontSize:'xs'}}
|
|
|
|
|
borderRadius={'4px'}
|
|
|
|
|
resize={'none'}
|
2024-06-27 11:50:59 +05:30
|
|
|
/>
|
|
|
|
|
);
|
2024-07-01 12:33:55 +05:30
|
|
|
} else if (type === "checkbox") {
|
2024-06-27 11:50:59 +05:30
|
|
|
return (
|
|
|
|
|
<Checkbox
|
|
|
|
|
size={"sm"}
|
|
|
|
|
{...field}
|
|
|
|
|
{...props}
|
|
|
|
|
textAlign={arabic ? "right" : "left"}
|
|
|
|
|
>
|
|
|
|
|
{label}
|
|
|
|
|
</Checkbox>
|
|
|
|
|
);
|
2024-07-01 12:33:55 +05:30
|
|
|
} else if (type === "radio") {
|
2024-06-27 11:50:59 +05:30
|
|
|
return (
|
|
|
|
|
<RadioGroup {...field} {...props}>
|
|
|
|
|
<Stack direction="row">
|
|
|
|
|
{options.map((option, index) => (
|
|
|
|
|
<Radio key={index} value={option.value}>
|
|
|
|
|
{option.label}
|
|
|
|
|
</Radio>
|
|
|
|
|
))}
|
|
|
|
|
</Stack>
|
|
|
|
|
</RadioGroup>
|
|
|
|
|
);
|
2024-07-01 12:33:55 +05:30
|
|
|
} else if (type === "file") {
|
2024-06-27 11:50:59 +05:30
|
|
|
return (
|
2024-07-01 12:33:55 +05:30
|
|
|
<>
|
|
|
|
|
<Box
|
|
|
|
|
borderColor="gray.300"
|
|
|
|
|
borderStyle="dashed"
|
|
|
|
|
borderWidth="2px"
|
|
|
|
|
rounded="md"
|
|
|
|
|
shadow="sm"
|
|
|
|
|
role="group"
|
|
|
|
|
transition="all 150ms ease-in-out"
|
|
|
|
|
_hover={{
|
|
|
|
|
shadow: "md",
|
|
|
|
|
}}
|
|
|
|
|
as={motion.div}
|
|
|
|
|
initial="rest"
|
|
|
|
|
animate="rest"
|
|
|
|
|
whileHover="hover"
|
|
|
|
|
height={"105px"}
|
|
|
|
|
className="pointer"
|
|
|
|
|
>
|
|
|
|
|
<Box position="relative" height="100%" width="100%">
|
|
|
|
|
<Box
|
|
|
|
|
position="absolute"
|
|
|
|
|
top="0"
|
|
|
|
|
left="0"
|
2024-06-27 11:50:59 +05:30
|
|
|
height="100%"
|
|
|
|
|
width="100%"
|
|
|
|
|
display="flex"
|
2024-07-01 12:33:55 +05:30
|
|
|
flexDirection="column"
|
2024-06-27 11:50:59 +05:30
|
|
|
>
|
2024-07-01 12:33:55 +05:30
|
|
|
<Stack
|
|
|
|
|
height="100%"
|
|
|
|
|
width="100%"
|
|
|
|
|
display="flex"
|
|
|
|
|
alignItems="center"
|
|
|
|
|
justify="center"
|
2024-06-27 11:50:59 +05:30
|
|
|
>
|
|
|
|
|
<span
|
2024-07-01 12:33:55 +05:30
|
|
|
className="d-flex flex-column align-items-center pointer"
|
|
|
|
|
spacing="1"
|
2024-06-27 11:50:59 +05:30
|
|
|
>
|
2024-07-01 12:33:55 +05:30
|
|
|
<Heading
|
|
|
|
|
fontSize="lg"
|
|
|
|
|
color="gray.700"
|
|
|
|
|
fontWeight="bold"
|
|
|
|
|
cursor={"pointer"}
|
|
|
|
|
>
|
|
|
|
|
Drop images here
|
|
|
|
|
</Heading>
|
|
|
|
|
<span
|
|
|
|
|
fontWeight="light"
|
|
|
|
|
className="web-text-large text-secondary text-center pointer"
|
|
|
|
|
>
|
|
|
|
|
or click to upload
|
|
|
|
|
</span>
|
2024-06-27 11:50:59 +05:30
|
|
|
</span>
|
2024-07-01 12:33:55 +05:30
|
|
|
</Stack>
|
|
|
|
|
</Box>
|
|
|
|
|
<Input
|
|
|
|
|
{...field}
|
|
|
|
|
{...props}
|
|
|
|
|
type="file"
|
|
|
|
|
height="100%"
|
|
|
|
|
width="100%"
|
|
|
|
|
position="absolute"
|
|
|
|
|
top="0"
|
|
|
|
|
left="0"
|
|
|
|
|
opacity="0"
|
|
|
|
|
aria-hidden="true"
|
|
|
|
|
accept="image/*"
|
|
|
|
|
onChange={(e) => {
|
|
|
|
|
field.onChange(e);
|
|
|
|
|
handleImageChange(e);
|
|
|
|
|
}}
|
|
|
|
|
onDrop={(e) => {
|
|
|
|
|
field.onChange(e);
|
|
|
|
|
handleImageChange(e);
|
|
|
|
|
}}
|
|
|
|
|
/>
|
2024-06-27 11:50:59 +05:30
|
|
|
</Box>
|
|
|
|
|
</Box>
|
2024-07-01 12:33:55 +05:30
|
|
|
</>
|
2024-06-27 11:50:59 +05:30
|
|
|
);
|
2024-07-01 12:33:55 +05:30
|
|
|
} else if (type === "fileNormal") {
|
2024-06-27 11:50:59 +05:30
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<Input
|
2024-07-01 12:33:55 +05:30
|
|
|
id={id}
|
2024-06-27 11:50:59 +05:30
|
|
|
{...field}
|
|
|
|
|
{...props}
|
|
|
|
|
multiple={multiple} // Support for multiple file uploads
|
|
|
|
|
accept="image/*"
|
|
|
|
|
type="file"
|
|
|
|
|
className="web-text-medium form-control rounded-1"
|
|
|
|
|
size="sm"
|
|
|
|
|
onChange={(e) => {
|
|
|
|
|
field.onChange(e);
|
|
|
|
|
handleImageChange(e);
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
{multiple && (
|
|
|
|
|
<FormHelperText className="web-text-small">
|
|
|
|
|
You can select multiple images using{" "}
|
|
|
|
|
<span className="text-dark">
|
2024-07-01 12:33:55 +05:30
|
|
|
<Kbd size={"sm"} className="text-dark">
|
|
|
|
|
ctrl
|
|
|
|
|
</Kbd>{" "}
|
|
|
|
|
+ <Kbd className="text-dark">select</Kbd>
|
|
|
|
|
</span>
|
2024-06-27 11:50:59 +05:30
|
|
|
</FormHelperText>
|
|
|
|
|
)}
|
2024-07-01 12:33:55 +05:30
|
|
|
{selectedImageData && (
|
|
|
|
|
multiple ?
|
|
|
|
|
selectedImageData?.length > 0 && (
|
|
|
|
|
<Box mt={4} width={"100%"} display="flex" flexWrap="wrap" gap={4}>
|
|
|
|
|
{selectedImageData?.map((imageDataLink, index) => (
|
|
|
|
|
<Box key={index} width={"100px"}>
|
|
|
|
|
<Image
|
|
|
|
|
rounded={"md"}
|
|
|
|
|
objectFit={"cover"}
|
|
|
|
|
src={imageDataLink}
|
|
|
|
|
alt={`profile-${index}`}
|
|
|
|
|
width={100}
|
|
|
|
|
height={100}
|
|
|
|
|
/>
|
|
|
|
|
<Box
|
|
|
|
|
display={"flex"}
|
|
|
|
|
flexDirection={"column"}
|
|
|
|
|
position={"relative"}
|
|
|
|
|
>
|
|
|
|
|
<CloseIcon
|
|
|
|
|
onClick={() => removeImage(index)}
|
|
|
|
|
bg={"#fff"}
|
|
|
|
|
className="link pointer"
|
|
|
|
|
p={1}
|
|
|
|
|
fontSize={"lg"}
|
|
|
|
|
color={"red"}
|
|
|
|
|
fontWeight={"500"}
|
|
|
|
|
rounded={"md"}
|
|
|
|
|
position={"absolute"}
|
|
|
|
|
bottom={0}
|
|
|
|
|
right={0}
|
|
|
|
|
/>
|
|
|
|
|
<Text
|
|
|
|
|
as={"span"}
|
2024-07-03 12:13:09 +05:30
|
|
|
fontSize={"sm"}
|
2024-07-01 12:33:55 +05:30
|
|
|
fontWeight={"500"}
|
|
|
|
|
mt={1}
|
|
|
|
|
isTruncated={true}
|
|
|
|
|
>
|
|
|
|
|
{imageData[index]?.name}
|
|
|
|
|
</Text>
|
2024-07-03 12:13:09 +05:30
|
|
|
<Text as={"span"} fontSize={"sm"} fontStyle={"italic"}>
|
2024-07-01 12:33:55 +05:30
|
|
|
{(imageData[index]?.size / (1024 * 1024)).toFixed(2)}{" "}
|
|
|
|
|
mb
|
|
|
|
|
</Text>
|
|
|
|
|
</Box>
|
|
|
|
|
</Box>
|
|
|
|
|
))}
|
|
|
|
|
<AddIcon
|
|
|
|
|
onClick={() =>
|
|
|
|
|
document.getElementById(id).click()
|
|
|
|
|
}
|
|
|
|
|
rounded={"md"}
|
|
|
|
|
width={50}
|
|
|
|
|
height={50}
|
|
|
|
|
mt={26}
|
|
|
|
|
p={4}
|
|
|
|
|
cursor={"pointer"}
|
|
|
|
|
className="link"
|
|
|
|
|
/>
|
|
|
|
|
</Box>)
|
|
|
|
|
:<Box mt={5} width={"49%"}>
|
|
|
|
|
<Image
|
|
|
|
|
rounded={"md"}
|
|
|
|
|
objectFit={"cover"}
|
|
|
|
|
src={selectedImageData}
|
|
|
|
|
alt="profile"
|
|
|
|
|
width={100}
|
|
|
|
|
height={100}
|
|
|
|
|
/>
|
|
|
|
|
<Box
|
|
|
|
|
w={"30%"}
|
|
|
|
|
display={"flex"}
|
|
|
|
|
flexDirection={"column"}
|
|
|
|
|
position={"relative"}
|
|
|
|
|
>
|
|
|
|
|
<CloseIcon
|
|
|
|
|
onClick={() => setSelectedImageData(null)}
|
|
|
|
|
className="link pointer"
|
|
|
|
|
p={1}
|
|
|
|
|
fontSize={"lg"}
|
|
|
|
|
color={"red"}
|
|
|
|
|
fontWeight={"500"}
|
|
|
|
|
rounded={"md"}
|
|
|
|
|
position={"absolute"}
|
|
|
|
|
top={1}
|
|
|
|
|
right={0}
|
|
|
|
|
/>
|
|
|
|
|
<Text
|
|
|
|
|
as={"span"}
|
|
|
|
|
fontSize={"xs"}
|
|
|
|
|
w={"70%"}
|
|
|
|
|
fontWeight={"500"}
|
|
|
|
|
mt={1}
|
|
|
|
|
isTruncated={true}
|
|
|
|
|
>
|
|
|
|
|
{imageData?.name}
|
|
|
|
|
</Text>
|
|
|
|
|
<Text as={"span"} fontSize={"xs"} fontStyle={"italic"}>
|
|
|
|
|
{(imageData?.size / (1024 * 1024)).toFixed(2)} mb
|
|
|
|
|
</Text>
|
|
|
|
|
</Box>
|
|
|
|
|
</Box>
|
|
|
|
|
)}
|
2024-06-27 11:50:59 +05:30
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
return (
|
|
|
|
|
<Input
|
|
|
|
|
focusBorderColor="forestGreen.300"
|
|
|
|
|
size={"sm"}
|
2024-07-03 12:13:09 +05:30
|
|
|
fontSize={'sm'}
|
2024-06-27 11:50:59 +05:30
|
|
|
type={type}
|
|
|
|
|
{...field}
|
|
|
|
|
{...props}
|
2024-07-01 12:33:55 +05:30
|
|
|
placeholder={placeHolder ? placeHolder : label}
|
2024-07-03 12:13:09 +05:30
|
|
|
borderRadius={'4px'}
|
2024-06-27 11:50:59 +05:30
|
|
|
textAlign={arabic ? "right" : "left"}
|
2024-07-03 12:13:09 +05:30
|
|
|
_placeholder={{fontSize:'xs'}}
|
2024-06-27 11:50:59 +05:30
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
{errors[name] && (
|
|
|
|
|
<span className="text-danger web-text-small fw-bold ps-2 d-flex align-items-center gap-1 mt-1">
|
|
|
|
|
<TiWarning className="fw-bold fs-5 " /> {errors[name].message}
|
|
|
|
|
</span>
|
|
|
|
|
)}
|
2024-07-01 12:33:55 +05:30
|
|
|
{helperText && (
|
|
|
|
|
<FormHelperText className="web-text-small">{helperText}</FormHelperText>
|
|
|
|
|
)}
|
|
|
|
|
{type === "file" && (
|
2024-06-27 11:50:59 +05:30
|
|
|
<FormHelperText className="web-text-small">
|
|
|
|
|
Maximum limit of image is 10MB.
|
|
|
|
|
</FormHelperText>
|
|
|
|
|
)}
|
|
|
|
|
</FormControl>
|
|
|
|
|
);
|
2024-06-24 12:08:21 +05:30
|
|
|
|
2024-06-26 17:45:13 +05:30
|
|
|
export default FormField;
|