refactor: enhance FormInput and FormSelect components with validation feedback and layout adjustments

This commit is contained in:
Md Asif 2024-12-24 01:31:07 +05:30
parent 03c4988ff1
commit 962102d44c
5 changed files with 53 additions and 24 deletions

View File

@ -1,22 +1,38 @@
import PropTypes from "prop-types";
import { motion, AnimatePresence } from "motion/react";
function FormInput({
value,
onChange,
maxLength=17,
valid = true,
maxLength = 17,
readOnly = false,
className = "",
type = "text",
}) {
return (
<input
readOnly={readOnly}
value={value}
className={`w-1/2 md:w-1/3 lg:w-1/4 h-10 px-2 rounded-full dark:bg-white dark:text-grey border-2 text-grey focus:outline-grey ${className}`}
onChange={onChange}
type={type}
maxLength={maxLength}
/>
<div>
<input
readOnly={readOnly}
value={value}
className={`w-72 h-10 px-2 rounded-full dark:bg-white dark:text-grey border-2 text-grey focus:outline-grey ${className}`}
onChange={onChange}
type={type}
maxLength={maxLength}
/>
<AnimatePresence>
{!valid && (
<motion.div
className="text-sm text-error ml-3 pt-1"
initial={{ y: 15, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
exit={{ y: 15, opacity: 0 }}
key="cabinetIdError"
>
Invalid Value
</motion.div>
)}
</AnimatePresence>
</div>
);
}
@ -27,6 +43,7 @@ FormInput.propTypes = {
className: PropTypes.string,
type: PropTypes.string,
maxLength: PropTypes.number,
valid: PropTypes.bool,
};
export default FormInput;

View File

@ -1,11 +1,13 @@
import PropTypes from "prop-types";
import { motion, AnimatePresence } from "motion/react";
function FormSelect({ value, onChange, options, className }) {
function FormSelect({ value, onChange, options, className, valid = true }) {
return (
<div>
<select
value={value}
className={
"w-1/2 md:w-1/3 lg:w-1/4 h-10 px-2 rounded-full dark:bg-white dark:text-grey border-2 text-grey focus:outline-grey " +
"w-72 h-10 px-2 rounded-full dark:bg-white dark:text-grey border-2 text-grey focus:outline-grey " +
className
}
onChange={onChange}
@ -19,6 +21,20 @@ function FormSelect({ value, onChange, options, className }) {
</option>
))}
</select>
<AnimatePresence>
{!valid && (
<motion.div
className="text-sm text-error ml-3 pt-1"
initial={{ y: 15, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
exit={{ y: 15, opacity: 0 }}
key="cabinetIdError"
>
Invalid Value
</motion.div>
)}
</AnimatePresence>
</div>
);
}
@ -26,6 +42,7 @@ FormSelect.propTypes = {
value: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
className: PropTypes.string,
valid: PropTypes.bool,
options: PropTypes.arrayOf(
PropTypes.shape({
value: PropTypes.string.isRequired,

View File

@ -9,13 +9,11 @@ import FormField from "../components/FormField";
import FormInput from "../components/FormInput";
import FormSelect from "../components/FormSelect";
import Button from "../components/Button";
import { useToast } from "../hooks/useToast";
import productInfo from "../util/productList";
import ProductListTable from "../components/ProductListTable";
function AccountCreation() {
const { t } = useTranslation();
const showToast = useToast();
const [notification] = useState({
visible: false,
message: "",
@ -179,7 +177,6 @@ function AccountCreation() {
setAccountDetails(newValidationState);
if (!isValid) {
showToast("Highlighted fields are invalid", "error");
return;
}
console.log("Form is valid", accountDetails);
@ -216,6 +213,7 @@ function AccountCreation() {
const renerField = (field) => {
const commonProps = {
value: accountDetails[field.name],
valid: accountDetails[`${field.name}Valid`],
onChange: (e) => {
const newAccountDetails = { ...accountDetails };
newAccountDetails[field.name] = e.target.value;

View File

@ -25,7 +25,7 @@ function CabinetMaintenace() {
<FormBox title={t("cabinetMaintenance")}>
<div className="p-2 pt-7">
<div className="flex">
<label className="mr-4 text-lg text-black dark:text-primary-dark w-[10%]">
<label className="mr-4 text-lg text-black dark:text-primary-dark w-[10%]">
{t("operation")}
</label>
<div className="w-full">
@ -45,13 +45,13 @@ function CabinetMaintenace() {
</option>
<option value="create">{t("create")}</option>
</select>
<AnimatePresence initial={false}>
<AnimatePresence>
{!operation.valid && (
<motion.div
className="w-1/5 text-sm text-error ml-3 pt-1"
initial={{ opacity: 0,scale: 0 }}
animate={{ opacity: 1,scale: 1 }}
exit={{ opacity: 0,scale: 0 }}
initial={{ y: 15, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
exit={{ y: 15, opacity: 0 }}
key="cabinetIdError"
>
Invalid Operation
@ -60,7 +60,6 @@ function CabinetMaintenace() {
</AnimatePresence>
</div>
</div>
</div>
<Button text={t("next")} onClick={(e) => handleNext(e)} />
</FormBox>

View File

@ -4,7 +4,6 @@ import FormInput from "../components/FormInput";
import FormSelect from "../components/FormSelect";
import { useTranslation } from "react-i18next";
import { useState } from "react";
import { useToast } from "../hooks/useToast";
import clsx from "clsx";
import Button from "../components/Button";
import { lockerService } from "../services/locker.service";
@ -14,7 +13,6 @@ import Notification from "../components/Notification";
function LockerStatus() {
const { t } = useTranslation();
const showToast = useToast();
const [lockerDetails, setLockerDetails] = useState({
cabinetId: "",
lockerId: "",
@ -73,7 +71,6 @@ function LockerStatus() {
setLockerDetails(newValidationState);
if (!isValid) {
showToast("Highlighted fields are invalid", "error");
return;
}
@ -101,6 +98,7 @@ function LockerStatus() {
const renderField = (field) => {
const commonProps = {
value: lockerDetails[field.name],
valid: lockerDetails[`${field.name}Valid`],
onChange: (e) => {
const newLockerDetails = { ...lockerDetails };
newLockerDetails[field.name] = e.target.value.toUpperCase();