Add AccountCreation component and product list functionality; update routing and translations
This commit is contained in:
parent
a6a67d69d5
commit
8cee8e0383
@ -55,5 +55,16 @@
|
|||||||
"cabinetCreation": "Cabinet Creation",
|
"cabinetCreation": "Cabinet Creation",
|
||||||
"cabinetId": "Cabinet ID",
|
"cabinetId": "Cabinet ID",
|
||||||
"cabinetKeyId": "Cabinet Key ID",
|
"cabinetKeyId": "Cabinet Key ID",
|
||||||
"noOfLockers": "No of Lockers"
|
"noOfLockers": "No of Lockers",
|
||||||
|
"productCode": "Product Code",
|
||||||
|
"interestCategory": "Interest Category",
|
||||||
|
"segmentCode": "Segment Code",
|
||||||
|
"accountHolderType": "Account Holder Type",
|
||||||
|
"primaryCifNumber": "Primary CIF Number",
|
||||||
|
"nomineeCifNumber": "Nominee CIF Number",
|
||||||
|
"activityCode": "Activity Code",
|
||||||
|
"customerType": "Customer Type",
|
||||||
|
"collateralFDAccount": "Collateral FD Account",
|
||||||
|
"rentPayAccount": "Rent Pay Account",
|
||||||
|
"submit": "Submit"
|
||||||
}
|
}
|
@ -6,7 +6,7 @@ function BannerInfo({info}) {
|
|||||||
const {t} = useTranslation();
|
const {t} = useTranslation();
|
||||||
|
|
||||||
const infoElements = Object.keys(info).map((key) => (
|
const infoElements = Object.keys(info).map((key) => (
|
||||||
<BannerInfoElement key={key} title={t(key)} description={t(info[key])} />
|
<BannerInfoElement key={key} title={t(key)} description={info[key]} />
|
||||||
))
|
))
|
||||||
infoElements.push(
|
infoElements.push(
|
||||||
<BannerInfoElement
|
<BannerInfoElement
|
||||||
|
33
src/components/FormField.jsx
Normal file
33
src/components/FormField.jsx
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import PropTypes from "prop-types";
|
||||||
|
import { motion } from "motion/react";
|
||||||
|
|
||||||
|
function FormField({ label, children, icon }) {
|
||||||
|
return (
|
||||||
|
<div className="flex">
|
||||||
|
<label className="mr-4 text-lg text-black dark:text-primary-dark w-[17%]">
|
||||||
|
{label}
|
||||||
|
</label>
|
||||||
|
<div className="flex w-full gap-4 items-center">
|
||||||
|
{children}
|
||||||
|
{icon && (
|
||||||
|
<motion.div
|
||||||
|
whileHover={{ scale: 1.1 }}
|
||||||
|
whileTap={{ scale: 0.9 }}
|
||||||
|
className="bg-primary rounded-full p-2 text-white cursor-pointer"
|
||||||
|
>
|
||||||
|
{icon}
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
FormField.propTypes = {
|
||||||
|
label: PropTypes.string.isRequired,
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
icon: PropTypes.node,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FormField;
|
32
src/components/FormInput.jsx
Normal file
32
src/components/FormInput.jsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import PropTypes from "prop-types";
|
||||||
|
|
||||||
|
function FormInput({
|
||||||
|
value,
|
||||||
|
onChange,
|
||||||
|
maxLength=17,
|
||||||
|
readOnly = false,
|
||||||
|
className = "",
|
||||||
|
type = "text",
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<input
|
||||||
|
readOnly={readOnly}
|
||||||
|
value={value}
|
||||||
|
className={`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}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
FormInput.propTypes = {
|
||||||
|
value: PropTypes.string.isRequired,
|
||||||
|
onChange: PropTypes.func.isRequired,
|
||||||
|
readOnly: PropTypes.bool,
|
||||||
|
className: PropTypes.string,
|
||||||
|
type: PropTypes.string,
|
||||||
|
maxLength: PropTypes.number,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FormInput;
|
37
src/components/FormSelect.jsx
Normal file
37
src/components/FormSelect.jsx
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import PropTypes from "prop-types";
|
||||||
|
|
||||||
|
function FormSelect({ value, onChange, options, className }) {
|
||||||
|
return (
|
||||||
|
<select
|
||||||
|
value={value}
|
||||||
|
className={
|
||||||
|
"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}
|
||||||
|
>
|
||||||
|
<option disabled value="">
|
||||||
|
Select
|
||||||
|
</option>
|
||||||
|
{options.map(({ value, label }) => (
|
||||||
|
<option key={value} value={value}>
|
||||||
|
{label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
FormSelect.propTypes = {
|
||||||
|
value: PropTypes.string.isRequired,
|
||||||
|
onChange: PropTypes.func.isRequired,
|
||||||
|
className: PropTypes.string,
|
||||||
|
options: PropTypes.arrayOf(
|
||||||
|
PropTypes.shape({
|
||||||
|
value: PropTypes.string.isRequired,
|
||||||
|
label: PropTypes.string.isRequired,
|
||||||
|
})
|
||||||
|
).isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FormSelect;
|
@ -24,7 +24,7 @@ function Header() {
|
|||||||
{
|
{
|
||||||
name: "lockerOperation",
|
name: "lockerOperation",
|
||||||
submenu: [
|
submenu: [
|
||||||
{ name: "accountCreation", path: "account-creation" },
|
{ name: "accountCreation", path: "operation/account" },
|
||||||
{ name: "cabinetMaintenance", path: "operation/cabinet" },
|
{ name: "cabinetMaintenance", path: "operation/cabinet" },
|
||||||
{ name: "lockerMaintenance", path: "locker-maintenance" },
|
{ name: "lockerMaintenance", path: "locker-maintenance" },
|
||||||
{ name: "rentPenaltyCollection", path: "rent-collection" },
|
{ name: "rentPenaltyCollection", path: "rent-collection" },
|
||||||
|
74
src/components/ProductListTable.jsx
Normal file
74
src/components/ProductListTable.jsx
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import clsx from "clsx";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
|
||||||
|
function ProductListTable({ productInfo, onSelectProduct }) {
|
||||||
|
return (
|
||||||
|
<table className="w-11/12 border-separate border-spacing-0 rounded-2xl overflow-hidden">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th className="border border-t-2 border-l-2 border-primary bg-secondary rounded-ss-2xl font-medium text-[#111]">
|
||||||
|
Product Code
|
||||||
|
</th>
|
||||||
|
<th className="border border-t-2 p-2 border-primary bg-secondary font-medium text-[#111]">
|
||||||
|
Description
|
||||||
|
</th>
|
||||||
|
<th className="border border-t-2 p-2 border-primary bg-secondary font-medium text-[#111]">
|
||||||
|
Interest Category
|
||||||
|
</th>
|
||||||
|
<th className="border border-t-2 border-r-2 p-2 border-primary bg-secondary rounded-se-2xl font-medium text-[#111]">
|
||||||
|
Description
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{productInfo.map((prod, idx) => (
|
||||||
|
<tr
|
||||||
|
key={idx}
|
||||||
|
className="cursor-pointer hover:bg-grey/[0.2] border-b"
|
||||||
|
onClick={() => onSelectProduct(prod)}
|
||||||
|
>
|
||||||
|
<td
|
||||||
|
className={clsx(
|
||||||
|
"border border-l-2 border-primary p-2",
|
||||||
|
idx === productInfo.length - 1 && "rounded-bl-2xl border-b-2"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{prod.productCode}
|
||||||
|
</td>
|
||||||
|
<td
|
||||||
|
className={clsx(
|
||||||
|
"border border-primary p-2",
|
||||||
|
idx === productInfo.length - 1 && "border-b-2"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{prod.productCodeDescription}
|
||||||
|
</td>
|
||||||
|
<td
|
||||||
|
className={clsx(
|
||||||
|
"border border-primary p-2",
|
||||||
|
idx === productInfo.length - 1 && "border-b-2"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{prod.interestCategory}
|
||||||
|
</td>
|
||||||
|
<td
|
||||||
|
className={clsx(
|
||||||
|
"border border-r-2 border-primary p-2",
|
||||||
|
idx === productInfo.length - 1 && "rounded-br-2xl border-b-2"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{prod.interestCategoryDescription}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProductListTable.propTypes = {
|
||||||
|
productInfo: PropTypes.array.isRequired,
|
||||||
|
onSelectProduct: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ProductListTable;
|
@ -8,6 +8,7 @@ import Home from "./pages/Home.jsx";
|
|||||||
import CabinetMaintenace from "./pages/CabinetMaintenance.jsx";
|
import CabinetMaintenace from "./pages/CabinetMaintenance.jsx";
|
||||||
import CabinetCreation from "./pages/CabinetCreation.jsx";
|
import CabinetCreation from "./pages/CabinetCreation.jsx";
|
||||||
import LockersRegistration from "./pages/LockersRegistration.jsx";
|
import LockersRegistration from "./pages/LockersRegistration.jsx";
|
||||||
|
import AccountCreation from "./pages/AccountCreation.jsx";
|
||||||
|
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
{
|
{
|
||||||
@ -30,6 +31,10 @@ const router = createBrowserRouter([
|
|||||||
path: "operation/cabinet/create/register-lockers",
|
path: "operation/cabinet/create/register-lockers",
|
||||||
element: <LockersRegistration />,
|
element: <LockersRegistration />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "operation/account",
|
||||||
|
element: <AccountCreation />,
|
||||||
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
310
src/pages/AccountCreation.jsx
Normal file
310
src/pages/AccountCreation.jsx
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
import { AnimatePresence } from "motion/react";
|
||||||
|
import clsx from "clsx";
|
||||||
|
import { PackageSearch, Copy, UserSearch } from "lucide-react";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { motion } from "motion/react";
|
||||||
|
import FormBox from "../components/FormBox";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
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: "",
|
||||||
|
type: "",
|
||||||
|
});
|
||||||
|
const [showProductModal, setShowProductModal] = useState(false);
|
||||||
|
const [submitting] = useState(false);
|
||||||
|
const [accountDetails, setAccountDetails] = useState({
|
||||||
|
productCode: "",
|
||||||
|
interestCategory: "",
|
||||||
|
segmentCode: "",
|
||||||
|
accountHolderType: "",
|
||||||
|
primaryCifNumber: "",
|
||||||
|
nomineeCifNumber: "",
|
||||||
|
activityCode: "",
|
||||||
|
customerType: "",
|
||||||
|
collateralFDAccount: "",
|
||||||
|
rentPayAccount: "",
|
||||||
|
productCodeValid: true,
|
||||||
|
interestCategoryValid: true,
|
||||||
|
segmentCodeValid: true,
|
||||||
|
accountHolderTypeValid: true,
|
||||||
|
primaryCifNumberValid: true,
|
||||||
|
nomineeCifNumberValid: true,
|
||||||
|
activityCodeValid: true,
|
||||||
|
customerTypeValid: true,
|
||||||
|
collateralFDAccountValid: true,
|
||||||
|
rentPayAccountValid: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleProductSelect = (product) => {
|
||||||
|
const newAccountDetails = { ...accountDetails };
|
||||||
|
newAccountDetails.productCode = product.productCode;
|
||||||
|
newAccountDetails.interestCategory = product.interestCategory;
|
||||||
|
setAccountDetails(newAccountDetails);
|
||||||
|
setShowProductModal(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const accountDetailsFields = [
|
||||||
|
{
|
||||||
|
label: t("productCode"),
|
||||||
|
name: "productCode",
|
||||||
|
type: "input",
|
||||||
|
subType: "number",
|
||||||
|
readOnly: true,
|
||||||
|
validate: (value) => value !== "",
|
||||||
|
icon: (
|
||||||
|
<PackageSearch
|
||||||
|
size={18}
|
||||||
|
onClick={() => {
|
||||||
|
console.log("Product search clicked");
|
||||||
|
console.log(showProductModal);
|
||||||
|
setShowProductModal(true);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t("interestCategory"),
|
||||||
|
name: "interestCategory",
|
||||||
|
type: "input",
|
||||||
|
subType: "number",
|
||||||
|
readOnly: true,
|
||||||
|
validate: (value) => value !== "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t("segmentCode"),
|
||||||
|
name: "segmentCode",
|
||||||
|
type: "select",
|
||||||
|
options: [
|
||||||
|
{ value: "0706", label: "0706: Individual" },
|
||||||
|
{ value: "0306", label: "0306: Staff" },
|
||||||
|
{ value: "5003", label: "5003: Senior Citizen" },
|
||||||
|
{ value: "5010", label: "5010: SHG" },
|
||||||
|
{ value: "5000", label: "5000: Bank" },
|
||||||
|
{ value: "5009", label: "5009: Institutions" },
|
||||||
|
{ value: "5050", label: "5050: Others" },
|
||||||
|
{ value: "5007", label: "5007: Society" },
|
||||||
|
],
|
||||||
|
validate: (value) => value !== "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t("accountHolderType"),
|
||||||
|
name: "accountHolderType",
|
||||||
|
type: "select",
|
||||||
|
options: [
|
||||||
|
{ value: "1", label: "Single" },
|
||||||
|
{ value: "2", label: "Joint" },
|
||||||
|
],
|
||||||
|
validate: (value) => value === "1" || value === "2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t("primaryCifNumber"),
|
||||||
|
name: "primaryCifNumber",
|
||||||
|
type: "input",
|
||||||
|
subType: "number",
|
||||||
|
maxLength: 17,
|
||||||
|
validate: (value) => /^[0-9]{17}$/.test(value),
|
||||||
|
icon: <UserSearch size={18} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t("nomineeCifNumber"),
|
||||||
|
name: "nomineeCifNumber",
|
||||||
|
type: "input",
|
||||||
|
subType: "number",
|
||||||
|
maxLength: 17,
|
||||||
|
validate: (value) => /^[0-9]{17}$/.test(value),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const additionalDetailsFields = [
|
||||||
|
{
|
||||||
|
label: t("activityCode"),
|
||||||
|
name: "activityCode",
|
||||||
|
type: "select",
|
||||||
|
options: [
|
||||||
|
{ value: "0701", label: "Direct Agriculture" },
|
||||||
|
{ value: "0702", label: "Indirect Agriculture" },
|
||||||
|
{ value: "0703", label: "Agricultural Services Unit" },
|
||||||
|
{ value: "0704", label: "Farm Irrigation" },
|
||||||
|
{ value: "0705", label: "Fruits & Vegetables" },
|
||||||
|
{ value: "0706", label: "Non-Agriculture" },
|
||||||
|
],
|
||||||
|
validate: (value) => value !== "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t("customerType"),
|
||||||
|
name: "customerType",
|
||||||
|
type: "select",
|
||||||
|
options: [
|
||||||
|
{ value: "0709", label: "Individual" },
|
||||||
|
{ value: "0701", label: "Corporate" },
|
||||||
|
],
|
||||||
|
validate: (value) => value === "0709" || value === "0701",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t("collateralFDAccount"),
|
||||||
|
name: "collateralFDAccount",
|
||||||
|
type: "input",
|
||||||
|
subType: "number",
|
||||||
|
maxLength: 17,
|
||||||
|
validate: (value) => /^[0-9]{17}$/.test(value),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t("rentPayAccount"),
|
||||||
|
name: "rentPayAccount",
|
||||||
|
type: "input",
|
||||||
|
subType: "number",
|
||||||
|
maxLength: 17,
|
||||||
|
validate: (value) => /^[0-9]{17}$/.test(value),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const handleSubmit = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
let isValid = true;
|
||||||
|
const newValidationState = { ...accountDetails };
|
||||||
|
|
||||||
|
// Validate account details fields
|
||||||
|
[...accountDetailsFields, ...additionalDetailsFields].forEach((field) => {
|
||||||
|
if (field.validate) {
|
||||||
|
const fieldIsValid = field.validate(accountDetails[field.name]);
|
||||||
|
newValidationState[`${field.name}Valid`] = fieldIsValid;
|
||||||
|
if (!fieldIsValid) isValid = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setAccountDetails(newValidationState);
|
||||||
|
|
||||||
|
if (!isValid) {
|
||||||
|
showToast("Highlighted fields are invalid", "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log("Form is valid", accountDetails);
|
||||||
|
};
|
||||||
|
const renderProductModal = () => {
|
||||||
|
return (
|
||||||
|
<AnimatePresence mode="popLayout">
|
||||||
|
{showProductModal && (
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
exit={{ opacity: 0 }}
|
||||||
|
key="productList"
|
||||||
|
className="fixed z-50 inset-0 flex items-center justify-center bg-black/50"
|
||||||
|
>
|
||||||
|
<motion.div
|
||||||
|
initial={{ scale: 0.8 }}
|
||||||
|
animate={{ scale: 1 }}
|
||||||
|
exit={{ scale: 0.8 }}
|
||||||
|
className="flex flex-col items-center bg-white p-4 py-8 rounded-3xl w-[60%] max-h-[80%] overflow-auto font-body"
|
||||||
|
>
|
||||||
|
<h2 className="text-xl mb-4">Select Product</h2>
|
||||||
|
<ProductListTable
|
||||||
|
productInfo={productInfo}
|
||||||
|
onSelectProduct={handleProductSelect}
|
||||||
|
/>
|
||||||
|
</motion.div>
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renerField = (field) => {
|
||||||
|
const commonProps = {
|
||||||
|
value: accountDetails[field.name],
|
||||||
|
onChange: (e) => {
|
||||||
|
const newAccountDetails = { ...accountDetails };
|
||||||
|
newAccountDetails[field.name] = e.target.value;
|
||||||
|
newAccountDetails[`${field.name}Valid`] = true;
|
||||||
|
setAccountDetails(newAccountDetails);
|
||||||
|
},
|
||||||
|
maxLength: field.maxLength,
|
||||||
|
className: clsx(!accountDetails[`${field.name}Valid`] && "border-error"),
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormField key={field.name} label={field.label} icon={field.icon}>
|
||||||
|
{field.type === "input" ? (
|
||||||
|
<FormInput
|
||||||
|
{...commonProps}
|
||||||
|
type={field.subType}
|
||||||
|
readOnly={field.readOnly}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<FormSelect {...commonProps} options={field.options} />
|
||||||
|
)}
|
||||||
|
</FormField>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<AnimatePresence>
|
||||||
|
{notification.visible && (
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
exit={{ opacity: 0 }}
|
||||||
|
className={clsx(
|
||||||
|
"p-4 mb-8 font-body text-center text-xl rounded-2xl flex items-center justify-center gap-2",
|
||||||
|
notification.type === "error"
|
||||||
|
? "bg-error-surface text-error"
|
||||||
|
: "bg-success-surface text-success"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{notification.message.split(":").map((msg, index) => {
|
||||||
|
return index === 1 ? (
|
||||||
|
<span key={index} className="border-b border-dashed">
|
||||||
|
{msg}
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span key={index}>{msg}</span>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
<Copy
|
||||||
|
cursor={"pointer"}
|
||||||
|
size={15}
|
||||||
|
onClick={navigator.clipboard.writeText(
|
||||||
|
notification.message.split(":")[1].trim()
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
|
{renderProductModal()}
|
||||||
|
<FormBox title="Account Creation" disabled={submitting}>
|
||||||
|
<div className="p-2 pt-7 ">
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<h1 className="text-2xl font-medium text-primary py-2">
|
||||||
|
Account Details
|
||||||
|
</h1>
|
||||||
|
{accountDetailsFields.map(renerField)}
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<h1 className="text-2xl font-medium text-primary py-2 pt-6">
|
||||||
|
Additional Details
|
||||||
|
</h1>
|
||||||
|
{additionalDetailsFields.map(renerField)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
text={t("submit")}
|
||||||
|
onClick={handleSubmit}
|
||||||
|
disabled={submitting}
|
||||||
|
/>
|
||||||
|
</FormBox>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AccountCreation;
|
12
src/util/productList.js
Normal file
12
src/util/productList.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
const productInfo = [
|
||||||
|
{ productCode: '3001', productCodeDescription: 'RECURRING DEPOSIT', interestCategory: '1004', interestCategoryDescription: 'NON MEMBER - SENIOR CITIZEN', payableGl: '16010', paidGl: '62110' },
|
||||||
|
{ productCode: '1101', productCodeDescription: 'CURRENT ACCOUNT', interestCategory: '1009', interestCategoryDescription: 'GENERAL', payableGl: '16018', paidGl: '62115' },
|
||||||
|
{ productCode: '1101', productCodeDescription: 'SAVINGS DEPOSIT', interestCategory: '1007', interestCategoryDescription: 'NON MEMBER', payableGl: '16301', paidGl: '62117' },
|
||||||
|
{ productCode: '2002', productCodeDescription: 'CASH CERTIFICATE -GENERAL', interestCategory: '1047', interestCategoryDescription: 'COMPOUNDING', payableGl: '16011', paidGl: '62111' },
|
||||||
|
{ productCode: '2002', productCodeDescription: 'CASH CERTIFICATE', interestCategory: '1005', interestCategoryDescription: 'NON MEMBER - SENIOR CITIZEN', payableGl: '16011', paidGl: '62111' },
|
||||||
|
{ productCode: '2001', productCodeDescription: 'MIS', interestCategory: '1003', interestCategoryDescription: 'NON MEMBER - SENIOR CITIZEN', payableGl: '16137', paidGl: '62125' },
|
||||||
|
{ productCode: '2002', productCodeDescription: 'FIXED DEPOSIT', interestCategory: '1006', interestCategoryDescription: 'NONMEMBER - SENIOR CITIZEN', payableGl: '16009', paidGl: '62109' },
|
||||||
|
{ productCode: '2002', productCodeDescription: 'CASH CERTIFICATE', interestCategory: '1001', interestCategoryDescription: 'MEMBER', payableGl: '16011', paidGl: '62111' },
|
||||||
|
{ productCode: '1101', productCodeDescription: 'SAVINGS DEPOSIT- MEMBER', interestCategory: '1347', interestCategoryDescription: 'COMPOUNDING', payableGl: '16301', paidGl: '62117' }
|
||||||
|
]
|
||||||
|
export default productInfo;
|
Loading…
x
Reference in New Issue
Block a user