diff --git a/backend/src/db/migrations/20260127000000-add-final-approval-status.js b/backend/src/db/migrations/20260127000000-add-final-approval-status.js new file mode 100644 index 0000000..bf564b6 --- /dev/null +++ b/backend/src/db/migrations/20260127000000-add-final-approval-status.js @@ -0,0 +1,8 @@ +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.sequelize.query(`ALTER TYPE "enum_leads_status" ADD VALUE IF NOT EXISTS 'FinalApproval' AFTER 'Validation'`); + }, + down: async (queryInterface, Sequelize) => { + // ENUM values cannot be easily removed in Postgres without dropping the type + } +}; diff --git a/backend/src/db/models/leads.js b/backend/src/db/models/leads.js index e436b3e..c3fc67f 100644 --- a/backend/src/db/models/leads.js +++ b/backend/src/db/models/leads.js @@ -85,7 +85,7 @@ status: { "UnderwritingReview", -"Validation", +"Validation", "FinalApproval", "KickOff", diff --git a/backend/src/services/leads.js b/backend/src/services/leads.js index 4aff6d5..f5811e2 100644 --- a/backend/src/services/leads.js +++ b/backend/src/services/leads.js @@ -7,14 +7,15 @@ const axios = require('axios'); const config = require('../config'); const stream = require('stream'); - - - - module.exports = class LeadsService { static async create(data, currentUser) { const transaction = await db.sequelize.transaction(); try { + // Auto-calculate Fast Track + if (data.threshold_amount !== undefined) { + data.is_fast_track = Number(data.threshold_amount) < 250000; + } + await LeadsDBApi.create( data, { @@ -79,6 +80,109 @@ module.exports = class LeadsService { ); } + // Auto-calculate Fast Track + if (data.threshold_amount !== undefined) { + data.is_fast_track = Number(data.threshold_amount) < 250000; + } + + // Workflow Transition Logic: Move to Step 2 (Pricing) + if (data.status === 'PricingReview' && (leads.status === 'Draft' || leads.status === 'Submitted')) { + const existingTask = await db.tasks.findOne({ where: { leadId: id, title: { [db.Sequelize.Op.like]: 'Pricing Review%' } }, transaction }); + if (!existingTask) { + await db.tasks.create({ + title: 'Pricing Review for ' + (data.title || leads.title), + description: 'Provide pricing for Actuarial or Underwriter review.', + status: 'Todo', + leadId: id, + createdById: currentUser.id, + updatedById: currentUser.id, + }, { transaction }); + } + } + + // Workflow Transition Logic: Move to Step 3 (Validation) + if (data.status === 'Validation' && leads.status === 'PricingReview') { + const approvalTitle = leads.is_fast_track + ? 'Fast Track Validation (CPO/CEO/Underwriter)' + : 'Regular Track Validation (MNPC Pre-validation)'; + + const existingApproval = await db.approvals.findOne({ where: { leadId: id, approval_title: approvalTitle }, transaction }); + if (!existingApproval) { + await db.approvals.create({ + approval_title: approvalTitle, + status: 'Pending', + leadId: id, + createdById: currentUser.id, + updatedById: currentUser.id, + }, { transaction }); + } + } + + // Workflow Transition Logic: Move to Step 5 (Dept Tasks) + if (data.status === 'UnderwritingReview' && leads.status === 'KickOff') { + const departmentTasks = [ + { title: 'Pricing Validation', description: 'Pricing Validation by Actuarial/Underwriting' }, + { title: 'Operations Check', description: 'Operations check and High Level review of GTCs, Policy subscription (premium collection, refunds etc)' }, + { title: 'Claims Handling Validation', description: 'Claims Handling processes for validation' }, + { title: 'Finance Check', description: 'Finance Check and validation regarding Financial Flows, Tax Payment, Commission Distribution, Claims Fund and Frequency of payments' }, + { title: 'Compliance Check', description: 'Check and validation of GTC, GDPR and any relevant Compliance topic' }, + { title: 'Risk Review', description: 'Review and Validation of adherence to risk profile of OIL and underwriting guidelines' }, + { title: 'Legal Creation/Review', description: 'Creation/Review of general terms and conditions and validation of contracts and annexes' }, + { title: 'IT Connectivity Confirm', description: 'Confirm connectivity, SAP, data templates agreed or if changes are required' }, + ]; + + for (const taskData of departmentTasks) { + const existingTask = await db.tasks.findOne({ + where: { + leadId: id, + title: taskData.title + }, + transaction + }); + + if (!existingTask) { + await db.tasks.create({ + ...taskData, + status: 'Todo', + leadId: id, + createdById: currentUser.id, + updatedById: currentUser.id, + }, { transaction }); + } + } + } + + // Workflow Transition Logic: Move to Step 6 (Final MNPC Approval) + if (data.status === 'FinalApproval' && leads.status === 'UnderwritingReview') { + const approvalTitle = 'Final MNPC Approval (Post-Dept Tasks)'; + const existingApproval = await db.approvals.findOne({ where: { leadId: id, approval_title: approvalTitle }, transaction }); + if (!existingApproval) { + await db.approvals.create({ + approval_title: approvalTitle, + status: 'Pending', + leadId: id, + createdById: currentUser.id, + updatedById: currentUser.id, + }, { transaction }); + } + } + + // Workflow Transition Logic: Move to Step 7 (Monitoring / Launched) + if (data.status === 'Launched' && leads.status === 'FinalApproval') { + const reportTitle = 'Initial After-Launch Monitoring'; + const existingReport = await db.monitoring_reports.findOne({ where: { leadId: id, report_title: reportTitle }, transaction }); + if (!existingReport) { + await db.monitoring_reports.create({ + report_title: reportTitle, + leadId: id, + period_start: new Date(), + adherence_score: 100, + created_byId: currentUser.id, + organizationsId: currentUser.organizationId || currentUser.organizationsId, + }, { transaction }); + } + } + const updatedLeads = await LeadsDBApi.update( id, data, @@ -132,7 +236,5 @@ module.exports = class LeadsService { } } - + }; - - diff --git a/frontend/src/components/Leads/ProgramWorkflow.tsx b/frontend/src/components/Leads/ProgramWorkflow.tsx new file mode 100644 index 0000000..797232e --- /dev/null +++ b/frontend/src/components/Leads/ProgramWorkflow.tsx @@ -0,0 +1,71 @@ +import React from 'react' +import { mdiCheckCircle, mdiCircleOutline, mdiClockOutline } from '@mdi/js' +import BaseIcon from '../BaseIcon' + +const workflowSteps = [ + { label: 'Documentation', status: 'Submitted' }, + { label: 'Pricing', status: 'PricingReview' }, + { label: 'Validation', status: 'Validation' }, + { label: 'Kick Off', status: 'KickOff' }, + { label: 'Dept Tasks', status: 'UnderwritingReview' }, + { label: 'Final Approval', status: 'FinalApproval' }, + { label: 'Monitoring', status: 'Launched' }, +] + +interface Props { + currentStatus: string +} + +export default function ProgramWorkflow({ currentStatus }: Props) { + const currentIndex = workflowSteps.findIndex((s) => s.status === currentStatus) + // Fallback for Draft + const effectiveIndex = currentStatus === 'Draft' ? 0 : currentIndex + + return ( +
+
+ {workflowSteps.map((step, index) => { + const isCompleted = index < effectiveIndex + const isActive = index === effectiveIndex + const isPending = index > effectiveIndex + + return ( + +
+
+ +
+
+ {step.label} +
+
+ {index < workflowSteps.length - 1 && ( +
+ )} + + ) + })} +
+
{/* Spacer for labels */} +
+ ) +} diff --git a/frontend/src/pages/lead_checklists/lead_checklists-new.tsx b/frontend/src/pages/lead_checklists/lead_checklists-new.tsx index b3b0b1f..d4e6908 100644 --- a/frontend/src/pages/lead_checklists/lead_checklists-new.tsx +++ b/frontend/src/pages/lead_checklists/lead_checklists-new.tsx @@ -1,4 +1,4 @@ -import { mdiAccount, mdiChartTimelineVariant, mdiMail, mdiUpload } from '@mdi/js' +import { mdiChartTimelineVariant } from '@mdi/js' import Head from 'next/head' import React, { ReactElement } from 'react' import CardBox from '../../components/CardBox' @@ -12,399 +12,88 @@ import FormField from '../../components/FormField' import BaseDivider from '../../components/BaseDivider' import BaseButtons from '../../components/BaseButtons' import BaseButton from '../../components/BaseButton' -import FormCheckRadio from '../../components/FormCheckRadio' -import FormCheckRadioGroup from '../../components/FormCheckRadioGroup' -import FormFilePicker from '../../components/FormFilePicker' -import FormImagePicker from '../../components/FormImagePicker' import { SwitchField } from '../../components/SwitchField' import { SelectField } from '../../components/SelectField' -import { SelectFieldMany } from "../../components/SelectFieldMany"; -import {RichTextField} from "../../components/RichTextField"; - import { create } from '../../stores/lead_checklists/lead_checklistsSlice' import { useAppDispatch } from '../../stores/hooks' import { useRouter } from 'next/router' -import moment from 'moment'; - -const initialValues = { - - - - - - - - - - - - - - lead: '', - - - - - item: '', - - - - - - - - - - - - - - - - - detail: '', - - - - - - - - - - - - - - - - - - - - - completed: false, - - - - - - - - - - - - - - - - - - - - - completed_by: '', - - - - - - - - - - due_date: '', - - - - - - - - - - - - - - - - - - - - - - organizations: '', - - - -} - const Lead_checklistsNew = () => { const router = useRouter() const dispatch = useAppDispatch() + const { leadId } = router.query - - + const initialValues = { + lead: leadId || '', + item: '', + detail: '', + completed: false, + completed_by: '', + due_date: '', + organizations: '', + } const handleSubmit = async (data) => { await dispatch(create(data)) - await router.push('/lead_checklists/lead_checklists-list') + if (leadId) { + await router.push(`/leads/${leadId}`) + } else { + await router.push('/lead_checklists/lead_checklists-list') + } } + return ( <> - {getPageTitle('New Item')} + {getPageTitle('New Checklist Item')} - + {''} handleSubmit(values)} >
+ + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - + - router.push('/lead_checklists/lead_checklists-list')}/> + leadId ? router.push(`/leads/${leadId}`) : router.push('/lead_checklists/lead_checklists-list')} + />
@@ -416,14 +105,10 @@ const Lead_checklistsNew = () => { Lead_checklistsNew.getLayout = function getLayout(page: ReactElement) { return ( - - {page} - + + {page} + ) } -export default Lead_checklistsNew +export default Lead_checklistsNew \ No newline at end of file diff --git a/frontend/src/pages/lead_evaluations/lead_evaluations-new.tsx b/frontend/src/pages/lead_evaluations/lead_evaluations-new.tsx index f616a47..6616ffb 100644 --- a/frontend/src/pages/lead_evaluations/lead_evaluations-new.tsx +++ b/frontend/src/pages/lead_evaluations/lead_evaluations-new.tsx @@ -1,4 +1,4 @@ -import { mdiAccount, mdiChartTimelineVariant, mdiMail, mdiUpload } from '@mdi/js' +import { mdiChartTimelineVariant } from '@mdi/js' import Head from 'next/head' import React, { ReactElement } from 'react' import CardBox from '../../components/CardBox' @@ -12,505 +12,104 @@ import FormField from '../../components/FormField' import BaseDivider from '../../components/BaseDivider' import BaseButtons from '../../components/BaseButtons' import BaseButton from '../../components/BaseButton' -import FormCheckRadio from '../../components/FormCheckRadio' -import FormCheckRadioGroup from '../../components/FormCheckRadioGroup' -import FormFilePicker from '../../components/FormFilePicker' -import FormImagePicker from '../../components/FormImagePicker' import { SwitchField } from '../../components/SwitchField' import { SelectField } from '../../components/SelectField' -import { SelectFieldMany } from "../../components/SelectFieldMany"; import {RichTextField} from "../../components/RichTextField"; import { create } from '../../stores/lead_evaluations/lead_evaluationsSlice' import { useAppDispatch } from '../../stores/hooks' import { useRouter } from 'next/router' -import moment from 'moment'; - -const initialValues = { - - - - - - - - - - - - - - lead: '', - - - - - - - - - - - - - - part: 'Part1', - - - - - - - - - - - - - - - - - - - evaluator: '', - - - - - - summary: '', - - - - - - - - - - - - - - - - - notes: '', - - - - - - - - - - - - - - - - - score: '', - - - - - - - - - - - - - - - - - - - approved: false, - - - - - - - - - - - - - - - evaluation_date: '', - - - - - - - - - - - - - - - - - - - - - - organizations: '', - - - -} - const Lead_evaluationsNew = () => { const router = useRouter() const dispatch = useAppDispatch() + const { leadId } = router.query - - + const initialValues = { + lead: leadId || '', + part: 'Part1', + evaluator: '', + summary: '', + notes: '', + score: '', + approved: false, + evaluation_date: '', + organizations: '', + } const handleSubmit = async (data) => { await dispatch(create(data)) - await router.push('/lead_evaluations/lead_evaluations-list') + if (leadId) { + await router.push(`/leads/${leadId}`) + } else { + await router.push('/lead_evaluations/lead_evaluations-list') + } } + return ( <> - {getPageTitle('New Item')} + {getPageTitle('New Evaluation')} - + {''} handleSubmit(values)} >
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - router.push('/lead_evaluations/lead_evaluations-list')}/> + leadId ? router.push(`/leads/${leadId}`) : router.push('/lead_evaluations/lead_evaluations-list')} + />
@@ -522,14 +121,10 @@ const Lead_evaluationsNew = () => { Lead_evaluationsNew.getLayout = function getLayout(page: ReactElement) { return ( - - {page} - + + {page} + ) } -export default Lead_evaluationsNew +export default Lead_evaluationsNew \ No newline at end of file diff --git a/frontend/src/pages/leads/[leadsId].tsx b/frontend/src/pages/leads/[leadsId].tsx index 50a6e74..ba8a5d9 100644 --- a/frontend/src/pages/leads/[leadsId].tsx +++ b/frontend/src/pages/leads/[leadsId].tsx @@ -1,4 +1,4 @@ -import { mdiChartTimelineVariant, mdiUpload } from '@mdi/js' +import { mdiChartTimelineVariant, mdiFileDocument, mdiClipboardCheck, mdiFormatListChecks, mdiArrowRightBoldCircle, mdiCurrencyEur, mdiShieldCheck, mdiAccountGroup, mdiPlaylistCheck, mdiRocketLaunch, mdiPoll } from '@mdi/js' import Head from 'next/head' import React, { ReactElement, useEffect, useState } from 'react' import DatePicker from "react-datepicker"; @@ -16,961 +16,441 @@ import FormField from '../../components/FormField' import BaseDivider from '../../components/BaseDivider' import BaseButtons from '../../components/BaseButtons' import BaseButton from '../../components/BaseButton' -import FormCheckRadio from '../../components/FormCheckRadio' -import FormCheckRadioGroup from '../../components/FormCheckRadioGroup' -import FormFilePicker from '../../components/FormFilePicker' -import FormImagePicker from '../../components/FormImagePicker' -import { SelectField } from "../../components/SelectField"; -import { SelectFieldMany } from "../../components/SelectFieldMany"; +import BaseIcon from '../../components/BaseIcon' import { SwitchField } from '../../components/SwitchField' import {RichTextField} from "../../components/RichTextField"; import { update, fetch } from '../../stores/leads/leadsSlice' import { useAppDispatch, useAppSelector } from '../../stores/hooks' import { useRouter } from 'next/router' -import {saveFile} from "../../helpers/fileSaver"; -import dataFormatter from '../../helpers/dataFormatter'; -import ImageField from "../../components/ImageField"; - -import {hasPermission} from "../../helpers/userPermissions"; - +import ProgramWorkflow from '../../components/Leads/ProgramWorkflow' +import TableLead_evaluations from '../../components/Lead_evaluations/TableLead_evaluations' +import TableLead_checklists from '../../components/Lead_checklists/TableLead_checklists' +import TableTasks from '../../components/Tasks/TableTasks' +import TableApprovals from '../../components/Approvals/TableApprovals' +import TableMonitoring_reports from '../../components/Monitoring_reports/TableMonitoring_reports' const EditLeads = () => { const router = useRouter() const dispatch = useAppDispatch() + const [activeTab, setActiveTab] = useState('summary') + const initVals = { - - - 'title': '', - - - - - - - - - - - - - - - - - - - - - - - - - - - - 'program_code': '', - - - - - - - - - - - - - - - - - - - - - - - - - - - - 'customer_name': '', - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + title: '', + program_code: '', + customer_name: '', description: '', - - - - - - - - - - - - - - - - - - - - - - - - 'estimated_volume': '', - - - - - - - - - - - - - - - - - - - - - - - - - - - - 'threshold_amount': '', - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + estimated_volume: '', + threshold_amount: '', is_fast_track: false, - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - submitted_by: null, - - - - - - - - - - - - - - - - - - - - - - status: '', - - - - - - - - - - - - 'primary_contact': '', - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + status: 'Draft', + primary_contact: '', launch_date: new Date(), - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - organizations: null, - - - - - } + const [initialValues, setInitialValues] = useState(initVals) - const { leads } = useAppSelector((state) => state.leads) - - const { currentUser } = useAppSelector((state) => state.auth); - - const { leadsId } = router.query - useEffect(() => { - dispatch(fetch({ id: leadsId })) - }, [leadsId]) + // Filter items for tables + const [evalFilterItems, setEvalFilterItems] = useState([]) + const [checklistFilterItems, setChecklistFilterItems] = useState([]) + const [taskFilterItems, setTaskFilterItems] = useState([]) + const [approvalFilterItems, setApprovalFilterItems] = useState([]) + const [monitoringFilterItems, setMonitoringFilterItems] = useState([]) useEffect(() => { - if (typeof leads === 'object') { - setInitialValues(leads) - } - }, [leads]) - - useEffect(() => { - if (typeof leads === 'object') { - - const newInitialVal = {...initVals}; - - Object.keys(initVals).forEach(el => newInitialVal[el] = (leads)[el]) - - setInitialValues(newInitialVal); + if (leadsId) { + dispatch(fetch({ id: leadsId })) + + // Setup filters for tables + const leadFilter = { + id: 'lead-filter', + fields: { + selectedField: 'lead', + filterValue: leadsId, + } } + setEvalFilterItems([leadFilter]) + setChecklistFilterItems([leadFilter]) + setTaskFilterItems([leadFilter]) + setApprovalFilterItems([leadFilter]) + setMonitoringFilterItems([leadFilter]) + } + }, [leadsId, dispatch]) + + useEffect(() => { + if (leads && typeof leads === 'object' && !Array.isArray(leads)) { + const newInitialVal = { ...initVals } + Object.keys(initVals).forEach((el) => { + if (leads[el] !== undefined && leads[el] !== null) { + newInitialVal[el] = leads[el] + } + }) + setInitialValues(newInitialVal) + } }, [leads]) const handleSubmit = async (data) => { await dispatch(update({ id: leadsId, data })) - await router.push('/leads/leads-list') + dispatch(fetch({ id: leadsId })) } + const handleNextStep = async (values) => { + let nextStatus = values.status + if (values.status === 'Draft' || values.status === 'Submitted') { + nextStatus = 'PricingReview' + } else if (values.status === 'PricingReview') { + nextStatus = 'Validation' + } else if (values.status === 'Validation') { + nextStatus = 'KickOff' + } else if (values.status === 'KickOff') { + nextStatus = 'UnderwritingReview' + } else if (values.status === 'UnderwritingReview') { + nextStatus = 'FinalApproval' + } else if (values.status === 'FinalApproval') { + nextStatus = 'Launched' + } + const data = { ...values, status: nextStatus } + await dispatch(update({ id: leadsId, data })) + dispatch(fetch({ id: leadsId })) + } + + const filtersConfig = [ + {label: 'Lead', title: 'lead'} + ] + return ( <> - {getPageTitle('Edit leads')} + {getPageTitle('Program Workflow')} - - {''} - - - handleSubmit(values)} - > -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - setInitialValues({...initialValues, 'launch_date': date})} + + router.push('/leads/leads-list')} /> - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - router.push('/leads/leads-list')}/> - - -
+ + + +
+
+ setActiveTab('summary')} + className="mb-2 md:mb-0" + /> + setActiveTab('evaluations')} + className="mb-2 md:mb-0" + /> + setActiveTab('checklist')} + className="mb-2 md:mb-0" + /> + setActiveTab('pricing')} + className="mb-2 md:mb-0" + /> + setActiveTab('kickoff')} + className="mb-2 md:mb-0" + /> + setActiveTab('final')} + className="mb-2 md:mb-0" + /> + setActiveTab('monitoring')} + className="mb-2 md:mb-0" + /> +
+ + {activeTab === 'summary' && ( + + handleSubmit(values)} + > + {({ values, setFieldValue }) => ( +
+
+

Step 1: Lead Documentation

+ {values.status === 'Draft' || values.status === 'Submitted' ? ( + handleNextStep(values)} + /> + ) : ( +
+ DOCUMENTATION COMPLETE +
+ )} +
+ +
+ + + + + + + + + + + + + + + + + { + const val = e.target.value; + setFieldValue('threshold_amount', val); + setFieldValue('is_fast_track', Number(val) < 250000); + }} + /> + + + + + + setFieldValue('launch_date', date)} + className="w-full border-gray-300 rounded p-2" + /> + +
+ + + + + + + + + + + + )} +
+
+ )} + + {activeTab === 'evaluations' && ( + +
+

Lead Evaluations (Part 1, 2 & 3)

+ router.push(`/lead_evaluations/lead_evaluations-new?leadId=${leadsId}`)} + /> +
+ +
+ )} + + {activeTab === 'checklist' && ( + +
+

Lead Checklist

+ router.push(`/lead_checklists/lead_checklists-new?leadId=${leadsId}`)} + /> +
+ +
+ )} + + {activeTab === 'pricing' && ( +
+ +
+

Step 2: Pricing Review

+ {initialValues.status === 'PricingReview' && ( + handleNextStep(initialValues)} + /> + )} +
+ +
+ + +
+

Step 3: Initial Validation

+ {initialValues.status === 'Validation' && ( + handleNextStep(initialValues)} + /> + )} +
+
+ Current Path: {initialValues.is_fast_track ? 'Fast Track (CEO/CPO & Underwriter)' : 'Regular Track (MNPC Pre-validation)'} +
+ +
+
+ )} + + {activeTab === 'kickoff' && ( +
+ +
+

Step 4: Kick Off Meeting

+ {initialValues.status === 'KickOff' && ( + handleNextStep(initialValues)} + /> + )} +
+
+

Organize the Kick Off meeting and validate the project with all department stakeholders.

+
+
+ + +
+

Step 5: Department Tasks

+ {initialValues.status === 'UnderwritingReview' && ( + handleNextStep(initialValues)} + /> + )} +
+ +
+
+ )} + + {activeTab === 'final' && ( + +
+

Step 6: Final MNPC Approval

+ {initialValues.status === 'FinalApproval' && ( + handleNextStep(initialValues)} + /> + )} +
+
+ After all department tasks are validated, the MNPC provides the final authorization to launch the program. +
+ +
+ )} + + {activeTab === 'monitoring' && ( + +
+

Step 7: After-Launch Monitoring

+ {initialValues.status === 'Launched' && ( + router.push(`/monitoring_reports/monitoring_reports-new?leadId=${leadsId}`)} + /> + )} +
+
+ Track sales volumes, adherence scores, and overall program performance post-launch. +
+ +
+ )} +
) @@ -978,13 +458,9 @@ const EditLeads = () => { EditLeads.getLayout = function getLayout(page: ReactElement) { return ( - - {page} - + + {page} + ) }