diff --git a/backend/openapi.yml b/backend/openapi.yml index a752f1b67b..56910e8256 100644 --- a/backend/openapi.yml +++ b/backend/openapi.yml @@ -291,11 +291,11 @@ paths: required: true content: application/json: - schema: - $ref: "#/components/schemas/CreateUpdateCANRequestSchema" - examples: - "0": - $ref: "#/components/examples/CreateUpdateCANRequestSchema" + schema: + $ref: "#/components/schemas/CreateUpdateCANRequestSchema" + examples: + "0": + $ref: "#/components/examples/CreateUpdateCANRequestSchema" responses: "200": description: CAN Updated @@ -329,11 +329,11 @@ paths: required: true content: application/json: - schema: - $ref: "#/components/schemas/CreateUpdateCANRequestSchema" - examples: - "0": - $ref: "#/components/examples/CreateUpdateCANRequestSchema" + schema: + $ref: "#/components/schemas/CreateUpdateCANRequestSchema" + examples: + "0": + $ref: "#/components/examples/CreateUpdateCANRequestSchema" responses: "200": description: CAN Updated @@ -391,11 +391,11 @@ paths: required: true content: application/json: - schema: - $ref: "#/components/schemas/CreateUpdateCANFundingBudgetRequest" - examples: - "0": - $ref: "#/components/examples/CreateUpdateCANFundingBudgetRequest" + schema: + $ref: "#/components/schemas/CreateUpdateCANFundingBudgetRequest" + examples: + "0": + $ref: "#/components/examples/CreateUpdateCANFundingBudgetRequest" responses: "201": description: Created @@ -457,11 +457,11 @@ paths: required: true content: application/json: - schema: - $ref: "#/components/schemas/CreateUpdateCANFundingBudgetRequest" - examples: - "0": - $ref: "#/components/examples/CreateUpdateCANFundingBudgetRequest" + schema: + $ref: "#/components/schemas/CreateUpdateCANFundingBudgetRequest" + examples: + "0": + $ref: "#/components/examples/CreateUpdateCANFundingBudgetRequest" responses: "200": description: CANFundingBudget Updated @@ -495,11 +495,11 @@ paths: required: true content: application/json: - schema: - $ref: "#/components/schemas/CreateUpdateCANFundingBudgetRequest" - examples: - "0": - $ref: "#/components/examples/CreateUpdateCANFundingBudgetRequest" + schema: + $ref: "#/components/schemas/CreateUpdateCANFundingBudgetRequest" + examples: + "0": + $ref: "#/components/examples/CreateUpdateCANFundingBudgetRequest" responses: "200": description: CAN Updated @@ -2355,6 +2355,8 @@ components: type: array items: $ref: "#/components/schemas/BudgetLineItem" + description: + type: string display_name: type: string funding_budgets: @@ -2371,8 +2373,14 @@ components: type: array items: $ref: "#/components/schemas/FundingReceived" + id: + type: integer + nick_name: + type: string number: type: string + obligate_by: + type: integer portfolio: type: integer portfolio_id: @@ -2381,12 +2389,6 @@ components: type: array items: $ref: "#/components/schemas/Project" - nick_name: - type: string - description: - type: string - id: - type: integer created_on: $ref: "#/components/parameters/created_on" updated_on: diff --git a/frontend/src/components/CANs/CANTable/CANTable.helpers.js b/frontend/src/components/CANs/CANTable/CANTable.helpers.js new file mode 100644 index 0000000000..b3790efd4e --- /dev/null +++ b/frontend/src/components/CANs/CANTable/CANTable.helpers.js @@ -0,0 +1,27 @@ +/** + * Gets the last day of the fiscal year for a given year. + * @param {number} fiscalYear - The fiscal year + * @returns {Date} The last day of the fiscal year + */ +const getLastDayOfFiscalYear = (fiscalYear) => { + // Fiscal year ends on September 30 of the previous calendar year + return new Date(fiscalYear - 1, 8, 30); // Month is 0-indexed, so 8 is September +}; +/** + * Formats the obligate by date to the last day of the fiscal year. + * @param {number | undefined} obligateBy - The obligate by value + * @returns {string} Formatted date string or "TBD" + */ +export const formatObligateBy = (obligateBy) => { + if (!obligateBy) return "TBD"; // Default value + if (typeof obligateBy !== "number" || isNaN(obligateBy)) return "TBD"; // Default if parsing fails + + const lastDay = getLastDayOfFiscalYear(obligateBy); + + // Format as MM/DD/YY + return lastDay.toLocaleDateString("en-US", { + month: "2-digit", + day: "2-digit", + year: "2-digit" + }); +}; diff --git a/frontend/src/components/CANs/CANTable/CANTable.helpers.test.js b/frontend/src/components/CANs/CANTable/CANTable.helpers.test.js new file mode 100644 index 0000000000..3349b089e6 --- /dev/null +++ b/frontend/src/components/CANs/CANTable/CANTable.helpers.test.js @@ -0,0 +1,24 @@ +import { formatObligateBy } from "./CANTable.helpers"; + +describe("formatObligateBy", () => { + test('returns "TBD" for undefined input', () => { + expect(formatObligateBy(undefined)).toBe("TBD"); + }); + + test('returns "TBD" for non-numeric input', () => { + expect(formatObligateBy("not a number")).toBe("TBD"); + }); + + test('returns "TBD" for NaN input', () => { + expect(formatObligateBy(NaN)).toBe("TBD"); + }); + + test("formats valid fiscal year correctly", () => { + expect(formatObligateBy(2023)).toBe("09/30/22"); + }); + + test("handles different fiscal years", () => { + expect(formatObligateBy(2024)).toBe("09/30/23"); + expect(formatObligateBy(2025)).toBe("09/30/24"); + }); +}); diff --git a/frontend/src/components/CANs/CANTable/CANTable.jsx b/frontend/src/components/CANs/CANTable/CANTable.jsx index 5ac792fffa..d6f20e233a 100644 --- a/frontend/src/components/CANs/CANTable/CANTable.jsx +++ b/frontend/src/components/CANs/CANTable/CANTable.jsx @@ -1,10 +1,11 @@ -import _ from "lodash"; import PropTypes from "prop-types"; import React from "react"; import PaginationNav from "../../UI/PaginationNav"; -import Tooltip from "../../UI/USWDS/Tooltip"; +import CANTableHead from "./CANTableHead"; import CANTableRow from "./CANTableRow"; import styles from "./style.module.css"; +import { formatObligateBy } from "./CANTable.helpers"; + /** * CANTable component of CanList * @component @@ -16,7 +17,7 @@ import styles from "./style.module.css"; const CANTable = ({ cans }) => { const CANS_PER_PAGE = 10; const [currentPage, setCurrentPage] = React.useState(1); - let cansPerPage = _.cloneDeep(cans); + let cansPerPage = [...cans]; cansPerPage = cansPerPage.slice((currentPage - 1) * CANS_PER_PAGE, currentPage * CANS_PER_PAGE); if (cans.length === 0) { @@ -26,18 +27,18 @@ const CANTable = ({ cans }) => { return ( <>
- CAN - | -- Portfolio - | -- FY - | -- Active Period - | -- Obligate By - | -- Transfer - | -- FY Budget - | -
- |
-
---|---|---|---|---|---|---|---|
+ CAN + | ++ Portfolio + | ++ FY + | ++ Active Period + | ++ Obligate By + | ++ Transfer + | ++ FY Budget + | +
+ |
+