diff --git a/src/api/API.ts b/src/api/API.ts
index aae4a6f..16c21fb 100644
--- a/src/api/API.ts
+++ b/src/api/API.ts
@@ -47,6 +47,7 @@ export const API = {
updateArchitectureStatus: (applicationId: string, status: string, remarks?: string) => client.post(`/onboarding/applications/${applicationId}/architecture-status`, { status, remarks }),
generateDealerCodes: (applicationId: string) => client.post(`/onboarding/applications/${applicationId}/generate-codes`),
updateApplicationStatus: (id: string, data: any) => client.put(`/onboarding/applications/${id}/status`, data),
+ retriggerEvaluators: (id: string) => client.post(`/onboarding/applications/${id}/retrigger-evaluators`),
// Documents
uploadDocument: (id: string, data: any) => client.post(`/onboarding/applications/${id}/documents`, data, {
diff --git a/src/components/admin/QuestionnaireBuilder.tsx b/src/components/admin/QuestionnaireBuilder.tsx
index ee174cd..9fcf188 100644
--- a/src/components/admin/QuestionnaireBuilder.tsx
+++ b/src/components/admin/QuestionnaireBuilder.tsx
@@ -8,7 +8,7 @@ interface Question {
id?: string;
sectionName: string;
questionText: string;
- inputType: 'text' | 'yesno' | 'file' | 'number' | 'select';
+ inputType: 'text' | 'yesno' | 'file' | 'number' | 'select' | 'mcq' | 'radio' | 'textarea' | 'email';
options?: { text: string; score: number }[];
weight: number;
order: number;
@@ -58,7 +58,7 @@ const QuestionnaireBuilder: React.FC = () => {
if (normalizedType === 'mcq') normalizedType = 'select';
// Fallback validity check
- const validTypes = ['text', 'number', 'file', 'yesno', 'select'];
+ const validTypes = ['text', 'number', 'file', 'yesno', 'select', 'radio', 'textarea', 'email', 'mcq'];
if (!validTypes.includes(normalizedType)) normalizedType = 'text';
return {
@@ -295,10 +295,13 @@ const QuestionnaireBuilder: React.FC = () => {
className="w-full border border-slate-300 p-2.5 rounded-lg focus:ring-2 focus:ring-amber-500 outline-none bg-white"
>
+
+
-
+
+
@@ -308,8 +311,8 @@ const QuestionnaireBuilder: React.FC = () => {
updateQuestion(index, 'weight', parseFloat(e.target.value))}
+ value={isNaN(q.weight) ? 0 : q.weight}
+ onChange={(e) => updateQuestion(index, 'weight', parseFloat(e.target.value) || 0)}
className="w-full border border-slate-300 p-2.5 rounded-lg focus:ring-2 focus:ring-amber-500 outline-none pl-3 pr-8"
title="Weightage"
/>
@@ -330,7 +333,7 @@ const QuestionnaireBuilder: React.FC = () => {
{/* Options Editor for Select/YesNo */}
- {(q.inputType === 'select' || q.inputType === 'yesno') && (
+ {(q.inputType === 'select' || q.inputType === 'yesno' || q.inputType === 'radio' || q.inputType === 'mcq') && (
@@ -2778,7 +2868,7 @@ export function ApplicationDetails() {
{users.map((user) => (
- {user.fullName} ({user.role?.roleName || user.roleCode})
+ {user.fullName || user.name} ({user.role?.roleName || user.roleCode})
))}
@@ -2795,7 +2885,7 @@ export function ApplicationDetails() {
{scheduledInterviewParticipants.map((p) => (
-
{p.fullName}
+
{p.fullName || p.name || 'Unknown'}
handleRemoveInterviewer(p.id)}
className="text-muted-foreground hover:text-destructive"
@@ -2819,7 +2909,10 @@ export function ApplicationDetails() {
{
+ // Ensure we pass participants to the schedule handler
+ handleScheduleInterview();
+ }}
disabled={isScheduling}
>
{isScheduling ? 'Scheduling...' : 'Schedule'}
@@ -3008,7 +3101,7 @@ export function ApplicationDetails() {
Cancel
@@ -3031,12 +3124,22 @@ export function ApplicationDetails() {
-
+
-
+
@@ -3137,7 +3240,7 @@ export function ApplicationDetails() {
Cancel
@@ -3220,12 +3323,22 @@ export function ApplicationDetails() {
+
+
);
-}
+};
+
+export default ApplicationDetails;
diff --git a/src/components/applications/MasterPage.tsx b/src/components/applications/MasterPage.tsx
index 86dfe61..c615fc9 100644
--- a/src/components/applications/MasterPage.tsx
+++ b/src/components/applications/MasterPage.tsx
@@ -98,7 +98,7 @@ export const MasterPage: React.FC = () => {
const [zoneName, setZoneName] = useState('');
const [zoneCode, setZoneCode] = useState('');
const [zoneDescription, setZoneDescription] = useState('');
- const [zonalBusinessHeadId, setZonalBusinessHeadId] = useState('');
+ const [zonalBusinessHeadId, setZonalBusinessHeadId] = useState('none');
// Form State (Region)
const [editingRegionId, setEditingRegionId] = useState
(null);
@@ -288,7 +288,13 @@ export const MasterPage: React.FC = () => {
const handleSaveZone = async () => {
try {
- const payload = { id: editingZoneId, name: zoneName, code: zoneCode, description: zoneDescription, managerId: zonalBusinessHeadId };
+ const payload = {
+ id: editingZoneId,
+ name: zoneName,
+ code: zoneCode,
+ description: zoneDescription,
+ managerId: zonalBusinessHeadId === 'none' ? null : zonalBusinessHeadId
+ };
const res = await masterService.saveZone(payload) as any;
if (res.success) {
toast.success('Zone saved successfully');
@@ -456,8 +462,8 @@ export const MasterPage: React.FC = () => {
setSelectedZone(selectedZone === id ? 'all' : id)} />
- { setEditingZoneId(null); setZoneName(''); setZoneCode(''); setZoneDescription(''); setZonalBusinessHeadId(''); setShowZoneDialog(true); }}
- onEditZone={(z) => { setEditingZoneId(z.id); setZoneName(z.name); setZoneCode(z.code); setZoneDescription(z.description); setZonalBusinessHeadId(z.zonalBusinessHead?.id || ''); setShowZoneDialog(true); }} />
+ { setEditingZoneId(null); setZoneName(''); setZoneCode(''); setZoneDescription(''); setZonalBusinessHeadId('none'); setShowZoneDialog(true); }}
+ onEditZone={(z) => { setEditingZoneId(z.id); setZoneName(z.name); setZoneCode(z.code); setZoneDescription(z.description); setZonalBusinessHeadId(z.zonalBusinessHead?.id || 'none'); setShowZoneDialog(true); }} />
{ setEditingRegionId(null); setRegionName(''); setRegionCode(''); setSelectedRegionZone(selectedZone === 'all' ? '' : selectedZone); setRegionalManagerId(''); setSelectedRegionDistricts([]); setShowRegionDialog(true); }}
onEditRegion={(r) => {
diff --git a/src/components/applications/MasterPage/UserManagementTable.tsx b/src/components/applications/MasterPage/UserManagementTable.tsx
index a502027..3561dca 100644
--- a/src/components/applications/MasterPage/UserManagementTable.tsx
+++ b/src/components/applications/MasterPage/UserManagementTable.tsx
@@ -2,7 +2,7 @@ import React from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '../../ui/card';
import { Badge } from '../../ui/badge';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '../../ui/table';
-import { Shield, User, Mail, MapPin } from 'lucide-react';
+import { Shield, User, Mail } from 'lucide-react';
interface UserManagementTableProps {
userAssignedData: any[];
@@ -22,7 +22,6 @@ export const UserManagementTable: React.FC = ({ userAs
Role
Assigned Zone
Assigned Region
- Location Type
Status
@@ -57,12 +56,6 @@ export const UserManagementTable: React.FC = ({ userAs
{user.region}
-
-
-
- {user.locationType || 'N/A'}
-
-
{user.status}
diff --git a/src/components/applications/MasterPage/ZMManagement.tsx b/src/components/applications/MasterPage/ZMManagement.tsx
index e3d4e76..6e32db0 100644
--- a/src/components/applications/MasterPage/ZMManagement.tsx
+++ b/src/components/applications/MasterPage/ZMManagement.tsx
@@ -31,7 +31,7 @@ export const ZMManagement: React.FC = ({
Zonal Managers (ZM)
- Manage Zonal Managers and their district assignments
+ Manage Zonal Managers and their region assignments
diff --git a/src/components/applications/MasterPage/ZoneDetails.tsx b/src/components/applications/MasterPage/ZoneDetails.tsx
index c1b4bd7..d614dbe 100644
--- a/src/components/applications/MasterPage/ZoneDetails.tsx
+++ b/src/components/applications/MasterPage/ZoneDetails.tsx
@@ -5,7 +5,7 @@ import { Button } from '../../ui/button';
import { Badge } from '../../ui/badge';
import { ScrollArea } from '../../ui/scroll-area';
import { Label } from '../../ui/label';
-import { Globe, Plus, Edit2, Mail, Users, MapPin } from 'lucide-react';
+import { Globe, Plus, Edit2, Mail, Users, Shield } from 'lucide-react';
import { RootState } from '../../../store';
interface ZoneDetailsProps {
@@ -81,6 +81,26 @@ export const ZoneDetails: React.FC = ({ selectedZone, onAddZon
+ {zone.zonalBusinessHead && (
+
+
+
+
+
+ {zone.zonalBusinessHead.name}
+ ZBH
+
+
+
+
+ {zone.zonalBusinessHead.email}
+
+
+
+ )}
+
{zone.zonalManagers && zone.zonalManagers.length > 0 && (
)}
- {zm.districts && zm.districts.length > 0 && (
+ {zm.regions && zm.regions.length > 0 && (
- {zm.districts.map((district: string, dIdx: number) => (
+ {zm.regions.map((region: string, rIdx: number) => (
-
- {district}
+
+ {region}
))}
diff --git a/src/components/applications/MasterPage/ZoneDialog.tsx b/src/components/applications/MasterPage/ZoneDialog.tsx
index 22afbb1..f268ef5 100644
--- a/src/components/applications/MasterPage/ZoneDialog.tsx
+++ b/src/components/applications/MasterPage/ZoneDialog.tsx
@@ -28,11 +28,15 @@ export const ZoneDialog: React.FC
= ({
zonalBusinessHeadId, setZonalBusinessHeadId, userAssignedData, onSave
}) => {
const filteredZBHUsers = (userAssignedData || []).filter((u: any) => {
+ // Always include the currently assigned head to ensure pre-filling works
+ if (zonalBusinessHeadId !== 'none' && u.id === zonalBusinessHeadId) return true;
+
const roles = u.allRoles || [];
- return roles.some((r: string) => {
+ const topLevelRole = (u.roleCode || '').toUpperCase();
+
+ return topLevelRole === 'ZBH' || roles.some((r: string) => {
const roleStr = (r || '').toUpperCase();
- return ['ZBH', 'ZONE BUSINESS HEAD', 'ZONAL BUSINESS HEAD', 'RM', 'RBM', 'REGIONAL MANAGER', 'ASM', 'AREA SALES MANAGER'].includes(roleStr) ||
- roleStr.includes('ZONAL') || roleStr.includes('REGIONAL') || roleStr.includes('AREA SALES');
+ return roleStr === 'ZBH' || roleStr === 'ZONE BUSINESS HEAD' || roleStr === 'ZONAL BUSINESS HEAD';
});
});
diff --git a/src/hooks/useMasterData.ts b/src/hooks/useMasterData.ts
index 5a5b080..a30bba4 100644
--- a/src/hooks/useMasterData.ts
+++ b/src/hooks/useMasterData.ts
@@ -65,7 +65,7 @@ export const useMasterData = () => {
const zones = (bodyZones?.zones || bodyZones?.data || []).map((z: any) => {
const zoneName = (z.name || z.zoneName || '').toUpperCase();
- const zoneUsers = users.filter((u: any) => u.allZones?.includes(zoneName));
+ // const zoneUsers = users.filter((u: any) => u.allZones?.includes(zoneName));
return {
id: z.id, name: zoneName, description: z.description || '',
@@ -75,17 +75,17 @@ export const useMasterData = () => {
regionalOfficerCount: z.regionalOfficerCount || 0,
zmCount: z.zmCount || 0,
states: z.states || [],
- zbh: {
- name: z.zonalBusinessHead?.fullName || 'Not Assigned',
+ zonalBusinessHead: {
+ name: z.zonalBusinessHead?.name || z.zonalBusinessHead?.fullName || 'Not Assigned',
email: z.zonalBusinessHead?.email || '',
- phone: z.zonalBusinessHead?.mobileNumber || ''
+ phone: z.zonalBusinessHead?.mobileNumber || z.zonalBusinessHead?.phone || ''
},
zonalManagers: (z.zonalManagers || []).map((m: any) => ({
id: m.id,
name: m.name || m.fullName || 'Unknown',
email: m.email || '',
phone: m.phone || m.mobileNumber || '',
- districts: m.districts || []
+ regions: m.regions || []
}))
};
});
diff --git a/src/lib/mock-data.ts b/src/lib/mock-data.ts
index 3507ec6..0122d97 100644
--- a/src/lib/mock-data.ts
+++ b/src/lib/mock-data.ts
@@ -116,6 +116,7 @@ export interface Application {
zoneId?: string;
regionId?: string;
areaId?: string;
+ districtId?: string;
}
export interface Participant {
diff --git a/src/pages/public/PublicQuestionnairePage.tsx b/src/pages/public/PublicQuestionnairePage.tsx
index dfbe6bd..839daa5 100644
--- a/src/pages/public/PublicQuestionnairePage.tsx
+++ b/src/pages/public/PublicQuestionnairePage.tsx
@@ -5,9 +5,9 @@ import { toast } from 'sonner';
import { useSelector } from 'react-redux';
import { RootState } from '../../store';
import {
- User, RefreshCw, HelpCircle, Bell, ArrowLeft, Bike,
- Users, Target, FileText, Award, ChevronLeft, ChevronRight,
- CheckCircle, AlertCircle
+ User, RefreshCw, HelpCircle, ArrowLeft, Bike,
+ Users, FileText, ChevronRight,
+ CheckCircle
} from 'lucide-react';
const PublicQuestionnairePage: React.FC = () => {
@@ -231,7 +231,7 @@ const PublicQuestionnairePage: React.FC = () => {
{/* Section Tabs */}
diff --git a/src/services/onboarding.service.ts b/src/services/onboarding.service.ts
index ef8dd63..cf316ad 100644
--- a/src/services/onboarding.service.ts
+++ b/src/services/onboarding.service.ts
@@ -188,5 +188,14 @@ export const onboardingService = {
console.error('Create dealer error:', error);
throw error;
}
+ },
+ retriggerEvaluators: async (id: string) => {
+ try {
+ const response: any = await API.retriggerEvaluators(id);
+ return response.data;
+ } catch (error) {
+ console.error('Retrigger evaluators error:', error);
+ throw error;
+ }
}
};
diff --git a/src/store/slices/masterSlice.ts b/src/store/slices/masterSlice.ts
index e6ef1e2..7de053b 100644
--- a/src/store/slices/masterSlice.ts
+++ b/src/store/slices/masterSlice.ts
@@ -6,11 +6,10 @@ export interface Zone {
description?: string;
code: string;
regionCount: number;
- districtCount: number;
- states: string[];
zmCount: number;
- zonalBusinessHead: { id: string; name: string; email: string; phone: string } | null;
- zonalManagers: { id: string; name: string; email: string; phone: string; districts: string[] }[];
+ states: string[];
+ zonalBusinessHead?: { id: string; name: string; email: string; phone?: string };
+ zonalManagers: { id: string; name: string; email: string; phone: string; regions: string[] }[];
}
export interface Region {
@@ -21,6 +20,7 @@ export interface Region {
zoneName: string;
districts: { id: string; name: string, stateId?: string }[];
states: string[];
+ cities: string[];
status: string;
regionalOfficerCount: number;
asmCount: number;