diff --git a/src/components/dashboard/dashboard.component.tsx b/src/components/dashboard/dashboard.component.tsx index ad23d9425..465203141 100644 --- a/src/components/dashboard/dashboard.component.tsx +++ b/src/components/dashboard/dashboard.component.tsx @@ -336,6 +336,19 @@ function FormsList({ forms, isValidating, mutate, t }: FormsListProps) { onChange={handleSearch} placeholder={t('searchThisList', 'Search this list')} /> + } + size={responsiveSize} + onClick={() => + navigate({ + to: `${window.spaBase}/form-builder/new?template=discharge-summary`, + }) + } + > + {t('dischargeSummary', 'Discharge Summary')} + = ({ return schema || dummySchema; }, [onSchemaChange, schema]); - const launchNewFormModal = useCallback(() => { - const schema = initializeSchema(); - const dispose = showModal('new-form-modal', { - closeModal: () => dispose(), - schema, - onSchemaChange, - }); - }, [onSchemaChange, initializeSchema]); + const launchNewFormModal = useCallback( + (templateId?: string) => { + const schema = initializeSchema(); + const dispose = showModal('new-form-modal', { + closeModal: () => dispose(), + schema, + onSchemaChange, + initialTemplate: templateId, + }); + }, + [onSchemaChange, initializeSchema], + ); const launchAddPageModal = useCallback(() => { const dispose = showModal('new-page-modal', { diff --git a/src/components/interactive-builder/modals/new-form/new-form.modal.tsx b/src/components/interactive-builder/modals/new-form/new-form.modal.tsx index 73b064331..d4b3a59ad 100644 --- a/src/components/interactive-builder/modals/new-form/new-form.modal.tsx +++ b/src/components/interactive-builder/modals/new-form/new-form.modal.tsx @@ -1,19 +1,34 @@ import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { Button, Form, FormGroup, ModalBody, ModalFooter, ModalHeader, Stack, TextInput } from '@carbon/react'; +import { + Button, + Form, + FormGroup, + ModalBody, + ModalFooter, + ModalHeader, + Stack, + TextInput, + Select, + SelectItem, + Tile, +} from '@carbon/react'; import { showSnackbar } from '@openmrs/esm-framework'; +import { formTemplates } from '@utils/form-templates'; import type { Schema } from '@types'; interface NewFormModalProps { schema: Schema; onSchemaChange: (schema: Schema) => void; closeModal: () => void; + initialTemplate?: string; } -const NewFormModal: React.FC = ({ schema, onSchemaChange, closeModal }) => { +const NewFormModal: React.FC = ({ schema, onSchemaChange, closeModal, initialTemplate }) => { const { t } = useTranslation(); const [formName, setFormName] = useState(''); const [formDescription, setFormDescription] = useState(''); + const [selectedTemplate, setSelectedTemplate] = useState(initialTemplate || 'blank'); const updateSchema = (updates: Partial) => { try { @@ -39,10 +54,24 @@ const NewFormModal: React.FC = ({ schema, onSchemaChange, clo const handleCreateForm = () => { if (formName) { - updateSchema({ - name: formName, - description: formDescription, - }); + if (selectedTemplate === 'blank') { + // Create blank form + updateSchema({ + name: formName, + description: formDescription, + }); + } else { + // Use selected template + const template = formTemplates.find((t) => t.id === selectedTemplate); + if (template) { + const templateSchema = JSON.parse(JSON.stringify(template.schema)); // Deep clone + updateSchema({ + ...templateSchema, + name: formName, + description: formDescription || template.description, + }); + } + } closeModal(); } @@ -54,6 +83,40 @@ const NewFormModal: React.FC = ({ schema, onSchemaChange, clo event.preventDefault()}> + + ) => { + const templateId = event.target.value; + setSelectedTemplate(templateId); + + // Auto-fill form details when template is selected + if (templateId !== 'blank') { + const template = formTemplates.find((t) => t.id === templateId); + if (template && !formName) { + setFormName(template.name); + setFormDescription(template.description); + } + } + }} + > + + {formTemplates.map((template) => ( + + ))} + + + + {selectedTemplate !== 'blank' && ( + + + {formTemplates.find((t) => t.id === selectedTemplate)?.description} + + + )} + template.id === templateId); +} + +/** + * Get all form templates for a specific category + * @param category The category to filter by + * @returns Array of form templates in the specified category + */ +export function getFormTemplatesByCategory(category: string): FormTemplate[] { + return formTemplates.filter((template) => template.category === category); +} + +/** + * Get all available template categories + * @returns Array of unique category names + */ +export function getTemplateCategories(): string[] { + return [...new Set(formTemplates.map((template) => template.category))]; +} diff --git a/tsconfig.json b/tsconfig.json index 0f11c09fb..c6ec31008 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -30,6 +30,7 @@ "@tools/*": ["./tools/*"], "@constants": ["./src/constants"], "@resources/*": ["./src/resources/*"], + "@utils/*": ["./src/utils/*"], "@openmrs/*": ["./node_modules/@openmrs/*"] } }, diff --git a/webpack.config.js b/webpack.config.js index 998f4863d..5f40f6a04 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -11,6 +11,7 @@ config.overrides.resolve = { '@resources': path.resolve(__dirname, 'src/resources/'), '@tools': path.resolve(__dirname, 'tools/'), '@constants$': path.resolve(__dirname, 'src/constants.ts'), + '@utils': path.resolve(__dirname, 'src/utils/'), }, }; module.exports = config;
+ {formTemplates.find((t) => t.id === selectedTemplate)?.description} +