Untitled

 avatar
unknown
javascript
12 days ago
16 kB
3
Indexable
import { FC, useState, useEffect } from "react";
import { useSelector } from "react-redux";
import {
  Col,
  Row,
  Form,
  FormGroup,
  Label,
  Input,
  InputGroup,
  InputGroupText,
  Button,
} from "reactstrap";
import { RootState } from "@/Redux/Store";

interface DebtRepaymentTabContentProps {
  updateField: (field: string, value: any) => void;
}

const DebtRepaymentTabContent: FC<DebtRepaymentTabContentProps> = ({
  updateField,
}) => {
  const budgetPlannerData = useSelector(
    (state: RootState) => state.budgetPlanner ?? {
      current_debt_repayments: {},
      post_debt_repayments: {},
      current_priority_debt: {},
      post_priority_debt: {},
      current_unsecured_borrowing: {},
      post_unsecured_borrowing: {},
    }
  );
  const [currentValues, setCurrentValues] = useState<Record<string, string>>(
    {}
  );
  const [postValues, setPostValues] = useState<Record<string, string>>({});

  const debtRepaymentFieldMappings = {
    "Mortgage/Rent - Monthly": "mortgage_rent",
    "Second Mortgage - Monthly": "second_mortgage",
    "Shared Ownership Rental - Monthly": "shared_ownership_rental",
  };

  const priorityDebtFieldMappings = {
    "Mortgage Arrears - Monthly": "mortgage_arrears",
    "Gas Arrears - Monthly": "gas_arrears",
    "Maintenance Arrears - Monthly": "maintenance_arrears",
    "Defaults - Monthly": "defaults",
    "CCJs - Monthly": "ccjs",
    "Debt Management Plans - Monthly": "debt_management_plans",
    "Magistrate Court Fines - Monthly": "magistrate_court_fines",
    "Council Tax Arrears - Monthly": "council_tax_arrears",
  };

  const unsecuredBorrowingFieldMappings = {
    "Credit Cards - Monthly": "credit_cards",
    "Loans - Monthly": "loans",
    "Car Finance - Monthly": "car_finance",
    "Overdraft - Monthly": "overdraft",
    "Store Cards - Monthly": "store_cards",
    "Student Loans - Monthly": "student_loans",
    "Other Borrowing - Monthly": "other_borrowing",
  };

  // Initialize local state with Redux data
  useEffect(() => {
    if (!budgetPlannerData) return; // Add early return if data is null

    const initialCurrentValues: Record<string, string> = {};
    const initialPostValues: Record<string, string> = {};

    // Current Debt Repayments
    Object.entries(debtRepaymentFieldMappings).forEach(([field, key]) => {
      const value =
        budgetPlannerData?.current_debt_repayments?.[
          key as keyof typeof budgetPlannerData.current_debt_repayments
        ] ?? 0;
      initialCurrentValues[`CurrentBudgetPlanner.${field}`] =
        value !== 0 ? String(value) : "";
    });

    // Post Debt Repayments
    Object.entries(debtRepaymentFieldMappings).forEach(([field, key]) => {
      const value =
        budgetPlannerData?.post_debt_repayments?.[
          key as keyof typeof budgetPlannerData.post_debt_repayments
        ] ?? 0;
      initialPostValues[`PostCompletionBudgetPlanner.${field}`] =
        value !== 0 ? String(value) : "";
    });

    // Current Priority Debt
    Object.entries(priorityDebtFieldMappings).forEach(([field, key]) => {
      const value =
        budgetPlannerData?.current_priority_debt?.[
          key as keyof typeof budgetPlannerData.current_priority_debt
        ] ?? 0;
      initialCurrentValues[`CurrentBudgetPlanner.${field}`] =
        value !== 0 ? String(value) : "";
    });

    // Post Priority Debt
    Object.entries(priorityDebtFieldMappings).forEach(([field, key]) => {
      const value =
        budgetPlannerData?.post_priority_debt?.[
          key as keyof typeof budgetPlannerData.post_priority_debt
        ] ?? 0;
      initialPostValues[`PostCompletionBudgetPlanner.${field}`] =
        value !== 0 ? String(value) : "";
    });

    // Current Unsecured Borrowing
    Object.entries(unsecuredBorrowingFieldMappings).forEach(([field, key]) => {
      const value =
        budgetPlannerData?.current_unsecured_borrowing?.[
          key as keyof typeof budgetPlannerData.current_unsecured_borrowing
        ] ?? 0;
      initialCurrentValues[`CurrentBudgetPlanner.${field}`] =
        value !== 0 ? String(value) : "";
    });

    // Post Unsecured Borrowing
    Object.entries(unsecuredBorrowingFieldMappings).forEach(([field, key]) => {
      const value =
        budgetPlannerData?.post_unsecured_borrowing?.[
          key as keyof typeof budgetPlannerData.post_unsecured_borrowing
        ] ?? 0;
      initialPostValues[`PostCompletionBudgetPlanner.${field}`] =
        value !== 0 ? String(value) : "";
    });

    setCurrentValues((prev) => ({ ...prev, ...initialCurrentValues }));
    setPostValues((prev) => ({ ...prev, ...initialPostValues }));
  }, [budgetPlannerData]);

  // Update parent modal with current values
  useEffect(() => {
    const formatValues = (
      values: Record<string, string>,
      mappings: Record<string, string>,
      section: string
    ) => {
      const formatted = Object.entries(values)
        .filter(([key]) => key.startsWith("CurrentBudgetPlanner"))
        .reduce((acc, [key, value]) => {
          const fieldName = key.split(".")[1];
          const reduxFieldName = mappings[fieldName as keyof typeof mappings];
          if (reduxFieldName) {
            acc[reduxFieldName] = value === "" ? 0 : parseFloat(value);
          }
          return acc;
        }, {} as Record<string, number | 0>);
      formatted.total_debt_repayment =
        parseFloat(
          calculateSectionTotal(
            values,
            Object.keys(mappings),
            "CurrentBudgetPlanner"
          )
        ) || 0;
      updateField(section, formatted);
    };

    formatValues(
      currentValues,
      debtRepaymentFieldMappings,
      "current_debt_repayments"
    );
    formatValues(
      currentValues,
      priorityDebtFieldMappings,
      "current_priority_debt"
    );
    formatValues(
      currentValues,
      unsecuredBorrowingFieldMappings,
      "current_unsecured_borrowing"
    );
  }, [currentValues, updateField]);

  // Update parent modal with post values
  useEffect(() => {
    const formatValues = (
      values: Record<string, string>,
      mappings: Record<string, string>,
      section: string
    ) => {
      const formatted = Object.entries(values)
        .filter(([key]) => key.startsWith("PostCompletionBudgetPlanner"))
        .reduce((acc, [key, value]) => {
          const fieldName = key.split(".")[1];
          const reduxFieldName = mappings[fieldName as keyof typeof mappings];
          if (reduxFieldName) {
            acc[reduxFieldName] = value === "" ? 0 : parseFloat(value);
          }
          return acc;
        }, {} as Record<string, number | 0>);
      formatted.total_debt_repayment =
        parseFloat(
          calculateSectionTotal(
            values,
            Object.keys(mappings),
            "PostCompletionBudgetPlanner"
          )
        ) || 0;
      updateField(section, formatted);
    };

    formatValues(
      postValues,
      debtRepaymentFieldMappings,
      "post_debt_repayments"
    );
    formatValues(postValues, priorityDebtFieldMappings, "post_priority_debt");
    formatValues(
      postValues,
      unsecuredBorrowingFieldMappings,
      "post_unsecured_borrowing"
    );
  }, [postValues, updateField]);

  const renderForm = (
    prefix: string,
    fields: string[],
    mappings: Record<string, string>
  ) => (
    <Form>
      {fields.map((field) => {
        const fieldName = `${prefix}.${field}`;
        const reduxFieldName = mappings[field];
        return (
          <FormGroup row key={field} className="mb-2">
            <Label
              for={`${prefix}_${reduxFieldName}`}
              sm={6}
              style={{ fontSize: "0.9rem" }}
            >
              {field}
            </Label>
            <Col sm={6}>
              <InputGroup>
                <InputGroupText>£</InputGroupText>
                <Input
                  type="number"
                  name={fieldName}
                  id={`${prefix}_${reduxFieldName}`}
                  className="numeric-decimal debt-repayment"
                  placeholder="0.00"
                  step="0.01"
                  value={
                    prefix === "CurrentBudgetPlanner"
                      ? currentValues[fieldName] || ""
                      : postValues[fieldName] || ""
                  }
                  onChange={(e) => {
                    const newValues =
                      prefix === "CurrentBudgetPlanner"
                        ? { ...currentValues, [fieldName]: e.target.value }
                        : { ...postValues, [fieldName]: e.target.value };
                    prefix === "CurrentBudgetPlanner"
                      ? setCurrentValues(newValues)
                      : setPostValues(newValues);
                  }}
                />
              </InputGroup>
            </Col>
          </FormGroup>
        );
      })}
    </Form>
  );

  const calculateSectionTotal = (
    values: Record<string, string>,
    fields: string[],
    prefix: string
  ) => {
    return fields
      .reduce((sum, field) => {
        const fieldName = `${prefix}.${field}`;
        return sum + (parseFloat(values[fieldName]) || 0);
      }, 0)
      .toFixed(2);
  };

  const calculateOverallTotal = (
    values: Record<string, string>,
    prefix: string
  ) => {
    const debtTotal = calculateSectionTotal(
      values,
      Object.keys(debtRepaymentFieldMappings),
      prefix
    );
    const priorityTotal = calculateSectionTotal(
      values,
      Object.keys(priorityDebtFieldMappings),
      prefix
    );
    const unsecuredTotal = calculateSectionTotal(
      values,
      Object.keys(unsecuredBorrowingFieldMappings),
      prefix
    );
    return (
      parseFloat(debtTotal) +
      parseFloat(priorityTotal) +
      parseFloat(unsecuredTotal)
    ).toFixed(2);
  };

  const handleCopyFromCurrent = (prefix: string) => {
    const newPostValues: Record<string, string> = {};
    Object.keys(currentValues).forEach((key) => {
      if (key.startsWith("CurrentBudgetPlanner")) {
        const newKey = key.replace("CurrentBudgetPlanner", prefix);
        newPostValues[newKey] = currentValues[key];
      }
    });
    setPostValues((prev) => ({ ...prev, ...newPostValues }));
  };

  const renderSection = (
    title: string,
    prefix: string,
    fields: string[],
    mappings: Record<string, string>,
    hasCalculate?: boolean,
    showCopyButton?: boolean
  ) => (
    <div className="col-md-6">
      <h4 className="text-center mb-3">
        {title === "Total Debt Repayment" ? "" : title}
      </h4>
      <div
        className={`panel-default panel panel-primary border rounded-3 shadow-sm ${
          title === "Total Debt Repayment" ? "no-padding-vr no-border" : ""
        }`}
      >
        <div
          className={`bg-light border-bottom p-3 ${
            showCopyButton
              ? "d-flex justify-content-between align-items-center"
              : ""
          }`}
        >
          {title !== "Total Debt Repayment" && (
            <span className="fw-bold text-primary">
              {title === "Debt Repayments"
                ? "Debt Repayments"
                : title === "Priority Debt"
                ? "Priority Debt"
                : "Unsecured Borrowing"}
            </span>
          )}
          {showCopyButton && (
            <Button
              color="primary"
              size="sm"
              onClick={() => handleCopyFromCurrent(prefix)}
            >
              Copy from Current
            </Button>
          )}
        </div>
        <div className="p-3">
          {title === "Total Debt Repayment" ? (
            <FormGroup row className="mb-2">
              <Label
                for={`${prefix}_TotalDebtRepayment`}
                sm={6}
                style={{ fontSize: "0.9rem" }}
              >
                Total Debt Repayment - Monthly
              </Label>
              <Col sm={6}>
                <InputGroup>
                  <InputGroupText>£</InputGroupText>
                  <Input
                    type="number"
                    name={`${prefix}.TotalDebtRepayment`}
                    id={`${prefix}_TotalDebtRepayment`}
                    className="numeric-decimal fw-bold"
                    readOnly
                    placeholder="0.00"
                    value={calculateOverallTotal(
                      prefix === "CurrentBudgetPlanner"
                        ? currentValues
                        : postValues,
                      prefix
                    )}
                  />
                </InputGroup>
              </Col>
            </FormGroup>
          ) : (
            renderForm(prefix, fields, mappings)
          )}
        </div>
        {hasCalculate && (
          <div className="p-3 bg-light border-top">
            <FormGroup row className="mb-0">
              <Label
                className="control-label fw-bold text-primary"
                for={`${prefix}_TotalDebt`}
                sm={6}
                style={{ fontSize: "0.9rem" }}
              >
                Total {title}
              </Label>
              <Col sm={6}>
                <InputGroup>
                  <InputGroupText>£</InputGroupText>
                  <Input
                    type="number"
                    name={`${prefix}.TotalDebt`}
                    id={`${prefix}_TotalDebt`}
                    className="numeric-decimal fw-bold"
                    readOnly
                    placeholder="0.00"
                    value={calculateSectionTotal(
                      prefix === "CurrentBudgetPlanner"
                        ? currentValues
                        : postValues,
                      fields,
                      prefix
                    )}
                  />
                </InputGroup>
              </Col>
            </FormGroup>
          </div>
        )}
      </div>
    </div>
  );

  return (
    <div>
      <p className="fs-9">
        <small>
          Add debt repayments like credit card minimum payments here. Do not
          include regular credit card spending - that goes in living costs.
        </small>
      </p>
      <Row>
        {renderSection(
          "Current",
          "CurrentBudgetPlanner",
          Object.keys(debtRepaymentFieldMappings),
          debtRepaymentFieldMappings,
          true
        )}
        {renderSection(
          "Post Completion",
          "PostCompletionBudgetPlanner",
          Object.keys(debtRepaymentFieldMappings),
          debtRepaymentFieldMappings,
          true,
          true
        )}
      </Row>
      <Row className="mt-4">
        {renderSection(
          "Priority Debt",
          "CurrentBudgetPlanner",
          Object.keys(priorityDebtFieldMappings),
          priorityDebtFieldMappings
        )}
        {renderSection(
          "Priority Debt",
          "PostCompletionBudgetPlanner",
          Object.keys(priorityDebtFieldMappings),
          priorityDebtFieldMappings,
          false,
          true
        )}
      </Row>
      <Row className="mt-4">
        {renderSection(
          "Unsecured Borrowing",
          "CurrentBudgetPlanner",
          Object.keys(unsecuredBorrowingFieldMappings),
          unsecuredBorrowingFieldMappings,
          true
        )}
        {renderSection(
          "Unsecured Borrowing",
          "PostCompletionBudgetPlanner",
          Object.keys(unsecuredBorrowingFieldMappings),
          unsecuredBorrowingFieldMappings,
          true,
          true
        )}
      </Row>
      <Row className="mt-4">
        {renderSection("Total Debt Repayment", "CurrentBudgetPlanner", [], {})}
        {renderSection(
          "Total Debt Repayment",
          "PostCompletionBudgetPlanner",
          [],
          {}
        )}
      </Row>
    </div>
  );
};

export default DebtRepaymentTabContent;
Editor is loading...
Leave a Comment