diff --git a/apcd-cms/src/apps/admin_extension/views.py b/apcd-cms/src/apps/admin_extension/views.py index c27f0dbf..7c491002 100644 --- a/apcd-cms/src/apps/admin_extension/views.py +++ b/apcd-cms/src/apps/admin_extension/views.py @@ -158,7 +158,7 @@ def put(self, request, ext_id): updated_data['extension_id'] = ext_id updated_data['status'] = data['ext_status'] updated_data['outcome'] = data['ext_outcome'] - updated_data['approved-expiration-date'] = data['approved_expiration_date'] + updated_data['approved_expiration_date'] = data['approved_expiration_date'] updated_data['applicable_data_period'] = data['applicable_data_period'] updated_data['notes'] = data['notes'] diff --git a/apcd-cms/src/apps/utils/apcd_database.py b/apcd-cms/src/apps/utils/apcd_database.py index 4625d65d..7ffdc7bf 100644 --- a/apcd-cms/src/apps/utils/apcd_database.py +++ b/apcd-cms/src/apps/utils/apcd_database.py @@ -1023,10 +1023,10 @@ def update_extension(form): set_values = [] # to set column names for query to the correct DB name columns = { - 'applicable-data-period': 'applicable_data_period', + 'applicable_data_period': 'applicable_data_period', 'status': 'status', 'outcome': 'outcome', - 'approved-expiration-date': 'approved_expiration_date' + 'approved_expiration_date': 'approved_expiration_date' } # To make sure fields are not blank. # If they aren't, add column to update set operation diff --git a/apcd-cms/src/client/src/components/Extensions/EditExtensionModal/EditExtensionModal.tsx b/apcd-cms/src/client/src/components/Extensions/EditExtensionModal/EditExtensionModal.tsx index f49a4788..89c28f44 100644 --- a/apcd-cms/src/client/src/components/Extensions/EditExtensionModal/EditExtensionModal.tsx +++ b/apcd-cms/src/client/src/components/Extensions/EditExtensionModal/EditExtensionModal.tsx @@ -22,12 +22,15 @@ import { import { fetchUtil } from 'utils/fetchUtil'; import * as Yup from 'yup'; import { ExtensionRow } from 'hooks/admin'; +import { useEntities } from 'hooks/entities'; +import QueryWrapper from 'core-wrappers/QueryWrapper'; +import { convertPeriodLabelToApiValue } from 'utils/dateUtil'; import styles from './EditExtensionModal.module.css'; interface EditExtensionModalProps { isVisible: boolean; onClose: () => void; - extension: ExtensionEditRow | null; + extension: ExtensionRow | null; statusOptions: string[] | undefined; outcomeOptions: string[] | undefined; onEditSuccess?: (updatedExtension: ExtensionRow) => void; @@ -66,6 +69,11 @@ const EditExtensionModal: React.FC = ({ { label: 'Exception Outcome', value: extension?.ext_outcome }, { label: 'Exception Notes', value: extension?.notes || 'None' }, ]); + const { + data: submitterData, + isLoading: entitiesLoading, + error: entitiesError, + } = useEntities(); if (!extension) return null; @@ -73,7 +81,7 @@ const EditExtensionModal: React.FC = ({ const useFormFields = () => { const initialValues: FormValues = { ...extension, - extension_id: extension?.ext_id, + ext_id: extension?.ext_id, notes: extension?.notes || 'None', // Set notes to 'None' if it is null }; @@ -193,190 +201,207 @@ const EditExtensionModal: React.FC = ({ Success: The extension data has been successfully updated.
Edit Selected Extension
- -
- - - - - - - Current: {extension.applicable_data_period} - - - - - - - - - - Current:{' '} - {extension.approved_expiration_date - ? new Date( - extension.approved_expiration_date - ).toLocaleDateString() - : 'None'} - - - - - - - - - {statusOptions?.map( - (opt) => - opt.value !== 'All' && ( + + + + + + + + + {submitterData?.submitters + .find( + (s) => + s.submitter_id === Number(extension.submitter_id) + ) + ?.data_periods?.map((item) => ( - ) - )} - - - - - - - - - {outcomeOptions?.map((opt) => ( - - ))} - - - - - - - - - - 2000 character limit - - - - - -
- - Error: {errorMessage} - - - -
+ ))} +
+ + Current: {extension.applicable_data_period} + + +
+ + + + + + + Current:{' '} + {extension.approved_expiration_date + ? new Date( + extension.approved_expiration_date + ).toLocaleDateString() + : 'None'} + + + + + + + + + {statusOptions?.map( + (opt) => + opt.value !== 'All' && ( + + ) + )} + + + + + + + + + {outcomeOptions?.map((opt) => ( + + ))} + + + + + + + + + + 2000 character limit + + + + +
+
+ + Error: {errorMessage} + + + +
+
{userFields.map((field, index) => ( diff --git a/apcd-cms/src/client/src/utils/dateUtil.ts b/apcd-cms/src/client/src/utils/dateUtil.ts index 1fd75db6..869fbb3d 100644 --- a/apcd-cms/src/client/src/utils/dateUtil.ts +++ b/apcd-cms/src/client/src/utils/dateUtil.ts @@ -13,3 +13,45 @@ export const formatDate = (dateString: string | number | Date): string => { hour12: true, }).format(date); }; + +/** + * + * @param period string - Jan. 2024 as example + * @returns string. 2024-01 for Jan. 2024. + */ +export const convertPeriodLabelToApiValue = (period: string): string | null => { + // Return as-is if already in expected format + if (/^\d{4}-(0[1-9]|1[0-2])$/.test(period)) { + return period; + } + const monthMap: Record = { + Jan: '01', + Feb: '02', + Mar: '03', + Apr: '04', + May: '05', + Jun: '06', + Jul: '07', + Aug: '08', + Sep: '09', + Oct: '10', + Nov: '11', + Dec: '12', + }; + + const match = period.match(/^([A-Za-z]{3})\.?\s(\d{4})$/); + if (!match) { + console.log(`Invalid period format: ${period}`); + return period; + } + + const [_, month, year] = match; + const numericMonth = monthMap[month]; + + if (!numericMonth) { + console.log(`Invalid month: ${month} in ${period}`); + return period; + } + + return `${year}-${numericMonth}`; +};