From 773389adf4048f928b6261265fb7b217d4dfd2e7 Mon Sep 17 00:00:00 2001 From: barshathakuri Date: Wed, 21 Aug 2024 18:52:37 +0545 Subject: [PATCH] Add enhancement features --- app/src/utils/domain/dref.ts | 4 +- app/src/utils/importTemplate.ts | 69 ++++++---- .../DownloadImportTemplateModal/index.tsx | 124 +++++++----------- .../useImportTemplateSchema.ts | 100 +++++++------- .../DownloadImportTemplateButton/utils.ts | 78 +++++------ .../DrefTableActions/drefAllocationExport.ts | 6 +- .../DrefTableActions/index.tsx | 5 +- .../DrefImportModal/i18n.json | 11 ++ .../DrefImportModal/index.tsx | 37 +++--- .../DrefImportButton/i18n.json | 6 + .../DrefImportButton/index.tsx | 12 +- app/src/views/DrefApplicationForm/common.tsx | 1 + app/src/views/DrefApplicationForm/schema.ts | 1 - 13 files changed, 238 insertions(+), 216 deletions(-) create mode 100644 app/src/views/DrefApplicationForm/DrefImportButton/DrefImportModal/i18n.json create mode 100644 app/src/views/DrefApplicationForm/DrefImportButton/i18n.json diff --git a/app/src/utils/domain/dref.ts b/app/src/utils/domain/dref.ts index a6efb9f52..9cba111df 100644 --- a/app/src/utils/domain/dref.ts +++ b/app/src/utils/domain/dref.ts @@ -58,9 +58,9 @@ export const nsActionsOrder: Record = { other: 18, }; -export type DrefSheetName = 'Operation Overview' | 'Event Detail' | 'Actions-Needs' | 'Operation' | 'Timeframes and Contacts'; +export type DrefSheetName = 'Operation Overview' | 'Event Detail' | 'Actions Needs' | 'Operation' | 'Timeframes and Contacts'; export const SHEET_OPERATION_OVERVIEW = 'Operation Overview' satisfies DrefSheetName; export const SHEET_EVENT_DETAIL = 'Event Detail' satisfies DrefSheetName; -export const SHEET_ACTIONS_NEEDS = 'Actions-Needs' satisfies DrefSheetName; +export const SHEET_ACTIONS_NEEDS = 'Actions Needs' satisfies DrefSheetName; export const SHEET_OPERATION = 'Operation' satisfies DrefSheetName; export const SHEET_TIMEFRAMES_AND_CONTACTS = 'Timeframes and Contacts' satisfies DrefSheetName; diff --git a/app/src/utils/importTemplate.ts b/app/src/utils/importTemplate.ts index 44d0d8460..c2c0aa46c 100644 --- a/app/src/utils/importTemplate.ts +++ b/app/src/utils/importTemplate.ts @@ -5,16 +5,18 @@ import { isObject, listToMap, mapToMap, + randomString, } from '@togglecorp/fujs'; -type ValidationType = string | number | boolean; +type ValidationType = string | number | boolean | 'textArea'; type TypeToLiteral = T extends string - ? 'string' | 'date' + ? 'string' | 'date' | 'textArea' : T extends number - ? 'integer' | 'number' - : T extends boolean - ? 'boolean' - : never; + ? 'integer' | 'number' + : T extends boolean + ? 'boolean' + : never; + type ExtractValidation = T extends ValidationType ? T : never; @@ -22,6 +24,7 @@ type ExtractValidation = T extends ValidationType interface BaseField { label: string; description?: string; + headingBefore?: string; } interface InputField< @@ -40,8 +43,8 @@ interface SelectField< // Make this more strict optionsKey: { [key in keyof OPTIONS_MAPPING]: VALIDATION extends OPTIONS_MAPPING[key][number]['key'] - ? key - : never + ? key + : never }[keyof OPTIONS_MAPPING] } @@ -76,8 +79,8 @@ export interface TemplateOptionItem { export interface TemplateFieldOptionsMapping { [key: string]: TemplateOptionItem[] - | TemplateOptionItem[] - | TemplateOptionItem[] + | TemplateOptionItem[] + | TemplateOptionItem[] } export type TemplateSchema< @@ -86,13 +89,13 @@ export type TemplateSchema< > = VALUE extends (infer LIST_ITEM)[] ? ( ListField - | InputField> - | SelectField, OPTIONS_MAPPING> + | InputField> + | SelectField, OPTIONS_MAPPING> ) : ( VALUE extends object - ? ObjectField - : (InputField> - | SelectField, OPTIONS_MAPPING>) + ? ObjectField + : (InputField> + | SelectField, OPTIONS_MAPPING>) ); interface HeadingTemplateField { @@ -111,11 +114,12 @@ type InputTemplateField = { label: string; outlineLevel: number; description?: string; + headingBefore?: string; } & ({ dataValidation: 'list'; optionsKey: ObjectKey; } | { - dataValidation?: 'number' | 'integer' | 'date'; + dataValidation?: 'number' | 'integer' | 'date' | 'textArea'; optionsKey?: never; }) @@ -168,19 +172,31 @@ export function createImportTemplate< return []; } + const fields: TemplateField[] = []; + + if (isDefined(schema.headingBefore)) { + fields.push({ + type: 'heading', + name: `${fieldName}__headingBefore`, + label: schema.headingBefore, + outlineLevel, + } satisfies HeadingTemplateField); + } + if (schema.type === 'input') { const field = { type: 'input', name: fieldName, label: schema.label, description: schema.description, - dataValidation: (schema.validation === 'number' || schema.validation === 'date' || schema.validation === 'integer') + dataValidation: (schema.validation === 'number' || schema.validation === 'date' || schema.validation === 'integer' || schema.validation === 'textArea') ? schema.validation : undefined, outlineLevel, } satisfies InputTemplateField; - return [field]; + fields.push(field); + return fields; } if (schema.type === 'select') { @@ -194,7 +210,8 @@ export function createImportTemplate< optionsKey: schema.optionsKey, } satisfies InputTemplateField; - return [field]; + fields.push(field); + return fields; } const headingField = { @@ -234,6 +251,7 @@ export function createImportTemplate< }); return [ + ...fields, headingField, ...optionFields, ]; @@ -246,7 +264,7 @@ export function getValueFromImportTemplate< >( schema: TemplateSchema, optionsMap: OPTIONS_MAPPING, - formValues: Record, + formValues: Record, fieldName: string | undefined = undefined, ): unknown { const optionsReverseMap = mapToMap( @@ -291,7 +309,7 @@ export function getValueFromImportTemplate< const value = formValues[fieldName]; const valueKey = optionsReverseMap[ schema.optionsKey as string - ]?.[value]; + ]?.[String(value)]; // TODO: add validation from schema.validation return valueKey; } @@ -308,12 +326,17 @@ export function getValueFromImportTemplate< ); if (isObject(value) && hasSomeDefinedValue(value)) { + if (schema.keyFieldName) { + return { + [schema.keyFieldName]: option.key, + ...value, + }; + } return { - [schema.keyFieldName ?? 'client_id']: option.key, + client_id: randomString(), ...value, }; } - return undefined; }).filter(isDefined); diff --git a/app/src/views/AccountMyFormsDref/DownloadImportTemplateButton/DownloadImportTemplateModal/index.tsx b/app/src/views/AccountMyFormsDref/DownloadImportTemplateButton/DownloadImportTemplateModal/index.tsx index 7796d4765..aec44a0ea 100644 --- a/app/src/views/AccountMyFormsDref/DownloadImportTemplateButton/DownloadImportTemplateModal/index.tsx +++ b/app/src/views/AccountMyFormsDref/DownloadImportTemplateButton/DownloadImportTemplateModal/index.tsx @@ -57,8 +57,8 @@ import useImportTemplateSchema from './useImportTemplateSchema'; import i18n from './i18n.json'; -function typeOfDrefKeySelector(option: { key: TypeOfDrefEnum }) { - return option.key; +function typeOfDrefKeySelector(option: { value: TypeOfDrefEnum }) { + return option.value; } async function generateTemplate( @@ -72,60 +72,46 @@ async function generateTemplate( const now = new Date(); workbook.created = now; + const typeOfDrefLabel = drefTypeLabelMap?.[typeOfDref ?? DREF_TYPE_RESPONSE] ?? ''; + + const coverWorksheet = workbook.addWorksheet( + 'DREF Import', + { properties: { tabColor: { argb: hexToArgb(COLOR_PRIMARY_RED, '10') } } }, + ); + await buildCoverWorksheet(coverWorksheet, workbook); + const fieldNameToTabNameMap: Record = { ...listToMap( overviewTabFields, - (key) => key, + (key) => key as string, () => SHEET_OPERATION_OVERVIEW, ), ...listToMap( eventDetailTabFields, - (key) => key, + (key) => key as string, () => SHEET_EVENT_DETAIL, ), ...listToMap( actionsTabFields, - (key) => key, + (key) => key as string, () => SHEET_ACTIONS_NEEDS, ), ...listToMap( operationTabFields, - (key) => key, + (key) => key as string, () => SHEET_OPERATION, ), ...listToMap( timeframeAndContactsTabFields, - (key) => key, + (key) => key as string, () => SHEET_TIMEFRAMES_AND_CONTACTS, ), }; - /* - const description: ImportTemplateDescription = { - application: 'ifrc-go', - templateName: 'dref-application', - meta: { - typeOfDref: 'response', - }, - fieldNameToTabNameMap, - }; - - workbook.description = JSON.stringify(description); - */ - - const typeOfDrefLabel = drefTypeLabelMap?.[typeOfDref ?? DREF_TYPE_RESPONSE] ?? ''; - - const coverWorksheet = workbook.addWorksheet( - 'DREF Import', - { properties: { tabColor: { argb: hexToArgb(COLOR_PRIMARY_RED, '10') } } }, - ); - await buildCoverWorksheet(coverWorksheet, workbook, typeOfDrefLabel); - const overviewWorksheet = workbook.addWorksheet( SHEET_OPERATION_OVERVIEW, { properties: { tabColor: { argb: hexToArgb(COLOR_PRIMARY_RED, '10') } } }, ); - // TODO: Add red color to all the sheet tabs const eventDetailsWorksheet = workbook.addWorksheet( SHEET_EVENT_DETAIL, { properties: { tabColor: { argb: hexToArgb(COLOR_PRIMARY_RED, '10') } } }, @@ -152,7 +138,7 @@ async function generateTemplate( }; const optionsWorksheet = workbook.addWorksheet('options'); - optionsWorksheet.state = 'veryHidden'; + // optionsWorksheet.state = 'veryHidden'; const optionKeys = Object.keys(optionsMap) as (keyof (typeof optionsMap))[]; optionsWorksheet.columns = optionKeys.map((key) => ( @@ -165,23 +151,26 @@ async function generateTemplate( if (isDefined(options)) { const column = optionsWorksheet.getColumnKey(key); - options.forEach((option, i) => { + options.forEach((option: TypeOfDrefEnum, i: number) => { const cell = optionsWorksheet.getCell(i + 2, column.number); - cell.name = String(option.key); + cell.name = `${key}____${option.key}`; cell.value = option.label; }); } }); - const tabGroupedTemplateActions = mapToList( - listToGroupList( + function groupTemplateActionsByTab() { + return listToGroupList( templateActions, (templateAction) => { const fieldName = String(templateAction.name).split('__')[0]; - const tabName = fieldNameToTabNameMap[fieldName]; - return tabName; + return fieldNameToTabNameMap[fieldName]; }, - ), + ); + } + + const tabGroupedTemplateActions = mapToList( + groupTemplateActionsByTab(), (actions, tabName) => { const worksheet = workbook.getWorksheet(tabName); if (isNotDefined(worksheet)) { @@ -212,10 +201,12 @@ async function generateTemplate( worksheet.mergeCells(i + ROW_OFFSET, 1, i + ROW_OFFSET, 3); lastHeadingIndex = i + 1; } else if (templateAction.type === 'input') { - const mode = (i - lastHeadingIndex) % 2 === 0 ? 'one' : 'two'; + // NOTE: Determines the headingLevel based on the index + // position relative to the last heading, list heading is for list section. + const headingLevel = (i - lastHeadingIndex) % 2 === 0 ? 'listHeading' : 'heading'; if (templateAction.dataValidation === 'list') { addInputRow( - mode, + headingLevel, worksheet, i + ROW_OFFSET, templateAction.outlineLevel, @@ -226,9 +217,22 @@ async function generateTemplate( String(templateAction.optionsKey), optionsWorksheet, ); + } else if (templateAction.dataValidation === 'textArea') { + addInputRow( + headingLevel, + worksheet, + i + ROW_OFFSET, + templateAction.outlineLevel, + String(templateAction.name), + templateAction.label, + templateAction.description, + 'text', + ); + const row = worksheet.getRow(i + ROW_OFFSET); + row.height = 100; } else { addInputRow( - mode, + headingLevel, worksheet, i + ROW_OFFSET, templateAction.outlineLevel, @@ -245,7 +249,7 @@ async function generateTemplate( Object.values(sheetMap).forEach( (sheet) => { const worksheet = sheet; - worksheet.properties.defaultRowHeight = 20; + worksheet.properties.defaultRowHeight = 30; worksheet.properties.showGridLines = false; worksheet.columns = [ @@ -254,11 +258,12 @@ async function generateTemplate( header: 'Field', protection: { locked: true }, width: 50, + style: { alignment: { wrapText: true } }, }, { key: 'value', header: 'Value', - width: 100, + width: 85, style: { alignment: { wrapText: true } }, }, { @@ -274,43 +279,16 @@ async function generateTemplate( cell.style = headerRowStyle; }, ); - - /* - worksheet.eachRow({ includeEmpty: true }, (row, rowNumber) => { - if (rowNumber <= 1) { // Skip the header row - return; - } - - const fillColor = rowNumber % 2 === 0 - ? hexToArgb(COLOR_PRIMARY_RED, '10') - : ; - - row.eachCell((cell) => { - const fill: xlsx.FillPattern = { - type: 'pattern', - pattern: 'solid', - fgColor: { argb: fillColor }, - }; - // eslint-disable-next-line no-param-reassign - cell.style = { - font: { - color: { argb: 'FFFFFFFF' }, - }, - fill, - }; - }); - }); - */ }, ); - const templateFileName = `DREF Application ${typeOfDrefLabel} import template ${now.toLocaleString()}.xlsx`; + const templateFileName = `DREF_Application_${typeOfDrefLabel}_import_template_${now.toLocaleString()}.xlsx`; await workbook.xlsx.writeBuffer().then( (sheet) => { FileSaver.saveAs( new Blob([sheet], { type: 'application/vnd.ms-excel;charset=utf-8' }), - templateFileName, + templateFileName.replace(' ', '_'), ); }, ); @@ -336,10 +314,10 @@ function DownloadImportTemplateModal(props: Props) { const drefTypeLabelMap = useMemo( () => ( - listToMap( + listToMap( dref_dref_dref_type, (option) => option.key, - (option) => option.value, + (option) => option.label, ) ), [dref_dref_dref_type], diff --git a/app/src/views/AccountMyFormsDref/DownloadImportTemplateButton/DownloadImportTemplateModal/useImportTemplateSchema.ts b/app/src/views/AccountMyFormsDref/DownloadImportTemplateButton/DownloadImportTemplateModal/useImportTemplateSchema.ts index 7f0daeada..2ee7747fd 100644 --- a/app/src/views/AccountMyFormsDref/DownloadImportTemplateButton/DownloadImportTemplateModal/useImportTemplateSchema.ts +++ b/app/src/views/AccountMyFormsDref/DownloadImportTemplateButton/DownloadImportTemplateModal/useImportTemplateSchema.ts @@ -1,7 +1,7 @@ import { useMemo } from 'react'; import useCountry from '#hooks/domain/useCountry'; -import useDisasterTypes from '#hooks/domain/useDisasterType'; +import useDisasterTypes, { DisasterType } from '#hooks/domain/useDisasterType'; import useGlobalEnums from '#hooks/domain/useGlobalEnums'; import useNationalSociety from '#hooks/domain/useNationalSociety'; import { type TemplateSchema } from '#utils/importTemplate'; @@ -38,7 +38,7 @@ function useImportTemplateSchema() { ({ id, name }) => ({ key: id, label: name }), ), disaster_type: disasterTypes?.map( - ({ id, name }) => ({ key: id, label: name }), + ({ id, name }: DisasterType) => ({ key: id, label: name }), ) ?? [], type_of_onset: dref_dref_onset_type?.map( ({ key, value }) => ({ key, label: value }), @@ -56,7 +56,7 @@ function useImportTemplateSchema() { { key: 'source__3', label: 'Source #4' }, { key: 'source__4', label: 'Source #5' }, ], - planned_interventions__indicators: [ + planned_interventions_indicators: [ { key: 'indicator__0', label: 'Indicator #1' }, { key: 'indicator__1', label: 'Indicator #2' }, { key: 'indicator__2', label: 'Indicator #3' }, @@ -95,6 +95,7 @@ function useImportTemplateSchema() { label: 'National society', validation: 'number', optionsKey: 'national_society', + headingBefore: 'Essential Information', }, // We're skipping type of DREF since we'll have separate @@ -158,6 +159,7 @@ function useImportTemplateSchema() { label: 'Has a similar event affected the same area(s) in the last 3 years?', optionsKey: '__boolean', validation: 'boolean', + headingBefore: 'Previous Operation', }, did_it_affect_same_population: { @@ -194,21 +196,22 @@ function useImportTemplateSchema() { dref_recurrent_text: { type: 'input', label: 'If you have answered yes to all questions above, justify why the use of DREF for a recurrent event, or how this event should not be considered recurrent', - validation: 'string', - description: 'Enter MDR code and year. Example: MDR', + validation: 'textArea', }, lessons_learned: { type: 'input', label: 'Lessons Learned', - validation: 'string', + validation: 'textArea', description: 'Specify how the lessons learnt from these previous operations are being used to mitigate similar challenges in the current operation', }, event_date: { type: 'input', - label: 'Date when the trigger was met', + label: 'Date of the Event / Date when the trigger was met', validation: 'date', + headingBefore: 'Description of the Event', + description: 'When the `Type of Onset` is Slow, we store the input date as `Date when the trigger was met. When the `Type of Onset` is Sudden, we store the input date as `Date of the Event`.', }, num_affected: { @@ -227,13 +230,13 @@ function useImportTemplateSchema() { event_description: { type: 'input', - validation: 'string', + validation: 'textArea', label: 'What happened, where and when?', }, event_scope: { type: 'input', - validation: 'string', + validation: 'textArea', label: 'Scope and scale of the event', description: 'Describe the extent this hazard will produce negative impacts on lives, livelihoods, well-being and infrastructure. Explain which people are most likely to experience the impacts of this hazard? Where do they live, and why are they vulnerable? Please explain which groups (e.g elderly, children, people with disabilities, IDPs, Refugees, etc.) are most likely to be affected? Provide historic information on how communities have been affected by the magnitude of this hazard in the past?', }, @@ -241,8 +244,8 @@ function useImportTemplateSchema() { source_information: { type: 'list', label: 'Source Information', - optionsKey: 'source_information', description: 'Add the links and the name of the sources, the name will be shown in the export, as an hyperlink.', + optionsKey: 'source_information', children: { type: 'object', fields: { @@ -255,6 +258,7 @@ function useImportTemplateSchema() { type: 'input', validation: 'string', label: 'Link', + description: 'Add the links and the name of the sources, the name will be shown in the export, as an hyperlink.', }, }, }, @@ -265,6 +269,7 @@ function useImportTemplateSchema() { validation: 'boolean', optionsKey: '__boolean', label: 'Has the National Society started any actions?', + headingBefore: 'Current National Society Actions', }, ns_respond_date: { @@ -284,7 +289,7 @@ function useImportTemplateSchema() { fields: { description: { type: 'input', - validation: 'string', + validation: 'textArea', label: 'Description', }, }, @@ -293,23 +298,25 @@ function useImportTemplateSchema() { ifrc: { type: 'input', - validation: 'string', + validation: 'textArea', label: 'IFRC', description: 'Presence or not of IFRC in country (if not, indicate the cluster covering), support provided for this response, domestic coordination, technical, strategic, surge. Explain what support provided in terms of Secretariat services: PMER, Finance, Admin, HR, Security, logistics, NSD.', + headingBefore: 'IFRC Network Actions Related To The Current Event', }, partner_national_society: { type: 'input', - validation: 'string', + validation: 'textArea', label: 'Participating National Societies', description: 'Briefly set out which PNS are present and give details of PNS contributions/roles on the ground and remotely for this specific operation', }, icrc: { type: 'input', - validation: 'string', + validation: 'textArea', label: 'ICRC', description: 'Presence or not of ICRC in country, and support directly provided for this emergency response. Other programs and support provided outside of the scope of this emergency should not be indicated here.', + headingBefore: 'ICRC Actions Related To The Current Event', }, government_requested_assistance: { @@ -317,17 +324,18 @@ function useImportTemplateSchema() { validation: 'boolean', optionsKey: '__boolean', label: 'Government has requested international assistance', + headingBefore: 'Other Actors Actions Related To The Current Event', }, national_authorities: { type: 'input', - validation: 'string', + validation: 'textArea', label: 'National authorities', }, un_or_other_actor: { type: 'input', - validation: 'string', + validation: 'textArea', label: 'UN or other actors', }, @@ -346,14 +354,15 @@ function useImportTemplateSchema() { needs_identified: { type: 'list', - label: 'Identified Needs', + label: 'Needs (Gaps) Identified', + keyFieldName: 'title', optionsKey: 'needs_identified', children: { type: 'object', fields: { description: { type: 'input', - validation: 'string', + validation: 'textArea', label: 'Description', }, }, @@ -362,33 +371,35 @@ function useImportTemplateSchema() { identified_gaps: { type: 'input', - validation: 'string', + validation: 'textArea', label: 'Any identified gaps/limitations in the assessment', }, // Operation operation_objective: { type: 'input', - validation: 'string', + validation: 'textArea', label: 'Overall objective of the operation', + headingBefore: 'Objective and Strategy Rationale', }, response_strategy: { type: 'input', - validation: 'string', + validation: 'textArea', label: 'Operation strategy rationale', }, people_assisted: { type: 'input', - validation: 'string', + validation: 'textArea', label: 'Who will be targeted through this operation?', description: 'Explain the logic behind our targets. Which groups are we targeting and why are we targeting these particular groups? Explain how you will target vulnerable groups (e.g., Migrants, refugees, etc.)', + headingBefore: 'Targeting Strategy', }, selection_criteria: { type: 'input', - validation: 'string', + validation: 'textArea', label: 'Explain the selection criteria for the targeted population', description: 'Explain the rational and logic behind which groups are being targeted and why and address vulnerable groups', }, @@ -397,6 +408,7 @@ function useImportTemplateSchema() { type: 'input', validation: 'number', label: 'Targeted Population: Women', + headingBefore: 'Total Targeted Population', }, men: { @@ -449,7 +461,7 @@ function useImportTemplateSchema() { risk_security: { type: 'list', - label: 'Please indicate about potential operational risk for this operations and mitigation actions', + label: 'Risk and security considerations', optionsKey: 'risk_security', children: { type: 'object', @@ -470,7 +482,7 @@ function useImportTemplateSchema() { risk_security_concern: { type: 'input', - validation: 'string', + validation: 'textArea', label: 'Please indicate any security and safety concerns for this operation', }, @@ -486,11 +498,12 @@ function useImportTemplateSchema() { type: 'input', validation: 'number', label: 'Requested Amount in CHF', + headingBefore: 'Planned Interventions', }, planned_interventions: { type: 'list', - label: 'Planned interventions', + label: 'Add the interventions that apply', optionsKey: 'planned_interventions', keyFieldName: 'title', children: { @@ -507,7 +520,7 @@ function useImportTemplateSchema() { label: 'Person targeted', }, description: { - description: 'A list should start with an \' * \' followed by a space. There are no limits to the number of lists that can be included. Eg:* Activity XYZ* Activity ABC', + description: 'A list should start with an \' * \' followed by a space. There are no limits to the number of lists that can be included. \n Eg: \n * Activity XYZ \n * Activity ABC', type: 'input', validation: 'string', label: 'List of activities', @@ -515,7 +528,7 @@ function useImportTemplateSchema() { indicators: { type: 'list', label: 'Indicators', - optionsKey: 'planned_interventions__indicators', + optionsKey: 'planned_interventions_indicators', children: { type: 'object', fields: { @@ -538,8 +551,9 @@ function useImportTemplateSchema() { human_resource: { type: 'input', - validation: 'string', + validation: 'textArea', label: 'How many staff and volunteers will be involved in this operation. Briefly describe their role.', + headingBefore: 'About Support Services', }, is_surge_personnel_deployed: { @@ -558,21 +572,21 @@ function useImportTemplateSchema() { logistic_capacity_of_ns: { type: 'input', - validation: 'string', + validation: 'textArea', label: 'If there is procurement, will be done by National Society or IFRC?', description: 'Will it be for replenishment or for distribution? If for distribution, how long is the tendering expected to take? For Cash and Voucher Assistance, what is the status of the Financial Service Provider?', }, pmer: { type: 'input', - validation: 'string', + validation: 'textArea', label: 'How will this operation be monitored?', description: 'Will there be IFRC monitoring visits? How will it be deployed?', }, communication: { type: 'input', - validation: 'string', + validation: 'textArea', label: 'Please briefly explain the National Societies communication strategy for this operation.', description: 'Will the IFRC be supporting with communication? What roles will be involved?', }, @@ -582,20 +596,7 @@ function useImportTemplateSchema() { type: 'input', validation: 'date', label: 'Date of National Society Application', - }, - - submission_to_geneva: { - type: 'input', - validation: 'date', - label: 'Date of Submission to GVA', - description: 'Added by Regional Office', - }, - - date_of_approval: { - type: 'input', - validation: 'date', - label: 'Date of Approval', - description: 'Added by Regional Office', + headingBefore: 'Operational Timeframes', }, operation_timeframe: { @@ -603,13 +604,6 @@ function useImportTemplateSchema() { validation: 'number', label: 'Operation timeframe', }, - - publishing_date: { - type: 'input', - validation: 'date', - label: 'Date of Publishing', - description: 'Added by Regional Office', - }, }, }), []); diff --git a/app/src/views/AccountMyFormsDref/DownloadImportTemplateButton/utils.ts b/app/src/views/AccountMyFormsDref/DownloadImportTemplateButton/utils.ts index b88e1f6b4..6b4f3f6b2 100644 --- a/app/src/views/AccountMyFormsDref/DownloadImportTemplateButton/utils.ts +++ b/app/src/views/AccountMyFormsDref/DownloadImportTemplateButton/utils.ts @@ -14,6 +14,7 @@ import { COLOR_LIGHT_GREY, COLOR_PRIMARY_BLUE, COLOR_PRIMARY_RED, + COLOR_WHITE, } from '#utils/constants'; export function hexToArgb(hexStr: string, alphaStr = 'ff') { @@ -24,7 +25,7 @@ export function hexToArgb(hexStr: string, alphaStr = 'ff') { export const headerRowStyle: Partial