Skip to content

Commit

Permalink
Merge pull request #3334 from HHS/OPS-310/3102_table2
Browse files Browse the repository at this point in the history
feat: adds welcome modal to can funding received tab
  • Loading branch information
fpigeonjr authored Jan 23, 2025
2 parents 68091ef + 95fded9 commit 3681ae8
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 36 deletions.
17 changes: 12 additions & 5 deletions frontend/cypress/e2e/canDetail.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,11 @@ describe("CAN detail page", () => {
cy.visit(`/cans/${can504.number}/funding`);
cy.get("#fiscal-year-select").select(currentFiscalYear);
cy.get("#edit").click();
// Check welcome modal
cy.get("#ops-modal-heading").contains(
"Data from the previous fiscal year can no longer be edited, but can be viewed by changing the FY dropdown on the CAN details page."
);
cy.get("[data-cy=confirm-action]").click();
cy.get("#carry-forward-card").should("contain", "$ 10,000,000.00");
cy.get("#save-changes").should("be.disabled");
cy.get("#add-fy-budget").should("be.disabled");
Expand All @@ -201,6 +206,8 @@ describe("CAN detail page", () => {
cy.visit(`/cans/${can504.number}/funding`);
cy.get("#fiscal-year-select").select(currentFiscalYear);
cy.get("#edit").click();
// welcome modal should not be present
cy.get("#ops-modal-heading").should("not.exist");
// check that all buttons (saved, all funding received) are disabled
cy.get("[data-cy=add-funding-received-btn]").should("be.disabled");
cy.get("[data-cy=save-btn]").should("be.disabled");
Expand Down Expand Up @@ -232,30 +239,29 @@ describe("CAN detail page", () => {
// verify form is populated correctly
cy.get("#funding-received-amount").invoke("val").should("equal", "1,000,000");
cy.get("#notes").invoke("val").should("equal", "Test notes");
// edit form
// edit funding received form
cy.get("#funding-received-amount").clear();
cy.get("#funding-received-amount").type("2_000_000");
cy.get("[data-cy=add-funding-received-btn]").click();
cy.get("[data-cy=budget-received-card]").should("exist").and("contain", "2,000,000.00");
// validation check
// validation check to ensure amount does not exceed budget amount
cy.get("tbody").find("tr").first().trigger("mouseover");
cy.get("tbody").find("tr").first().find('[data-cy="edit-row"]').click();
cy.get("#funding-received-amount").clear();
cy.get("#funding-received-amount").type("5_000_001");
cy.get("[data-cy=add-funding-received-btn]").should("be.disabled");
cy.get(".usa-error-message").should("exist").contains("Amount cannot exceed FY Budget");
cy.get("[data-cy=cancel-funding-received-btn]").click();

// delete a funding received from table
cy.get("#funding-received-amount").type("3_000_000");
cy.get("#notes").type("Delete me please");
cy.get("[data-cy=add-funding-received-btn]").click();
cy.get("tbody").find("tr").eq(1).trigger("mouseover");
cy.get("tbody").find("tr").eq(1).find('[data-cy="delete-row"]').click();
cy.get("tbody").children().should("have.length", 1);
// make sure the funding received card on the right updates (to do after bug fix)
// make sure the funding received card on the right updates
cy.get("[data-cy=budget-received-card]").should("exist").and("contain", "2,000,000.00");
// click on button at bottom of form
// click on save button at bottom of form
cy.get("[data-cy=save-btn]").click();
// check success alert
cy.get(".usa-alert__body").should("contain", `The CAN ${can504.nickname} has been successfully updated.`);
Expand Down Expand Up @@ -327,6 +333,7 @@ describe("CAN detail page", () => {
cy.visit(`/cans/500/funding`);
cy.get("#fiscal-year-select").select(currentFiscalYear);
cy.get("#edit").click();
cy.get("[data-cy=confirm-action]").click();
cy.get("#carry-forward-card").should("not.exist");
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ const CANBudgetByFYCard = ({ fundingBudgets }) => {
title="CAN Budget by FY"
dataCy="can-budget-fy-card"
>
{chartData.map((item) => (
{chartData.map((item, i) => (
<LineBar
key={`budget-fy-${item.FY}`}
iterator={i}
color={item.color}
ratio={item.ratio}
title={`FY ${item.FY}`}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import icons from "../../../uswds/img/sprite.svg";
* @property {number} fiscalYear
* @property {(e: React.FormEvent<HTMLFormElement>) => void} handleAddBudget
* @property {(name: string, value: string) => void} runValidate
* @property { React.Dispatch<React.SetStateAction<string>>} setBudgetAmount
* @property {(value: string) => void} setBudgetAmount
*/

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import icons from "../../../uswds/img/sprite.svg";
* @property {(e: React.FormEvent<HTMLFormElement>) => void} handleSubmit
* @property {boolean} isEditing
* @property {(name: string, value: string) => void} runValidate
* @property { React.Dispatch<React.SetStateAction<string>>} setReceivedFundingAmount
* @property {(value: string) => void} setReceivedFundingAmount
* @property {string} notes
* @property { React.Dispatch<React.SetStateAction<string>>} setNotes
* @property { () => void } cancelFundingReceived
* @property {(value: string) => void} setNotes
* @property {(e: React.FormEvent<HTMLFormElement>) => void } cancelFundingReceived
*/

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import CANFundingReceivedTableRow from "./CANFundingReceivedTableRow";
* @property {FundingReceived[]} fundingReceived data for table
* @property {boolean} isEditMode for if we're in edit mode
* @property {(id: number | string) => void} populateFundingReceivedForm function for editing funding received
* @property {() => void} deleteFundingReceived
* @property {(fundingReceivedId: number | string) => void} deleteFundingReceived
*/

/**
Expand Down
26 changes: 16 additions & 10 deletions frontend/src/components/UI/DataViz/LineBar/LineBar.jsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import CurrencyFormat from "react-currency-format";
import styles from "./LineBar.styles.module.css";
import { NO_DATA } from "../../../../constants";
import { getDecimalScale } from "../../../../helpers/currencyFormat.helpers";
import styles from "./LineBar.styles.module.css";

/**
* @typedef {Object} LineBarProps
* @property {string} title - The title text to display
* @property {number} ratio - The ratio value that determines the bar length
* @property {string} color - The background color of the bar
* @property {number} total - The total amount to display formatted as currency
* @property {number} iterator - The index of the current item in the list
*/

/**
* @component A line bar component that displays a title, a colored bar based on ratio, and a currency formatted total value
* @param {LineBarProps} props
* @returns {JSX.Element} A line bar component
*/
const LineBar = ({ title, ratio, color, total }) => {
const LineBar = ({ title, ratio, color, total, iterator }) => {
return (
<div className={styles.container}>
<span className={styles.title}>{title}</span>
Expand All @@ -26,14 +28,18 @@ const LineBar = ({ title, ratio, color, total }) => {
/>
</div>
<div className={styles.amount}>
<CurrencyFormat
value={total}
displayType="text"
thousandSeparator=","
prefix="$"
decimalScale={getDecimalScale(total)}
fixedDecimalScale={true}
/>
{total === 0 && iterator === 0 ? (
NO_DATA
) : (
<CurrencyFormat
value={total}
displayType="text"
thousandSeparator=","
prefix="$"
decimalScale={getDecimalScale(total)}
fixedDecimalScale={true}
/>
)}
</div>
</div>
);
Expand Down
43 changes: 37 additions & 6 deletions frontend/src/pages/cans/detail/Can.hooks.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";
import { useSelector } from "react-redux";
import { useParams } from "react-router-dom";
import { useLocation, useParams } from "react-router-dom";
import { useGetCanByIdQuery, useGetCanFundingSummaryQuery } from "../../../api/opsAPI";
import { USER_ROLES } from "../../../components/Users/User.constants";
import { NO_DATA } from "../../../constants";
Expand All @@ -16,19 +16,30 @@ export default function useCan() {
// send to CanFunding hook
// if its present PATCH otherwise POST

const [isEditMode, setIsEditMode] = React.useState(false);
const urlPathParams = useParams();
const location = useLocation();
const activeUser = useSelector((state) => state.auth.activeUser);
const userRoles = activeUser?.roles ?? [];
const isBudgetTeam = userRoles.includes(USER_ROLES.BUDGET_TEAM);
const selectedFiscalYear = useSelector((state) => state.canDetail.selectedFiscalYear);
const fiscalYear = Number(selectedFiscalYear.value);
const urlPathParams = useParams();
const canId = parseInt(urlPathParams.id ?? "-1");
/** @type {{data?: CAN | undefined, isLoading: boolean}} */
const initialModalProps = {
heading: "",
actionButtonText: "",
secondaryButtonText: "",
handleConfirm: () => {},
showModal: false
};
const [modalProps, setModalProps] = React.useState(initialModalProps);
const [isEditMode, setIsEditMode] = React.useState(false);
const isFundingPage = location.pathname.includes("funding");

/** @type {{data?: CAN | undefined, isLoading: boolean}} */
const { data: can, isLoading } = useGetCanByIdQuery(canId, {
refetchOnMountOrArgChange: true
});

/** @type {{data?: FundingSummary | undefined, isLoading: boolean}} */
const { data: CANFunding, isLoading: CANFundingLoading } = useGetCanFundingSummaryQuery({
ids: [canId],
Expand Down Expand Up @@ -82,7 +93,25 @@ export default function useCan() {
);

const toggleEditMode = () => {
setIsEditMode(!isEditMode);
if (isFundingPage && CANFunding?.total_funding === "0") {
setModalProps({
heading: `Welcome to FY ${fiscalYear}! The new fiscal year started on October 1, ${fiscalYear - 1} and it's time to add the FY budget for this CAN. Data from the previous fiscal year can no longer be edited, but can be viewed by changing the FY dropdown on the CAN details page.`,
actionButtonText: "Edit CAN",
secondaryButtonText: "Cancel",
showModal: true,
handleConfirm: () => {
setIsEditMode(!isEditMode);
setModalProps(initialModalProps);
}
});
} else {
setIsEditMode(!isEditMode);
}
};

const resetModal = () => {
setIsEditMode(false);
setModalProps(initialModalProps);
};

const currentFiscalYearFundingId = can?.funding_budgets?.find((funding) => funding.fiscal_year === fiscalYear)?.id;
Expand All @@ -98,6 +127,7 @@ export default function useCan() {
canNumber: can?.number ?? NO_DATA,
description: can?.description,
nickname: can?.nick_name,
modalProps,
fundingDetails: can?.funding_details ?? {},
fundingBudgets: can?.funding_budgets ?? [],
fundingReceivedByFiscalYear: fundingReceivedByFiscalYear,
Expand All @@ -119,6 +149,7 @@ export default function useCan() {
isBudgetTeam,
toggleEditMode,
isEditMode,
setIsEditMode
setIsEditMode,
resetModal
};
}
4 changes: 4 additions & 0 deletions frontend/src/pages/cans/detail/Can.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ const Can = () => {
canNumber,
description,
nickname,
modalProps,
resetModal,
fundingDetails,
fundingBudgets,
fundingReceivedByFiscalYear,
Expand Down Expand Up @@ -115,6 +117,8 @@ const Can = () => {
<CanFunding
canId={canId}
canNumber={canNumber}
welcomeModal={modalProps}
setWelcomeModal={resetModal}
currentFiscalYearFundingId={currentFiscalYearFundingId}
funding={fundingDetails}
fundingBudgets={fundingBudgets}
Expand Down
11 changes: 7 additions & 4 deletions frontend/src/pages/cans/detail/CanFunding.hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import cryptoRandomString from "crypto-random-string";
* @param {boolean} isBudgetTeamMember
* @param {boolean} isEditMode
* @param {() => void} toggleEditMode
* @param {() => void} setWelcomeModal
* @param {string} receivedFunding
* @param {FundingReceived[]} fundingReceived
* @param {number} [currentFiscalYearFundingId] - The id of the current fiscal year funding. optional
Expand All @@ -39,6 +40,7 @@ export default function useCanFunding(
isBudgetTeamMember,
isEditMode,
toggleEditMode,
setWelcomeModal,
receivedFunding,
fundingReceived,
currentFiscalYearFundingId
Expand Down Expand Up @@ -291,9 +293,9 @@ export default function useCanFunding(
return fundingEntry.id === newFundingReceived.id;
});

console.log({ matchingFundingReceived });

const matchingFundingReceivedFunding = +matchingFundingReceived?.funding || 0;
const matchingFundingReceivedFunding =
// set matchingFundingReceivedFunding to 0 if matchingFundingReceived is undefined
matchingFundingReceived && matchingFundingReceived.funding ? +matchingFundingReceived.funding : 0;
setTotalReceived(
(currentTotal) => currentTotal - matchingFundingReceivedFunding + +fundingReceivedForm.enteredAmount
);
Expand Down Expand Up @@ -342,7 +344,7 @@ export default function useCanFunding(
const newDeletedFundingReceivedIds = [...deletedFundingReceivedIds, fundingReceivedId];
setDeletedFundingReceivedIds(newDeletedFundingReceivedIds);
}
setTotalReceived((currentTotal) => currentTotal - +matchingFundingReceived?.funding);
setTotalReceived((currentTotal) => currentTotal - +(matchingFundingReceived?.funding ?? 0));
};

const handleCancel = () => {
Expand All @@ -365,6 +367,7 @@ export default function useCanFunding(
setShowModal(false);
setFundingReceivedForm(initialFundingReceivedForm);
toggleEditMode();
setWelcomeModal();
setModalProps({
heading: "",
actionButtonText: "",
Expand Down
Loading

0 comments on commit 3681ae8

Please sign in to comment.