|
- import {
- Button,
- FormControlLabel,
- Grid, InputAdornment, Switch, TextField, Typography,
- Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Select, MenuItem, IconButton
- } from '@mui/material';
- import MainCard from "../../../components/MainCard";
- import * as React from "react";
- import {useForm} from "react-hook-form";
- import {useContext, useEffect, useState} from "react";
- import LoadingComponent from "../../extra-pages/LoadingComponent";
- import {useLocation, useNavigate, useParams} from "react-router-dom";
- import {
- GeneralConfirmWindow,
- getComboValueByIdList,
- getComboValueByLabel,
- getDateString,
- getDeletedRecordWithRefList,
- getIdList,
- getNewRecordWithRefList, isOptionEqualToValue, isStringEmptyAfterTrim, notifyDeleteError, notifyDeleteSuccess,
- notifySaveSuccess, trimDataBeforePost,
- } from "../../../utils/CommonFunction";
- import Autocomplete from "@mui/material/Autocomplete";
- import axios from "axios";
- import {apiPath} from "../../../auth/utils";
- import {
- CHECK_EVENT_DUPLICATE,
- GET_CLIENT_PATH,
- GET_CONSULTANT_COMBO_LIST,
- GET_SUB_DIVISION_COMBO_LIST,
- POST_CLIENT_PATH
- } from "../../../utils/ApiPathConst";
- import {LIONER_BUTTON_THEME, LIONER_LONG_BUTTON_THEME, GENERAL_RED_COLOR} from "../../../themes/colorConst";
- import {eventFrequencyCombo, EVENT_REGION_COMBO, EVENT_TYPE_COMBO} from "../../../utils/ComboConst";
- import {DatePicker} from "@mui/x-date-pickers/DatePicker";
- import dayjs from "dayjs";
- import {DemoItem} from "@mui/x-date-pickers/internals/demo";
- import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs";
- import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider";
- import {ThemeProvider} from "@emotion/react";
- import UploadContext from "../../../components/UploadProvider";
- import {isObjEmpty} from "../../../utils/Utils";
- import AbilityContext from "../../../components/AbilityProvider";
- import {CARD_MAX_WIDTH} from "../../../themes/themeConst";
-
- const ClientForm = ({ refClientDetail, isNewRecord, getClientDetail }) => {
- const location = useLocation();
- const queryParams = new URLSearchParams(location.search);
- const refId = queryParams.get("refId");
-
- const params = useParams();
- const navigate = useNavigate();
- const ability = useContext(AbilityContext);
- const [onReady, setOnReady] = useState(false);
- const [errors, setErrors] = useState({});
- const [clientDetail, setClientDetail] = useState({});
- const [isCollectData, setIsCollectData] = useState(false);
- const [userConfirm, setUserConfirm] = useState(false);
- const [isEditing, setIsEditing] = useState(false);
- const { setIsUploading } = useContext(UploadContext);
- const [refClient, setRefClient] = useState({});
- const [consultantComboList, setConsultantComboList] = useState([]);
- const [selectedConsultant, setSelectedConsultant] = useState(null);
- const [isFirstInit, setIsFirstInit] = useState(true);
-
- // Form data
- const { register, getValues, setValue } = useForm();
- const [dob, setDob] = useState(null);
-
- const [dobError, setDobError] = React.useState(null);
-
- // Handler to navigate back
- const returnSearchPage = () => {
- navigate('/client');
- }
-
- const FIXED_HEADER_HEIGHT = 120; // <-- **IMPORTANT: Set this to the height of your actual fixed header in pixels**
-
- const handleFocus = (event) => {
- setTimeout(() => {
- const element = event.target;
- // Get the element's position relative to the viewport
- const rect = element.getBoundingClientRect();
-
- // Calculate the target scroll position (Current scroll position + element top position - Header height)
- const targetScrollY = window.scrollY + rect.top - FIXED_HEADER_HEIGHT;
-
- // Scroll the window to the new position
- window.scrollTo({
- top: targetScrollY,
- behavior: 'smooth'
- });
-
- // Ensure the element has focus
- element.focus();
-
- }, 100);
- };
-
- // Handler to enable edit mode
- const handleEditClick = () => {
- setIsEditing(true);
- };
-
- useEffect(() => {
- if (!isObjEmpty(refClient) && consultantComboList.length > 0 && isFirstInit) {
- const matched = consultantComboList.find(c => c.id === refClient.consultantId);
- setSelectedConsultant(matched || null);
- setValue("consultantId", matched || null);
- setIsFirstInit(false);
- }
- }, [refClient, consultantComboList, isFirstInit]);
-
- // 1. Earned Income
- const [earnedIncome, setEarnedIncome] = useState({
- salaryCurrent: '',
- salaryLast: '',
- bonusCurrent: '',
- bonusLast: '',
- otherEarnedCurrent: '',
- otherEarnedLast: ''
- });
- const handleEarnedIncomeChange = (field, value) => {
- setEarnedIncome(prev => ({ ...prev, [field]: value }));
- };
- const totalEarnedCurrent = (parseFloat(earnedIncome.salaryCurrent) || 0) +
- (parseFloat(earnedIncome.bonusCurrent) || 0) +
- (parseFloat(earnedIncome.otherEarnedCurrent) || 0);
- const totalEarnedLast = (parseFloat(earnedIncome.salaryLast) || 0) +
- (parseFloat(earnedIncome.bonusLast) || 0) +
- (parseFloat(earnedIncome.otherEarnedLast) || 0);
-
-
- // 2. Unearned Income (Updated for Current Year / Last Year columns as per Image 2)
- const [unearnedIncome, setUnearnedIncome] = useState({
- companyInterestCurrent: '',
- companyInterestLast: '',
- dividendsCurrent: '',
- dividendsLast: '',
- rentalsCurrent: '',
- rentalsLast: '',
- investmentIncomeCurrent: '',
- investmentIncomeLast: '',
- otherUnearnedCurrent: '',
- otherUnearnedLast: ''
- });
- const handleUnearnedIncomeChange = (field, value) => {
- setUnearnedIncome(prev => ({ ...prev, [field]: value }));
- };
- const totalUnearnedCurrent = (parseFloat(unearnedIncome.companyInterestCurrent) || 0) +
- (parseFloat(unearnedIncome.dividendsCurrent) || 0) +
- (parseFloat(unearnedIncome.rentalsCurrent) || 0) +
- (parseFloat(unearnedIncome.investmentIncomeCurrent) || 0) +
- (parseFloat(unearnedIncome.otherUnearnedCurrent) || 0);
- const totalUnearnedLast = (parseFloat(unearnedIncome.companyInterestLast) || 0) +
- (parseFloat(unearnedIncome.dividendsLast) || 0) +
- (parseFloat(unearnedIncome.rentalsLast) || 0) +
- (parseFloat(unearnedIncome.investmentIncomeLast) || 0) +
- (parseFloat(unearnedIncome.otherUnearnedLast) || 0);
-
-
- // Total Income Calculation
- const totalIncomeCurrent = totalEarnedCurrent + totalUnearnedCurrent;
- const totalIncomeLast = totalEarnedLast + totalUnearnedLast;
-
-
- // 3. Expenditure Statement
- const [expenditure, setExpenditure] = useState({
- mortgageCurrent: '',
- mortgageLast: '',
- rentCurrent: '',
- rentLast: '',
- schoolingCurrent: '',
- schoolingLast: '',
- membershipsCurrent: '',
- membershipsLast: '',
- otherExpenditureCurrent: '',
- otherExpenditureLast: '',
- interestCurrent: '',
- interestLast: '',
- principalCurrent: '',
- principalLast: '',
- otherPrefFinanceCurrent: '',
- otherPrefFinanceLast: ''
- });
- const handleExpenditureChange = (field, value) => {
- setExpenditure(prev => ({ ...prev, [field]: value }));
- };
- const totalExpenditureCurrent = (parseFloat(expenditure.mortgageCurrent) || 0) +
- (parseFloat(expenditure.rentCurrent) || 0) +
- (parseFloat(expenditure.schoolingCurrent) || 0) +
- (parseFloat(expenditure.membershipsCurrent) || 0) +
- (parseFloat(expenditure.otherExpenditureCurrent) || 0) +
- (parseFloat(expenditure.interestCurrent) || 0) +
- (parseFloat(expenditure.principalCurrent) || 0)+
- (parseFloat(expenditure.otherPrefFinanceCurrent) || 0);
- const totalExpenditureLast = (parseFloat(expenditure.mortgageLast) || 0) +
- (parseFloat(expenditure.rentLast) || 0) +
- (parseFloat(expenditure.schoolingLast) || 0) +
- (parseFloat(expenditure.membershipsLast) || 0) +
- (parseFloat(expenditure.otherExpenditureLast) || 0) +
- (parseFloat(expenditure.interestLast) || 0) +
- (parseFloat(expenditure.principalLast) || 0)+
- (parseFloat(expenditure.otherPrefFinanceLast) || 0);
-
-
- // 4. Liquid & Non-Liquid Assets (Combined for Image 4)
- const [assets, setAssets] = useState({
- // Liquid Assets
- cashDepositsCurrent: '',
- cashDepositsLast: '',
- investmentsCurrent: '',
- investmentsLast: '',
- otherLiquidCurrent: '',
- otherLiquidLast: '',
- // Non-Liquid Assets
- netBusinessInterestCurrent: '',
- netBusinessInterestLast: '',
- personalPropertiesCurrent: '',
- personalPropertiesLast: '',
- realEstateCurrent: '',
- realEstateLast: '',
- otherNonLiquidCurrent: '',
- otherNonLiquidLast: ''
- });
- const handleAssetsChange = (field, value) => {
- setAssets(prev => ({ ...prev, [field]: value }));
- };
- const totalLiquidAssetCurrent = (parseFloat(assets.cashDepositsCurrent) || 0) +
- (parseFloat(assets.investmentsCurrent) || 0) +
- (parseFloat(assets.otherLiquidCurrent) || 0);
- const totalLiquidAssetLast = (parseFloat(assets.cashDepositsLast) || 0) +
- (parseFloat(assets.investmentsLast) || 0) +
- (parseFloat(assets.otherLiquidLast) || 0);
-
- const totalNonLiquidAssetCurrent = (parseFloat(assets.netBusinessInterestCurrent) || 0) +
- (parseFloat(assets.personalPropertiesCurrent) || 0) +
- (parseFloat(assets.realEstateCurrent) || 0) + // ← NEW
- (parseFloat(assets.otherNonLiquidCurrent) || 0);
-
- const totalNonLiquidAssetLast = (parseFloat(assets.netBusinessInterestLast) || 0) +
- (parseFloat(assets.personalPropertiesLast) || 0) +
- (parseFloat(assets.realEstateLast) || 0) + // ← NEW
- (parseFloat(assets.otherNonLiquidLast) || 0);
-
- const totalAssetsCurrent = totalLiquidAssetCurrent + totalNonLiquidAssetCurrent;
- const totalAssetsLast = totalLiquidAssetLast + totalNonLiquidAssetLast;
-
-
- // 5. Liabilities (Combined with Existing Premium Financing/Policy Loan section from Image 5)
- const [liabilities, setLiabilities] = useState({
- personalLoansCurrent: '',
- personalLoansLast: '',
- mortgagesCurrent: '',
- mortgagesLast: '',
- marginAccountCurrent: '',
- marginAccountLast: '',
- loanGuaranteesCurrent: '',
- loanGuaranteesLast: '',
- bankingFacilityCurrent: '',
- bankingFacilityLast: '',
- // Existing Premium Financing/Policy Loan (Principal and Other from Image 5)
- prefFinancePrincipalCurrent: '',
- prefFinancePrincipalLast: '',
- prefFinanceOtherCurrent: '',
- prefFinanceOtherLast: '',
- });
- const handleLiabilitiesChange = (field, value) => {
- setLiabilities(prev => ({ ...prev, [field]: value }));
- };
-
- const totalLiabilitiesCurrent = (parseFloat(liabilities.personalLoansCurrent) || 0) +
- (parseFloat(liabilities.mortgagesCurrent) || 0) +
- (parseFloat(liabilities.marginAccountCurrent) || 0) +
- (parseFloat(liabilities.loanGuaranteesCurrent) || 0) +
- (parseFloat(liabilities.bankingFacilityCurrent) || 0) +
- (parseFloat(liabilities.prefFinancePrincipalCurrent) || 0) +
- (parseFloat(liabilities.prefFinanceOtherCurrent) || 0);
- const totalLiabilitiesLast = (parseFloat(liabilities.personalLoansLast) || 0) +
- (parseFloat(liabilities.mortgagesLast) || 0) +
- (parseFloat(liabilities.marginAccountLast) || 0) +
- (parseFloat(liabilities.loanGuaranteesLast) || 0) +
- (parseFloat(liabilities.bankingFacilityLast) || 0) +
- (parseFloat(liabilities.prefFinancePrincipalLast) || 0) +
- (parseFloat(liabilities.prefFinanceOtherLast) || 0);
-
- const dobErrorMessage = React.useMemo(() => {
- switch (dobError) {
- case 'invalidDate': {
- return "Invalid date";
- }
- }
- }, [dobError]);
-
- // DELETE WINDOW RELATED
- const [isWindowOpen, setIsWindowOpen] = React.useState(false);
-
- const handleClose = () => {
- setIsWindowOpen(false);
- };
-
- const handleDeleteClick = () => {
- setIsWindowOpen(true);
- };
-
- const copyClientAsNew = () => {
- navigate(`/event/maintain/-1?refId=${params.id}`);
- };
-
- const formatNumberForDisplay = (num) => {
- console.log(num);
- // 1. Handle null, undefined, or empty string input gracefully (return as is)
- if (num === null || num === undefined || num === '') return '';
-
- // Convert to a string and use regex to allow up to one decimal point and digits
- const numString = String(num);
-
- // Check if the input ends with a decimal point (e.g., '100.')
- // We preserve this during display so the user can continue typing decimals.
- const endsWithDecimal = numString.endsWith('.');
-
- // Attempt to parse the number
- const numericValue = parseFloat(numString);
-
- // 2. If it's NaN (like if the input was only '.'), return the original string
- if (isNaN(numericValue) && numString !== '.') return numString;
-
- // 3. Use Intl.NumberFormat to add commas
- const formatted = new Intl.NumberFormat('en-US', {
- minimumFractionDigits: 0,
- maximumFractionDigits: 2,
- }).format(numericValue);
-
- // 4. If the original string ended with a decimal (e.g., '123.'),
- // re-append the decimal point because Intl.NumberFormat removes it for whole numbers.
- if (endsWithDecimal) {
- // If the formatted number doesn't already contain a decimal point
- if (!formatted.includes('.')) {
- return formatted + '.';
- }
- }
-
- console.log(formatted);
-
- return formatted;
- };
-
- // Function to clean the string input back to a raw number string for state storage
- const cleanNumberForState = (inputString) => {
- if (inputString === null || inputString === undefined) return '';
-
- // 1. Remove commas (,) and any thousand separators
- let cleanedString = inputString.toString().replace(/,/g, '');
-
- // 2. Check for multiple decimal points (only keep the first one)
- const parts = cleanedString.split('.');
- if (parts.length > 2) {
- // If there are multiple decimals, we revert to the state before the last one was typed
- // This prevents '123.45.' from breaking the number
- return parts[0] + '.' + parts.slice(1).join('');
- }
-
- // 3. Optional: Remove characters that are NOT digits or a decimal point
- // cleanedString = cleanedString.replace(/[^0-9.]/g, '');
-
- // Return the cleaned string. We keep it as a STRING to preserve leading zeros
- // and prevent immediate number conversion issues.
- return cleanedString;
- };
-
- function updateData() {
- axios.delete(`${apiPath}${GET_CLIENT_PATH}/${params.id}`)
- .then((response) => {
- if (response.status === 204) {
- notifyDeleteSuccess();
- setIsWindowOpen(false);
- returnSearchPage();
- }
- })
- .catch(error => {
- console.log(error);
- return false;
- });
- }
-
- function getConsultantCombo() {
- axios.get(`${apiPath}${GET_CONSULTANT_COMBO_LIST}`, {
- params: {}
- })
- .then((response) => {
- if (response.status === 200) {
- setConsultantComboList(response.data.records);
- }
- })
- .catch(error => {
- console.log(error);
- return false;
- });
- }
-
- useEffect(() => {
- if (!isNewRecord) {
- setRefClient(refClientDetail);
- }
- getConsultantCombo();
- }, []);
-
- useEffect(() => {
- if (!isObjEmpty(refClient)) {
- setValue("lastname", refClient.lastname);
- setValue("firstname", refClient.firstname);
- setValue("email", refClient.email);
- setValue("phone1", refClient.phone1);
- setValue("phone1Code", refClient.phone1Code);
- setValue("phone2", refClient.phone2);
- setValue("remarks", refClient.remarks);
- setValue("caseManagerId", 1);
-
- setValue("crAddressRoom", refClient.crAddressRoom);
- setValue("crAddressFloor", refClient.crAddressFloor);
- setValue("crAddressBuilding", refClient.crAddressBuilding);
- setValue("crAddressStreet", refClient.crAddressStreet);
- setValue("crAddressStreet", refClient.crAddressStreet);
- setValue("crAddressArea", refClient.crAddressArea);
- setValue("crAddressCity", refClient.crAddressCity);
- setValue("crAddressCountry", refClient.crAddressCountry);
- setValue("crAddressPostalCode", refClient.crAddressPostalCode);
-
- setValue("corAddressRoom", refClient.corAddressRoom);
- setValue("corAddressFloor", refClient.corAddressFloor);
- setValue("corAddressBlock", refClient.corAddressBlock);
- setValue("corAddressBuilding", refClient.corAddressBuilding);
- setValue("corAddressStreet", refClient.corAddressStreet);
- setValue("corAddressArea", refClient.corAddressArea);
- setValue("corAddressCity", refClient.corAddressCity);
- setValue("corAddressCountry", refClient.corAddressCountry);
- setValue("corAddressPostalCode", refClient.corAddressPostalCode);
-
- earnedIncome.salaryCurrent = refClient.salaryCurrent;
- earnedIncome.salaryLast = refClient.salaryLast;
- earnedIncome.bonusCurrent = refClient.bonusCurrent;
- earnedIncome.bonusLast = refClient.bonusLast;
- earnedIncome.otherEarnedCurrent = refClient.otherEarnedCurrent;
- earnedIncome.otherEarnedLast = refClient.otherEarnedLast;
-
- unearnedIncome.companyInterestCurrent = refClient.companyInterestCurrent;
- unearnedIncome.companyInterestLast = refClient.companyInterestLast;
- unearnedIncome.dividendsCurrent = refClient.dividendsCurrent;
- unearnedIncome.dividendsLast = refClient.dividendsLast;
- unearnedIncome.rentalsCurrent = refClient.rentalsCurrent;
- unearnedIncome.rentalsLast = refClient.rentalsLast;
- unearnedIncome.investmentIncomeCurrent = refClient.investmentIncomeCurrent;
- unearnedIncome.investmentIncomeLast = refClient.investmentIncomeLast;
- unearnedIncome.otherUnearnedCurrent = refClient.otherUnearnedCurrent;
- unearnedIncome.otherUnearnedLast = refClient.otherUnearnedLast;
-
- expenditure.mortgageCurrent = refClient.mortgageCurrent;
- expenditure.mortgageLast = refClient.mortgageLast;
- expenditure.rentCurrent = refClient.rentCurrent;
- expenditure.rentLast = refClient.rentLast;
- expenditure.schoolingCurrent = refClient.schoolingCurrent;
- expenditure.schoolingLast = refClient.schoolingLast;
- expenditure.membershipsCurrent = refClient.membershipsCurrent;
- expenditure.membershipsLast = refClient.membershipsLast;
- expenditure.otherExpenditureCurrent = refClient.otherExpenditureCurrent;
- expenditure.otherExpenditureLast = refClient.otherExpenditureLast;
-
- expenditure.interestCurrent = refClient.interestCurrent;
- expenditure.interestLast = refClient.interestLast;
- expenditure.principalCurrent = refClient.principalCurrent;
- expenditure.principalLast = refClient.principalLast;
- expenditure.otherPrefFinanceCurrent = refClient.otherPrefFinanceCurrent;
- expenditure.otherPrefFinanceLast = refClient.otherPrefFinanceLast;
-
- assets.cashDepositsCurrent = refClient.cashDepositsCurrent;
- assets.cashDepositsLast = refClient.cashDepositsLast;
- assets.investmentsCurrent = refClient.investmentsCurrent;
- assets.investmentsLast = refClient.investmentsLast;
- assets.otherLiquidCurrent = refClient.otherLiquidCurrent;
- assets.otherLiquidLast = refClient.otherLiquidLast;
- assets.netBusinessInterestCurrent = refClient.netBusinessInterestCurrent;
- assets.netBusinessInterestLast = refClient.netBusinessInterestLast;
- assets.personalPropertiesCurrent = refClient.personalPropertiesCurrent;
- assets.personalPropertiesLast = refClient.personalPropertiesLast;
- assets.realEstateCurrent = refClient.realEstateCurrent;
- assets.realEstateLast = refClient.realEstateLast;
- assets.otherNonLiquidCurrent = refClient.otherNonLiquidCurrent;
- assets.otherNonLiquidLast = refClient.otherNonLiquidLast;
-
- liabilities.personalLoansCurrent = refClient.personalLoansCurrent;
- liabilities.personalLoansLast = refClient.personalLoansLast;
- liabilities.mortgagesCurrent = refClient.mortgagesCurrent;
- liabilities.mortgagesLast = refClient.mortgagesLast;
- liabilities.marginAccountCurrent = refClient.marginAccountCurrent;
- liabilities.marginAccountLast = refClient.marginAccountLast;
- liabilities.loanGuaranteesCurrent = refClient.loanGuaranteesCurrent;
- liabilities.loanGuaranteesLast = refClient.loanGuaranteesLast;
- liabilities.bankingFacilityCurrent = refClient.bankingFacilityCurrent;
- liabilities.bankingFacilityLast = refClient.bankingFacilityLast;
- liabilities.prefFinancePrincipalCurrent = refClient.prefFinancePrincipalCurrent;
- liabilities.prefFinancePrincipalLast = refClient.prefFinancePrincipalLast;
-
- liabilities.prefFinanceOtherCurrent = refClient.prefFinanceOtherCurrent;
- liabilities.prefFinanceOtherLast = refClient.prefFinanceOtherLast;
-
-
- //totalEarnedCurrent = refClient.totalEarnedCurrent;
- //totalEarnedLast = refClient.totalEarnedLast;
-
- // Set consultantId for Autocomplete
- const selectedConsultant = consultantComboList.find(
- (option) => option.id === refClient.consultantId
- );
- setValue("consultantId", selectedConsultant || null);
-
- setDob(dayjs(getDateString(refClient.dob)));
- }
- }, [refClient, consultantComboList]);
-
- useEffect(() => {
- if (!isObjEmpty(refClient)) {
- setOnReady(true);
- } else if (isNewRecord) {
- setOnReady(true);
- setIsEditing(true);
- }
- }, [refClient]);
-
- useEffect(() => {
- if (isCollectData) {
- const values = getValues();
- const formErrors = {};
-
- if (isStringEmptyAfterTrim(values.lastname)) {
- formErrors.lastname = 'Last Name is required';
- }
-
- setErrors(formErrors);
- if (Object.keys(formErrors).length === 0) {
- let data = {};
- data["id"] = isNewRecord ? params.id : refClientDetail.id;
- data["lastname"] = values.lastname;
- data["firstname"] = values.firstname;
- data["email"] = values.email;
- data["phone1"] = values.phone1;
- data["phone1Code"] = values.phone1Code;
- data["phone2"] = values.phone2;
- data["remarks"] = values.remarks;
- data["caseManagerId"] = 1;
- data["consultantId"] = values.consultantId ? values.consultantId.id : null;
- data["dob"] = dob === null ? null : dayjs(dob).format('YYYY-MM-DD');
- data["crAddressRoom"] = values.crAddressRoom;
- data["crAddressFloor"] = values.crAddressFloor;
- data["crAddressBlock"] = values.crAddressBlock;
- data["crAddressBuilding"] = values.crAddressBuilding;
- data["crAddressStreet"] = values.crAddressStreet;
- data["crAddressArea"] = values.crAddressArea;
- data["crAddressCity"] = values.crAddressCity;
- data["crAddressCountry"] = values.crAddressCountry;
- data["crAddressPostalCode"] = values.crAddressPostalCode;
- data["corAddressRoom"] = values.corAddressRoom;
- data["corAddressFloor"] = values.corAddressFloor;
- data["corAddressBlock"] = values.corAddressBlock;
- data["corAddressBuilding"] = values.corAddressBuilding;
- data["corAddressStreet"] = values.corAddressStreet;
- data["corAddressArea"] = values.corAddressArea;
- data["corAddressCity"] = values.corAddressCity;
- data["corAddressCountry"] = values.corAddressCountry;
- data["corAddressPostalCode"] = values.corAddressPostalCode;
-
- data = {
- ...data, // Keep all existing header fields
- ...earnedIncome,
- ...unearnedIncome,
- ...expenditure,
- ...assets,
- ...liabilities,
- totalEarnedCurrent,
- totalEarnedLast,
- totalUnearnedCurrent,
- totalUnearnedLast,
- totalAssetsCurrent,
- totalAssetsLast,
- totalIncomeCurrent,
- totalIncomeLast,
- totalExpenditureCurrent,
- totalExpenditureLast,
- totalLiquidAssetCurrent,
- totalLiquidAssetLast,
- totalNonLiquidAssetCurrent,
- totalNonLiquidAssetLast,
- totalLiabilitiesCurrent,
- totalLiabilitiesLast,
- };
-
- setClientDetail(data);
- } else if (isCollectData) {
- setUserConfirm(false);
- setIsCollectData(false);
- }
- }
- }, [isCollectData]);
-
- useEffect(() => {
- if (userConfirm) {
- postClient();
- }
- setUserConfirm(false);
- }, [clientDetail]);
-
- const submitData = () => {
- setIsCollectData(!isCollectData);
- setUserConfirm(true);
- };
-
- const updateIsEdit = () => {
- setIsEditing(!isEditing);
- };
-
- function postClient() {
- setIsUploading(true);
- const temp = trimDataBeforePost(clientDetail);
- axios.post(`${apiPath}${POST_CLIENT_PATH}`, temp)
- .then((response) => {
- if (response.status === 200) {
- notifySaveSuccess();
- if (isNewRecord) {
- setIsUploading(false);
- navigate('/client');
- } else {
- setIsUploading(false);
- getClientDetail(params.id);
- setIsEditing(!isEditing);
- }
- setIsCollectData(!isCollectData);
- }
- })
- .catch(error => {
- if (error.response.status === 422) {
- const formErrors = {};
- formErrors.subDivision = error.response.data.error;
- setErrors(formErrors);
- }
- console.log(error);
- setIsUploading(false);
- return false;
- });
- }
-
- return (
- !onReady ?
- <LoadingComponent />
- :
- <MainCard content={false} sx={{ width: CARD_MAX_WIDTH }}>
- <Typography variant="h5" sx={{ mt: 3, ml: 3, mb: 1 }}>
- Information
- </Typography>
- <form>
- <Grid container>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ mt: 1, ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"flex-start"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, mt: 1, display: 'flex', alignItems: 'flex-start' }}>
- <Typography variant="lionerSize" component="span">
- Client Code: <Typography sx={{ color: GENERAL_RED_COLOR }} component="span">*</Typography>
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={6.5}>
- <TextField
- fullWidth
- {...register("clientCode", { value: refClient.clientCode })}
- id='clientCode'
- required
- inputProps={{ maxLength: 255, style: { fontSize: '1.1rem' } }}
- InputProps={{ style: { minHeight: '42.5px', maxHeight: '50vh' } }}
- multiline
- maxRows={3}
- error={!!errors.lastname}
- helperText={errors.lastname}
- disabled
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ mt: 1, ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"flex-start"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, mt: 1, display: 'flex', alignItems: 'flex-start' }}>
- <Typography variant="lionerSize" component="span">
- Last Name(Surname/Family Name): <Typography sx={{ color: GENERAL_RED_COLOR }} component="span">*</Typography>
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={6.5}>
- <TextField
- fullWidth
- {...register("lastname", { value: refClient.lastname })}
- id='lastname'
- required
- inputProps={{ maxLength: 255, style: { fontSize: '1.1rem' } }}
- InputProps={{ style: { minHeight: '42.5px', maxHeight: '50vh' } }}
- multiline
- maxRows={3}
- error={!!errors.lastname}
- helperText={errors.lastname}
- disabled={!isEditing}
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ mt: 1, ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"flex-start"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, mt: 1, display: 'flex', alignItems: 'flex-start' }}>
- <Typography variant="lionerSize" component="span">
- First Name(Given Name/Forename):
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={6.5}>
- <TextField
- fullWidth
- {...register("firstname", { value: refClient.firstname })}
- id='firstname'
- required
- inputProps={{ maxLength: 255, style: { fontSize: '1.1rem' } }}
- InputProps={{ style: { minHeight: '42.5px', maxHeight: '50vh' } }}
- multiline
- maxRows={3}
- disabled={!isEditing}
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"center"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, display: 'flex', alignItems: 'center' }}>
- <Typography variant="lionerSize" component="span">
- Date of Birth:
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={7}>
- <LocalizationProvider dateAdapter={AdapterDayjs}>
- <DemoItem components={['DatePicker']}>
- <DatePicker
- id="dob"
- size="small"
- required
- value={dob === null ? null : dayjs(dob)}
- onChange={(newValue) => setDob(newValue)}
- format="DD/MM/YYYY"
- onError={(newError) => setDobError(newError)}
- slotProps={{
- field: { clearable: true },
- textField: {
- error: !!errors.dob || dobError,
- helperText: dobError ? dobErrorMessage : errors.dob,
- },
- }}
- disabled={!isEditing}
- />
- </DemoItem>
- </LocalizationProvider>
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"center"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, display: 'flex', alignItems: 'center' }}>
- <Typography variant="lionerSize" component="span">
- Email Address:
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={6.5}>
- <TextField
- fullWidth
- inputProps={{ maxLength: 50 }}
- size="small"
- {...register("email", { value: refClient.email })}
- id='email'
- disabled={!isEditing}
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"center"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, display: 'flex', alignItems: 'center' }}>
- <Typography variant="lionerSize" component="span">
- Phone Number:
- </Typography>
- </Grid>
- <Grid item xs={1} sm={1} md={1} lg={1.5}>
- <TextField
- fullWidth
- inputProps={{ maxLength: 5 }}
- size="small"
- {...register("phone1Code", { value: refClient.phote1Code })}
- id='phone1Code'
- disabled={!isEditing}
- autoComplete="off"
- />
- </Grid>
- <Grid item xs={0.1} sm={0.1} md={0.1} lg={0.15}>
- </Grid>
- <Grid item xs={6} sm={6} md={6} lg={5}>
- <TextField
- fullWidth
- inputProps={{ maxLength: 20 }}
- size="small"
- {...register("phone1", { value: refClient.phone1 })}
- id='phone1'
- disabled={!isEditing}
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"flex-start"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, display: 'flex', alignItems: 'center' }}>
- <Typography variant="lionerSize" component="span">
- Case Manager: <Typography sx={{ color: GENERAL_RED_COLOR }} component="span"></Typography>
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={6.5}>
- <TextField
- fullWidth
- inputProps={{ maxLength: 50 }}
- size="small"
- {...register("cm", { value: "N/A" })}
- id='cm'
- disabled
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"flex-start"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, display: 'flex', alignItems: 'center' }}>
- <Typography variant="lionerSize" component="span">
- Consultant: <Typography sx={{ color: GENERAL_RED_COLOR }} component="span"></Typography>
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={6.5}>
- <Autocomplete
- disablePortal
- id="consultant-combo-box"
- options={consultantComboList}
- getOptionLabel={(option) => option.name || ""}
- isOptionEqualToValue={(option, value) => option.id === value.id}
- value={selectedConsultant}
- onChange={(e, v) => {
- setSelectedConsultant(v);
- setValue('consultantId', v); }
- }
- renderInput={(params) => (
- <TextField
- {...params}
- label="Consultant"
- name="consultant"
- />
- )}
- disabled={!isEditing}
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"center"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, display: 'flex', alignItems: 'center' }}>
- <Typography variant="lionerSize" component="span">
- Rs. Address(Room):
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={6.5}>
- <TextField
- fullWidth
- inputProps={{ maxLength: 50 }}
- size="small"
- {...register("crAddressRoom", { value: refClient.crAddressRoom })}
- id='crAddressRoom'
- disabled={!isEditing}
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"center"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, display: 'flex', alignItems: 'center' }}>
- <Typography variant="lionerSize" component="span">
- Rs. Address(Floor):
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={6.5}>
- <TextField
- fullWidth
- inputProps={{ maxLength: 50 }}
- size="small"
- {...register("crAddressFloor", { value: refClient.crAddressFloor })}
- id='crAddressFloor'
- disabled={!isEditing}
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"center"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, display: 'flex', alignItems: 'center' }}>
- <Typography variant="lionerSize" component="span">
- Rs. Address(Block):
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={6.5}>
- <TextField
- fullWidth
- inputProps={{ maxLength: 50 }}
- size="small"
- {...register("crAddressBlock", { value: refClient.crAddressBlock })}
- id='crAddressBlock'
- disabled={!isEditing}
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"center"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, display: 'flex', alignItems: 'center' }}>
- <Typography variant="lionerSize" component="span">
- Rs. Address(Buliding):
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={6.5}>
- <TextField
- fullWidth
- inputProps={{ maxLength: 50 }}
- size="small"
- {...register("crAddressBuilding", { value: refClient.crAddressBuilding })}
- id='crAddressBuilding'
- disabled={!isEditing}
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"center"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, display: 'flex', alignItems: 'center' }}>
- <Typography variant="lionerSize" component="span">
- Rs. Address(Street):
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={6.5}>
- <TextField
- fullWidth
- inputProps={{ maxLength: 50 }}
- size="small"
- {...register("crAddressStreet", { value: refClient.crAddressStreet })}
- id='crAddressStreet'
- disabled={!isEditing}
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"center"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, display: 'flex', alignItems: 'center' }}>
- <Typography variant="lionerSize" component="span">
- Rs. Address(Area):
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={6.5}>
- <TextField
- fullWidth
- inputProps={{ maxLength: 50 }}
- size="small"
- {...register("crAddressArea", { value: refClient.crAddressArea })}
- id='crAddressArea'
- disabled={!isEditing}
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"center"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, display: 'flex', alignItems: 'center' }}>
- <Typography variant="lionerSize" component="span">
- Rs. Address(City):
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={6.5}>
- <TextField
- fullWidth
- inputProps={{ maxLength: 50 }}
- size="small"
- {...register("crAddressCity", { value: refClient.crAddressCity })}
- id='crAddressCity'
- disabled={!isEditing}
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"center"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, display: 'flex', alignItems: 'center' }}>
- <Typography variant="lionerSize" component="span">
- Rs. Address(Country):
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={6.5}>
- <TextField
- fullWidth
- inputProps={{ maxLength: 50 }}
- size="small"
- {...register("crAddressCountry", { value: refClient.crAddressCountry })}
- id='crAddressCountry'
- disabled={!isEditing}
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"center"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, display: 'flex', alignItems: 'center' }}>
- <Typography variant="lionerSize" component="span">
- Rs. Address(Postal Code):
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={6.5}>
- <TextField
- fullWidth
- inputProps={{ maxLength: 50 }}
- size="small"
- {...register("crAddressPostalCode", { value: refClient.crAddressPostalCode })}
- id='crAddressPostalCode'
- disabled={!isEditing}
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"center"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, display: 'flex', alignItems: 'center' }}>
- <Typography variant="lionerSize" component="span">
- Corr. Address(Room):
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={6.5}>
- <TextField
- fullWidth
- inputProps={{ maxLength: 50 }}
- size="small"
- {...register("corAddressRoom", { value: refClient.corAddressRoom })}
- id='corAddressRoom'
- disabled={!isEditing}
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"center"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, display: 'flex', alignItems: 'center' }}>
- <Typography variant="lionerSize" component="span">
- Corr. Address(Floor):
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={6.5}>
- <TextField
- fullWidth
- inputProps={{ maxLength: 50 }}
- size="small"
- {...register("corAddressFloor", { value: refClient.corAddressFloor })}
- id='corAddressFloor'
- disabled={!isEditing}
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"center"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, display: 'flex', alignItems: 'center' }}>
- <Typography variant="lionerSize" component="span">
- Corr. Address(Block):
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={6.5}>
- <TextField
- fullWidth
- inputProps={{ maxLength: 50 }}
- size="small"
- {...register("corAddressBlock", { value: refClient.corAddressBlock })}
- id='corAddressBlock'
- disabled={!isEditing}
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"center"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, display: 'flex', alignItems: 'center' }}>
- <Typography variant="lionerSize" component="span">
- Corr. Address(Buliding):
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={6.5}>
- <TextField
- fullWidth
- inputProps={{ maxLength: 50 }}
- size="small"
- {...register("corAddressBuilding", { value: refClient.corAddressBuilding })}
- id='corAddressBuilding'
- disabled={!isEditing}
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"center"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, display: 'flex', alignItems: 'center' }}>
- <Typography variant="lionerSize" component="span">
- Corr. Address(Street):
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={6.5}>
- <TextField
- fullWidth
- inputProps={{ maxLength: 50 }}
- size="small"
- {...register("corAddressStreet", { value: refClient.corAddressStreet })}
- id='corAddressStreet'
- disabled={!isEditing}
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"center"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, display: 'flex', alignItems: 'center' }}>
- <Typography variant="lionerSize" component="span">
- Corr. Address(Area):
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={6.5}>
- <TextField
- fullWidth
- inputProps={{ maxLength: 50 }}
- size="small"
- {...register("corAddressArea", { value: refClient.corAddressArea })}
- id='corAddressArea'
- disabled={!isEditing}
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"center"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, display: 'flex', alignItems: 'center' }}>
- <Typography variant="lionerSize" component="span">
- Corr. Address(City):
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={6.5}>
- <TextField
- fullWidth
- inputProps={{ maxLength: 50 }}
- size="small"
- {...register("corAddressCity", { value: refClient.corAddressCity })}
- id='corAddressCity'
- disabled={!isEditing}
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"center"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, display: 'flex', alignItems: 'center' }}>
- <Typography variant="lionerSize" component="span">
- Corr. Address(Country):
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={6.5}>
- <TextField
- fullWidth
- inputProps={{ maxLength: 50 }}
- size="small"
- {...register("corAddressCountry", { value: refClient.corAddressCountry })}
- id='corAddressCountry'
- disabled={!isEditing}
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- <Grid container alignItems={"center"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, display: 'flex', alignItems: 'center' }}>
- <Typography variant="lionerSize" component="span">
- Corr. Address(Postal Code):
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={6.5}>
- <TextField
- fullWidth
- inputProps={{ maxLength: 50 }}
- size="small"
- {...register("corAddressPostalCode", { value: refClient.corAddressPostalCode })}
- id='corAddressPostalCode'
- disabled={!isEditing}
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3, mt: 1 }}>
- <Grid container alignItems={"flex-start"}>
- <Grid item xs={4} sm={4} md={4} lg={4} sx={{ ml: 3, mr: 3, mt: 1, display: 'flex', alignItems: 'flex-start' }}>
- <Typography variant="lionerSize" component="span">
- Remarks:
- </Typography>
- </Grid>
- <Grid item xs={7} sm={7} md={7} lg={7}>
- <TextField
- fullWidth
- {...register("remarks", { value: refClient.remarks })}
- id='remarks'
- required
- disabled={!isEditing}
- inputProps={{ maxLength: 500, style: { fontSize: '1.1rem' } }}
- InputProps={{ style: { minHeight: '42.5px', maxHeight: '50vh' } }}
- multiline
- maxRows={10}
- autoComplete="off"
- />
- </Grid>
- </Grid>
- </Grid>
- <Grid item xs={12} sm={12} md={12} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }}>
- </Grid>
- <Grid>
- {/* ======================================================================= */}
- {/* --- START: EARNED INCOME 薪酬收入 (Image 1) --- */}
- {/* ======================================================================= */}
- <Grid item xs={12}>
- <Typography variant="h5" sx={{ mt: 3, mb: 1, px: 2, backgroundColor: '#d0d0d0', py: 1, borderRadius: 1 }}>
- EARNED INCOME 薪酬收入
- </Typography>
- <TableContainer component={Paper} elevation={1}>
- <Table size="small" aria-label="earned income table">
- <TableHead sx={{ backgroundColor: '#f0f0f0' }}>
- <TableRow>
- <TableCell sx={{ fontWeight: 'bold', width: '40%' }}></TableCell>
- <TableCell align="center" sx={{ fontWeight: 'bold', width: '30%' }}>Current Year 本年度</TableCell>
- <TableCell align="center" sx={{ fontWeight: 'bold', width: '30%' }}>Last Year 上年度</TableCell>
- </TableRow>
- </TableHead>
- <TableBody>
- {/* Salary */}
- <TableRow>
- <TableCell>Salary 薪酬</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(earnedIncome.salaryCurrent)} onChange={(e) => handleEarnedIncomeChange('salaryCurrent', cleanNumberForState(cleanNumberForState(e.target.value)))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(earnedIncome.salaryLast)} onChange={(e) => handleEarnedIncomeChange('salaryLast', cleanNumberForState(cleanNumberForState(e.target.value)))}
- />
- </TableCell>
- </TableRow>
- {/* Bonus */}
- <TableRow>
- <TableCell>Bonus 花紅</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(earnedIncome.bonusCurrent)} onChange={(e) => handleEarnedIncomeChange('bonusCurrent', cleanNumberForState(cleanNumberForState(e.target.value)))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(earnedIncome.bonusLast)} onChange={(e) => handleEarnedIncomeChange('bonusLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Other */}
- <TableRow>
- <TableCell>Other 其他</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(earnedIncome.otherEarnedCurrent)} onChange={(e) => handleEarnedIncomeChange('otherEarnedCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(earnedIncome.otherEarnedLast)} onChange={(e) => handleEarnedIncomeChange('otherEarnedLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Total Earned Income */}
- <TableRow sx={{ '& td': { fontWeight: 'bold', backgroundColor: '#e0e0e0' } }}>
- <TableCell>Total Earned Income 薪酬收入總額</TableCell>
- <TableCell align="right">
- <TextField fullWidth variant="filled" size="small" readOnly
- value={formatNumberForDisplay(totalEarnedCurrent.toFixed(0))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField fullWidth variant="filled" size="small" readOnly
- value={formatNumberForDisplay(totalEarnedLast.toFixed(0))}
- />
- </TableCell>
- </TableRow>
- </TableBody>
- </Table>
- </TableContainer>
- </Grid>
- {/* --- END: EARNED INCOME --- */}
-
-
- {/* ======================================================================= */}
- {/* --- START: UNEARNED INCOME 非薪酬收入 (Image 2 - UPDATED) --- */}
- {/* ======================================================================= */}
- <Grid item xs={12}>
- <Typography variant="h5" sx={{ mt: 5, mb: 1, px: 2, backgroundColor: '#d0d0d0', py: 1, borderRadius: 1 }}>
- UNEARNED INCOME 非薪酬收入
- </Typography>
- <TableContainer component={Paper} elevation={1}>
- <Table size="small" aria-label="unearned income table">
- <TableHead sx={{ backgroundColor: '#f0f0f0' }}>
- <TableRow>
- <TableCell sx={{ fontWeight: 'bold', width: '40%' }}></TableCell>
- <TableCell align="center" sx={{ fontWeight: 'bold', width: '30%' }}>Current Year 本年度</TableCell>
- <TableCell align="center" sx={{ fontWeight: 'bold', width: '30%' }}>Last Year 上年度</TableCell>
- </TableRow>
- </TableHead>
- <TableBody>
- {/* Company Interest */}
- <TableRow>
- <TableCell>Company Interest 公司收益</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(unearnedIncome.companyInterestCurrent)} onChange={(e) => handleUnearnedIncomeChange('companyInterestCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(unearnedIncome.companyInterestLast)} onChange={(e) => handleUnearnedIncomeChange('companyInterestLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Dividends */}
- <TableRow>
- <TableCell>Dividends 股息</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(unearnedIncome.dividendsCurrent)} onChange={(e) => handleUnearnedIncomeChange('dividendsCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(unearnedIncome.dividendsLast)} onChange={(e) => handleUnearnedIncomeChange('dividendsLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Rentals */}
- <TableRow>
- <TableCell>Rentals 租金</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(unearnedIncome.rentalsCurrent)} onChange={(e) => handleUnearnedIncomeChange('rentalsCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(unearnedIncome.rentalsLast)} onChange={(e) => handleUnearnedIncomeChange('rentalsLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Investment Income */}
- <TableRow>
- <TableCell>Investment Income 投資收益</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(unearnedIncome.investmentIncomeCurrent)} onChange={(e) => handleUnearnedIncomeChange('investmentIncomeCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(unearnedIncome.investmentIncomeLast)} onChange={(e) => handleUnearnedIncomeChange('investmentIncomeLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Other Unearned */}
- <TableRow>
- <TableCell>Other 其他</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(unearnedIncome.otherUnearnedCurrent)} onChange={(e) => handleUnearnedIncomeChange('otherUnearnedCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(unearnedIncome.otherUnearnedLast)} onChange={(e) => handleUnearnedIncomeChange('otherUnearnedLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Total Unearned Income */}
- <TableRow sx={{ '& td': { fontWeight: 'bold', backgroundColor: '#e0e0e0' } }}>
- <TableCell>Total Unearned Income 非薪酬收入總額</TableCell>
- <TableCell align="right">
- <TextField fullWidth variant="filled" size="small" readOnly
- value={formatNumberForDisplay(totalUnearnedCurrent.toFixed(0))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField fullWidth variant="filled" size="small" readOnly
- value={formatNumberForDisplay(totalUnearnedLast.toFixed(0))}
- />
- </TableCell>
- </TableRow>
- {/* Total Income */}
- <TableRow sx={{ '& td': { fontWeight: 'bold', backgroundColor: '#d0d0d0' } }}>
- <TableCell>Total Income 收入總額</TableCell>
- <TableCell align="right">
- <TextField fullWidth variant="filled" size="small" readOnly
- value={formatNumberForDisplay(totalIncomeCurrent.toFixed(0))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField fullWidth variant="filled" size="small" readOnly
- value={formatNumberForDisplay(totalIncomeLast.toFixed(0))}
- />
- </TableCell>
- </TableRow>
- </TableBody>
- </Table>
- </TableContainer>
- </Grid>
- {/* --- END: UNEARNED INCOME --- */}
-
-
- {/* ======================================================================= */}
- {/* --- START: EXPENDITURE STATEMENT 開支報表 (Image 3) --- */}
- {/* ======================================================================= */}
- <Grid item xs={12}>
- <Typography variant="h5" sx={{ mt: 5, mb: 1, px: 2, backgroundColor: '#d0d0d0', py: 1, borderRadius: 1 }}>
- Expenditure Statement 開支報表
- </Typography>
- <TableContainer component={Paper} elevation={1}>
- <Table size="small" aria-label="expenditure statement table">
- <TableHead sx={{ backgroundColor: '#f0f0f0' }}>
- <TableRow>
- <TableCell sx={{ fontWeight: 'bold', width: '40%' }}></TableCell>
- <TableCell align="center" sx={{ fontWeight: 'bold', width: '30%' }}>Current Year 本年度</TableCell>
- <TableCell align="center" sx={{ fontWeight: 'bold', width: '30%' }}>Last Year 上年度</TableCell>
- </TableRow>
- </TableHead>
- <TableBody>
- {/* Mortgage */}
- <TableRow>
- <TableCell>Mortgage 按揭</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(expenditure.mortgageCurrent)} onChange={(e) => handleExpenditureChange('mortgageCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(expenditure.mortgageLast)} onChange={(e) => handleExpenditureChange('mortgageLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Rent */}
- <TableRow>
- <TableCell>Rent 租金</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(expenditure.rentCurrent)} onChange={(e) => handleExpenditureChange('rentCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(expenditure.rentLast)} onChange={(e) => handleExpenditureChange('rentLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Schooling for Children */}
- <TableRow>
- <TableCell>Schooling for Children 子女教育</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(expenditure.schoolingCurrent)} onChange={(e) => handleExpenditureChange('schoolingCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(expenditure.schoolingLast)} onChange={(e) => handleExpenditureChange('schoolingLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Memberships */}
- <TableRow>
- <TableCell>Memberships 會籍</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(expenditure.membershipsCurrent)} onChange={(e) => handleExpenditureChange('membershipsCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(expenditure.membershipsLast)} onChange={(e) => handleExpenditureChange('membershipsLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Other Expenditure */}
- <TableRow>
- <TableCell>Other 其他</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(expenditure.otherExpenditureCurrent)} onChange={(e) => handleExpenditureChange('otherExpenditureCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(expenditure.otherExpenditureLast)} onChange={(e) => handleExpenditureChange('otherExpenditureLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Interest */}
- <TableRow>
- <TableCell>Interest 利息還款額</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(expenditure.interestCurrent)} onChange={(e) => handleExpenditureChange('interestCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(expenditure.interestLast)} onChange={(e) => handleExpenditureChange('interestLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Principal */}
- <TableRow>
- <TableCell>Principal 本金還款額</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(expenditure.principalCurrent)} onChange={(e) => handleExpenditureChange('principalCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(expenditure.principalLast)} onChange={(e) => handleExpenditureChange('principalLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Other */}
- <TableRow>
- <TableCell>Other Loan 其他</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(expenditure.otherPrefFinanceCurrent)} onChange={(e) => handleExpenditureChange('otherPrefFinanceCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(expenditure.otherPrefFinanceLast)} onChange={(e) => handleExpenditureChange('otherPrefFinanceLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Empty Rows (from your image) - you can remove these if not strictly needed for layout */}
- <TableRow><TableCell></TableCell><TableCell></TableCell><TableCell></TableCell></TableRow>
- <TableRow><TableCell></TableCell><TableCell></TableCell><TableCell></TableCell></TableRow>
-
- {/* Total Expenditure */}
- <TableRow sx={{ '& td': { fontWeight: 'bold', backgroundColor: '#e0e0e0' } }}>
- <TableCell>Total Expenditure 開支總額</TableCell>
- <TableCell align="right">
- <TextField fullWidth variant="filled" size="small" readOnly
- value={formatNumberForDisplay(totalExpenditureCurrent.toFixed(0))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField fullWidth variant="filled" size="small" readOnly
- value={formatNumberForDisplay(totalExpenditureLast.toFixed(0))}
- />
- </TableCell>
- </TableRow>
- </TableBody>
- </Table>
- </TableContainer>
- </Grid>
- {/* --- END: EXPENDITURE STATEMENT --- */}
-
-
- {/* ======================================================================= */}
- {/* --- START: LIQUID & NON-LIQUID ASSET 流動資產 & 非流動資產 (Image 4) --- */}
- {/* ======================================================================= */}
- <Grid item xs={12}>
- <Typography variant="h5" sx={{ mt: 5, mb: 1, px: 2, backgroundColor: '#d0d0d0', py: 1, borderRadius: 1 }}>
- Liquid Asset 流動資產
- </Typography>
- <TableContainer component={Paper} elevation={1}>
- <Table size="small" aria-label="liquid asset table">
- <TableHead sx={{ backgroundColor: '#f0f0f0' }}>
- <TableRow>
- <TableCell sx={{ fontWeight: 'bold', width: '40%' }}></TableCell>
- <TableCell align="center" sx={{ fontWeight: 'bold', width: '30%' }}>Current Year 本年度</TableCell>
- <TableCell align="center" sx={{ fontWeight: 'bold', width: '30%' }}>Last Year 上年度</TableCell>
- </TableRow>
- </TableHead>
- <TableBody>
- {/* Cash and Fixed Deposits */}
- <TableRow>
- <TableCell>Cash and Fixed Deposits 現金與定期存款</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(assets.cashDepositsCurrent)} onChange={(e) => handleAssetsChange('cashDepositsCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(assets.cashDepositsLast)} onChange={(e) => handleAssetsChange('cashDepositsLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Investments */}
- <TableRow>
- <TableCell>Investments 投資</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(assets.investmentsCurrent)} onChange={(e) => handleAssetsChange('investmentsCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(assets.investmentsLast)} onChange={(e) => handleAssetsChange('investmentsLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Other Liquid */}
- <TableRow>
- <TableCell>Other 其他</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(assets.otherLiquidCurrent)} onChange={(e) => handleAssetsChange('otherLiquidCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(assets.otherLiquidLast)} onChange={(e) => handleAssetsChange('otherLiquidLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Total Liquid Asset */}
- <TableRow sx={{ '& td': { fontWeight: 'bold', backgroundColor: '#e0e0e0' } }}>
- <TableCell>Total Liquid Asset 流動資產總額</TableCell>
- <TableCell align="right">
- <TextField fullWidth variant="filled" size="small" readOnly
- value={formatNumberForDisplay(totalLiquidAssetCurrent.toFixed(0))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField fullWidth variant="filled" size="small" readOnly
- value={formatNumberForDisplay(totalLiquidAssetLast.toFixed(0))}
- />
- </TableCell>
- </TableRow>
- </TableBody>
- </Table>
- </TableContainer>
-
- <Typography variant="h5" sx={{ mt: 3, mb: 1, px: 2, backgroundColor: '#d0d0d0', py: 1, borderRadius: 1 }}>
- Non-Liquid Asset 非流動資產
- </Typography>
- <TableContainer component={Paper} elevation={1}>
- <Table size="small" aria-label="non-liquid asset table">
- <TableHead sx={{ backgroundColor: '#f0f0f0' }}>
- <TableRow>
- <TableCell sx={{ fontWeight: 'bold', width: '40%' }}></TableCell>
- <TableCell align="center" sx={{ fontWeight: 'bold', width: '30%' }}>Current Year 本年度</TableCell>
- <TableCell align="center" sx={{ fontWeight: 'bold', width: '30%' }}>Last Year 上年度</TableCell>
- </TableRow>
- </TableHead>
- <TableBody>
- {/* Net Business Interest */}
- <TableRow>
- <TableCell>Net Business Interest 淨商業利益</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(assets.netBusinessInterestCurrent)} onChange={(e) => handleAssetsChange('netBusinessInterestCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(assets.netBusinessInterestLast)} onChange={(e) => handleAssetsChange('netBusinessInterestLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Personal Properties */}
- <TableRow>
- <TableCell>Personal Properties 個人財產</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(assets.personalPropertiesCurrent)} onChange={(e) => handleAssetsChange('personalPropertiesCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(assets.personalPropertiesLast)} onChange={(e) => handleAssetsChange('personalPropertiesLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Real Estate - NEW ROW */}
- <TableRow>
- <TableCell>Real Estate 房地產</TableCell>
- <TableCell align="right">
- <TextField
- onFocus={handleFocus}
- disabled={!isEditing}
- fullWidth
- variant="outlined"
- size="small"
- inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(assets.realEstateCurrent)}
- onChange={(e) => handleAssetsChange('realEstateCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField
- onFocus={handleFocus}
- disabled={!isEditing}
- fullWidth
- variant="outlined"
- size="small"
- inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(assets.realEstateLast)}
- onChange={(e) => handleAssetsChange('realEstateLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Other Non-Liquid */}
- <TableRow>
- <TableCell>Other 其他</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(assets.otherNonLiquidCurrent)} onChange={(e) => handleAssetsChange('otherNonLiquidCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(assets.otherNonLiquidLast)} onChange={(e) => handleAssetsChange('otherNonLiquidLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Total Non-Liquid Asset */}
- <TableRow sx={{ '& td': { fontWeight: 'bold', backgroundColor: '#e0e0e0' } }}>
- <TableCell>Total Non-Liquid Asset 非流動資產總額</TableCell>
- <TableCell align="right">
- <TextField fullWidth variant="filled" size="small" readOnly
- value={formatNumberForDisplay(totalNonLiquidAssetCurrent.toFixed(0))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField fullWidth variant="filled" size="small" readOnly
- value={formatNumberForDisplay(totalNonLiquidAssetLast.toFixed(0))}
- />
- </TableCell>
- </TableRow>
- {/* Total Assets */}
- <TableRow sx={{ '& td': { fontWeight: 'bold', backgroundColor: '#d0d0d0' } }}>
- <TableCell>Total Assets 資產總額</TableCell>
- <TableCell align="right">
- <TextField fullWidth variant="filled" size="small" readOnly
- value={formatNumberForDisplay(totalAssetsCurrent.toFixed(0))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField fullWidth variant="filled" size="small" readOnly
- value={formatNumberForDisplay(totalAssetsLast.toFixed(0))}
- />
- </TableCell>
- </TableRow>
- </TableBody>
- </Table>
- </TableContainer>
- </Grid>
- {/* --- END: LIQUID & NON-LIQUID ASSET --- */}
-
-
- {/* ======================================================================= */}
- {/* --- START: LIABILITIES 負債 (Image 5) --- */}
- {/* ======================================================================= */}
- <Grid item xs={12}>
- <Typography variant="h5" sx={{ mt: 5, mb: 1, px: 2, backgroundColor: '#d0d0d0', py: 1, borderRadius: 1 }}>
- Liabilities 負債
- </Typography>
- <TableContainer component={Paper} elevation={1}>
- <Table size="small" aria-label="liabilities table">
- <TableHead sx={{ backgroundColor: '#f0f0f0' }}>
- <TableRow>
- <TableCell sx={{ fontWeight: 'bold', width: '40%' }}></TableCell>
- <TableCell align="center" sx={{ fontWeight: 'bold', width: '30%' }}>Current Year 本年度</TableCell>
- <TableCell align="center" sx={{ fontWeight: 'bold', width: '30%' }}>Last Year 上年度</TableCell>
- </TableRow>
- </TableHead>
- <TableBody>
- {/* Personal Loans */}
- <TableRow>
- <TableCell>Personal Loans 個人債務</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(liabilities.personalLoansCurrent)} onChange={(e) => handleLiabilitiesChange('personalLoansCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(liabilities.personalLoansLast)} onChange={(e) => handleLiabilitiesChange('personalLoansLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Mortgages */}
- <TableRow>
- <TableCell>Mortgages 按揭</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(liabilities.mortgagesCurrent)} onChange={(e) => handleLiabilitiesChange('mortgagesCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(liabilities.mortgagesLast)} onChange={(e) => handleLiabilitiesChange('mortgagesLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Margin Account */}
- <TableRow>
- <TableCell>Margin Account 保證金賬戶</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(liabilities.marginAccountCurrent)} onChange={(e) => handleLiabilitiesChange('marginAccountCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(liabilities.marginAccountLast)} onChange={(e) => handleLiabilitiesChange('marginAccountLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Loan Guarantees */}
- <TableRow>
- <TableCell>Loan Guarantees 債務擔保</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(liabilities.loanGuaranteesCurrent)} onChange={(e) => handleLiabilitiesChange('loanGuaranteesCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(liabilities.loanGuaranteesLast)} onChange={(e) => handleLiabilitiesChange('loanGuaranteesLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Banking Facility */}
- <TableRow>
- <TableCell>Banking Facility 銀行貸款</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(liabilities.bankingFacilityCurrent)} onChange={(e) => handleLiabilitiesChange('bankingFacilityCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(liabilities.bankingFacilityLast)} onChange={(e) => handleLiabilitiesChange('bankingFacilityLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Sub-header for Existing Premium Financing/Policy loan */}
- <TableRow>
- <TableCell colSpan={3} sx={{ fontWeight: 'bold', backgroundColor: '#f0f0f0', textAlign: 'center' }}>
- Existing Premium Financing/ Policy loan 現有保費融資/保單貸款
- </TableCell>
- </TableRow>
- {/* Principal */}
- <TableRow>
- <TableCell>Principal 本金還款額</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(liabilities.prefFinancePrincipalCurrent)} onChange={(e) => handleLiabilitiesChange('prefFinancePrincipalCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(liabilities.prefFinancePrincipalLast)} onChange={(e) => handleLiabilitiesChange('prefFinancePrincipalLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Other Liabilities */}
- <TableRow>
- <TableCell>Other 其他</TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(liabilities.prefFinanceOtherCurrent)} onChange={(e) => handleLiabilitiesChange('prefFinanceOtherCurrent', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField onFocus={handleFocus} disabled={!isEditing} fullWidth variant="outlined" size="small" inputProps={{ min: "0", step: "0.01" }}
- value={formatNumberForDisplay(liabilities.prefFinanceOtherLast)} onChange={(e) => handleLiabilitiesChange('prefFinanceOtherLast', cleanNumberForState(e.target.value))}
- />
- </TableCell>
- </TableRow>
- {/* Total Liabilities */}
- <TableRow sx={{ '& td': { fontWeight: 'bold', backgroundColor: '#d0d0d0' } }}>
- <TableCell>Total Liabilities 負債總額</TableCell>
- <TableCell align="right">
- <TextField fullWidth variant="filled" size="small" readOnly
- value={formatNumberForDisplay(totalLiabilitiesCurrent.toFixed(0))}
- />
- </TableCell>
- <TableCell align="right">
- <TextField fullWidth variant="filled" size="small" readOnly
- value={formatNumberForDisplay(totalLiabilitiesLast.toFixed(0))}
- />
- </TableCell>
- </TableRow>
- </TableBody>
- </Table>
- </TableContainer>
- </Grid>
- {/* --- END: LIABILITIES --- */}
-
- <Grid item xs={12} sx={{
- minHeight: isEditing ? '100px' : '70px',
- width: '100%'
- }} />
- <Grid></Grid>
- <Grid item xs={12} sx={{
- minHeight: isEditing ? '100px' : '70px',
- width: '100%'
- }} />
- <Grid></Grid>
-
-
- {(isEditing) ?
- <Paper
- sx={{
- position: 'fixed',
- bottom: 0,
- left: 0,
- right: 0,
- zIndex: 1300,
- padding: 1.5,
- boxShadow: '0 -4px 12px rgba(0, 0, 0, 0.15)',
- backgroundColor: 'white',
- display: 'flex',
- justifyContent: 'flex-end',
- }}
- >
- <Grid container maxWidth justifyContent="center" alignItems="center" >
- <ThemeProvider theme={LIONER_BUTTON_THEME}>
- <Grid item>
- <Grid container>
- <Grid item sx={{ ml: { xs: 1.5, md: 1.5, lg: 1.5 }, mr: 1.5, mb: 1, mt: 2 }}>
- <Button
- variant="contained"
- color="save"
- onClick={submitData}
- >
- Save
- </Button>
- </Grid>
- <Grid item sx={{ ml: 1.5, mr: 1.5, mb: 1, mt: 2 }}>
- <Button
- variant="contained"
- color="cancel"
- onClick={isNewRecord ? returnSearchPage : updateIsEdit}
- >
- Cancel
- </Button>
- </Grid>
- </Grid>
- </Grid>
- <Grid item>
- <Grid container>
- <ThemeProvider theme={LIONER_LONG_BUTTON_THEME}>
- </ThemeProvider>
- </Grid>
- </Grid>
- </ThemeProvider>
- </Grid>
- </Paper>
- :
- <Paper
- sx={{
- position: 'fixed',
- bottom: 0,
- left: 0,
- right: 0,
- zIndex: 1100, // Ensure it floats above all other content
- padding: 1.5,
- boxShadow: '0 -4px 12px rgba(0, 0, 0, 0.15)', // A shadow to clearly separate the bar
- backgroundColor: 'white', // Set an explicit background color
- display: 'flex',
- justifyContent: 'flex-end', // Push buttons to the right
- }}
- >
- <Grid container justifyContent="flex-end" alignItems="center" sx={{ maxWidth: '1400px', width: '100%', margin: '0 auto', pr: 3, pl: 3 }}>
- <Grid item sx={{ ml: 1, mr: 1 }}>
- {/* The Save button should only show/be enabled when editing */}
- <Button
- type="submit"
- variant="contained"
- color="primary"
- disabled={!isEditing || !ability.can('MAINTAIN', 'CLIENT')} // Disable if not editing
- sx={{ display: isEditing ? 'block' : 'none' }} // Only show when editing
- >
- Save
- </Button>
- </Grid>
- <Grid item sx={{ ml: 1, mr: 1 }}>
- {/* ADDED: onClick={handleEditClick} and conditional display/disabled */}
- <Button
- variant="contained"
- color="info"
- onClick={handleEditClick} // <--- REINSTATED EDIT LOGIC
- disabled={isEditing || !ability.can('MAINTAIN', 'CLIENT')} // Disable if already editing or no permission
- sx={{ display: isEditing ? 'none' : 'block' }} // Only show when not editing
- >
- Edit
- </Button>
- </Grid>
- <Grid item>
- <Button
- variant="contained"
- // ... (rest of Back button styles)
- onClick={returnSearchPage}
- >
- Back
- </Button>
- </Grid>
- </Grid>
- </Paper>
- }
- </Grid>
- </Grid>
- </form>
- </MainCard>
- );
- };
-
- export default ClientForm;
|