made compatible t take

serve frontend build
This commit is contained in:
laxman h 2026-04-27 19:52:56 +05:30
parent 5170ab6c5a
commit 7b417be427
24 changed files with 47 additions and 83 deletions

View File

@ -6,6 +6,7 @@
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"build:deploy": "vite build",
"lint": "eslint . --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview",
"test": "jest",

View File

@ -2,6 +2,8 @@ import client from './client';
import axios from 'axios';
import type { ConstitutionalChangeAction } from '@/lib/offboarding-actions';
const PUBLIC_API_BASE_URL = (import.meta as any).env?.VITE_API_URL || '/api';
export const API = {
// Auth routes
login: (data: any) => client.post('/auth/login', data),
@ -70,8 +72,8 @@ export const API = {
deleteDocumentConfig: (id: string) => client.delete(`/onboarding/document-configs/${id}`),
// Public Questionnaire
getPublicQuestionnaire: (appId: string) => axios.get(`http://localhost:5000/api/questionnaire/public/${appId}`), // Direct axios to bypass interceptors if client has auth
submitPublicResponse: (data: any) => axios.post('http://localhost:5000/api/questionnaire/public/submit', data),
getPublicQuestionnaire: (appId: string) => axios.get(`${PUBLIC_API_BASE_URL}/questionnaire/public/${appId}`), // Direct axios to bypass interceptors if client has auth
submitPublicResponse: (data: any) => axios.post(`${PUBLIC_API_BASE_URL}/questionnaire/public/submit`, data),
// Assessment & Interviews
getAiSummary: (appId: string) => client.get(`/assessment/ai-summary/${appId}`),

View File

@ -1,6 +1,6 @@
import { create } from 'apisauce';
const API_BASE_URL = (import.meta as any).env?.VITE_API_URL || 'http://localhost:5000/api';
const API_BASE_URL = (import.meta as any).env?.VITE_API_URL || '/api';
const client = create({
baseURL: API_BASE_URL,

View File

@ -59,9 +59,9 @@ const QuestionnaireForm: React.FC<QuestionnaireFormProps> = ({
return;
}
const res = await API.getLatestQuestionnaire();
const res: any = await API.getLatestQuestionnaire();
if (res.data && res.data.data && res.data.data.questions) {
if (res?.data?.data?.questions) {
// Normalize questions
const normalized = res.data.data.questions.map((q: any) => ({
...q,

View File

@ -1,20 +1,13 @@
import React, { useState } from 'react';
import React from 'react';
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogDescription,
} from './dialog';
import { Button } from './button';
import {
Eye,
Download,
RotateCw,
RefreshCw,
Plus,
Minus,
FileText
} from 'lucide-react';
import { WIDE_DIALOG_CLASS } from '../../lib/dialogStyles';
@ -35,9 +28,6 @@ export const DocumentPreviewModal: React.FC<DocumentPreviewModalProps> = ({
onClose,
document
}) => {
const [zoomScale, setZoomScale] = useState(1);
const [rotation, setRotation] = useState(0);
const baseUrl = 'http://localhost:5000';
const fileUrl = document ? `${baseUrl}${document.filePath.startsWith('/') ? '' : '/'}${document.filePath}` : '';

View File

@ -1,20 +1,11 @@
import { useState, useEffect } from 'react';
import {
LayoutDashboard,
Calendar,
FileText,
UserMinus,
RefreshCcw,
MapPin,
LogOut,
Search,
ChevronLeft,
ChevronRight,
Bell,
User,
RefreshCw,
HelpCircle,
X
} from 'lucide-react';
import { useDispatch, useSelector } from 'react-redux';
import { useNavigate, Routes, Route, useParams } from 'react-router-dom';

View File

@ -423,12 +423,6 @@ export function FnFDetails({ fnfId, onBack, currentUser }: FnFDetailsProps) {
const fnfAge = calculateAge(fnfCase.submittedOn);
const canSendToStakeholders =
currentUser &&
["DD Lead", "DD Head", "NBH", "DD Admin", "Super Admin"].includes(
currentUser.role,
);
const canRespondToDepartment = (dept: any) => {
if (!fnfCase || !dept) return false;
const role = String(currentUser?.role || "").toLowerCase();

View File

@ -1,5 +1,5 @@
import { useState, useEffect } from 'react';
import { IndianRupee, Calendar, Eye, Send, FileCheck, Loader2 } from 'lucide-react';
import { IndianRupee, Calendar, Eye, FileCheck, Loader2 } from 'lucide-react';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
@ -42,9 +42,6 @@ export function FnFPage({ currentUser, onViewDetails }: FnFPageProps) {
const [settlements, setSettlements] = useState<any[]>([]);
const [loading, setLoading] = useState(true);
const canSendToStakeholders = currentUser &&
['DD Lead', 'DD Head', 'NBH', 'DD Admin', 'Super Admin'].includes(currentUser.role);
useEffect(() => {
fetchSettlements();
}, []);
@ -65,11 +62,6 @@ export function FnFPage({ currentUser, onViewDetails }: FnFPageProps) {
}
};
const handleSendToStakeholders = (caseId: string) => {
console.log('Sending to stakeholders for case:', caseId);
toast.success('Notifications sent to all stakeholders');
};
if (loading) {
return (
<div className="flex items-center justify-center p-12">

View File

@ -37,7 +37,7 @@ export const ASMDialog: React.FC<ASMDialogProps> = ({
asmStatus, setAsmStatus, selectedASMZone, setSelectedASMZone,
selectedASMRegion, setSelectedASMRegion, selectedASMStates, setSelectedASMStates,
selectedASMDistricts, setSelectedASMDistricts, onSave,
asmRoleCode, setAsmRoleCode,
asmRoleCode,
userAssignedData, districtsAssignedToOthers, getDistrictsForSelectedState
}) => {
const { zones, regionalOffices } = useSelector((state: RootState) => state.master);

View File

@ -1,4 +1,4 @@
import { render, screen } from "@testing-library/react"
import { screen } from "@testing-library/react"
import userEvent from "@testing-library/user-event"
import { AllApplicationsPage } from "../pages/AllApplicationsPage"
import { renderWithProviders } from "./test-utils"
@ -10,12 +10,12 @@ describe("AllApplicationsPage - Robust Admin Verification", () => {
jest.clearAllMocks()
})
const renderPage = (apps = []) => {
const renderPage = (apps: any[] = []) => {
;(mockOnboardingService.getApplications as jest.Mock).mockResolvedValue({
success: true,
data: apps
})
return renderWithProviders(<AllApplicationsPage />, {
return renderWithProviders(<AllApplicationsPage onViewDetails={jest.fn()} />, {
preloadedState: {
auth: {
user: { id: "admin-1", role: "DD Admin" } as any,

View File

@ -1,4 +1,4 @@
import { render, screen, waitFor } from "@testing-library/react"
import { screen, waitFor } from "@testing-library/react"
import userEvent from "@testing-library/user-event"
import { ApplicationDetails } from "../pages/ApplicationDetails"
import { renderWithProvidersAndRoute } from "./test-utils"

View File

@ -1,4 +1,4 @@
import { render, screen, waitFor } from "@testing-library/react"
import { screen } from "@testing-library/react"
import userEvent from "@testing-library/user-event"
import { ApplicationsPage } from "../pages/ApplicationsPage"
import { renderWithProviders } from "./test-utils"
@ -10,7 +10,7 @@ describe("ApplicationsPage - Robust Feature Verification", () => {
jest.clearAllMocks()
})
const renderPage = (apps = []) => {
const renderPage = (apps: any[] = []) => {
;(mockOnboardingService.getApplications as jest.Mock).mockResolvedValue({
success: true,
data: apps

View File

@ -1,4 +1,4 @@
import { render, screen, waitFor } from "@testing-library/react"
import { screen, waitFor } from "@testing-library/react"
import userEvent from "@testing-library/user-event"
import { ApplicationDetails } from "../pages/ApplicationDetails"
import { renderWithProvidersAndRoute } from "./test-utils"

View File

@ -1,4 +1,4 @@
import { render, screen, waitFor } from "@testing-library/react"
import { screen, waitFor } from "@testing-library/react"
import userEvent from "@testing-library/user-event"
import { FDDApplicationDetails } from "../pages/FDDApplicationDetails"
import { renderWithProvidersAndRoute } from "./test-utils"

View File

@ -1,4 +1,4 @@
import { render, screen } from "@testing-library/react"
import { screen } from "@testing-library/react"
import userEvent from "@testing-library/user-event"
import { NonOpportunitiesPage } from "../pages/NonOpportunitiesPage"
import { renderWithProviders } from "./test-utils"
@ -10,7 +10,7 @@ describe("NonOpportunitiesPage - Lead generation filtering", () => {
jest.clearAllMocks()
})
const renderPage = (apps = []) => {
const renderPage = (apps: any[] = []) => {
;(mockOnboardingService.getApplications as jest.Mock).mockResolvedValue({
success: true,
data: apps,

View File

@ -1,4 +1,4 @@
import { render, screen, waitFor } from "@testing-library/react"
import { screen, waitFor } from "@testing-library/react"
import userEvent from "@testing-library/user-event"
import { OpportunityRequestsPage } from "../pages/OpportunityRequestsPage"
import { renderWithProviders } from "./test-utils"
@ -14,12 +14,12 @@ describe("OpportunityRequestsFlow - Lead Triage Verification", () => {
jest.clearAllMocks()
})
const renderPage = (apps = []) => {
const renderPage = (apps: any[] = []) => {
;(mockOnboardingService.getApplications as jest.Mock).mockResolvedValue({
success: true,
data: apps
})
return renderWithProviders(<OpportunityRequestsPage />, {
return renderWithProviders(<OpportunityRequestsPage onViewDetails={jest.fn()} />, {
preloadedState: {
auth: {
user: { id: "admin-1", role: "DD Admin" } as any,

View File

@ -1 +1 @@
export const SHARED_APP_STATUSES = { SUBMITTED: "Submitted" };
export { TEST_STRINGS, GLOBAL_MOCK_IDS, SHARED_APP_STATUSES } from "@/testing/constants";

View File

@ -49,19 +49,18 @@ export const globalMockAdminService = {
* Helper to prepare global mocks in any test file.
*/
export const setupUnifiedMocks = () => {
jest.mock("@/services/onboarding.service", () => ({ onboardingService: globalMockOnboardingService }));
jest.mock("@/services/collaboration.service", () => ({ collaborationService: globalMockCollaborationService }));
// Mapping worknoteService to collaborationService as they share logic in this codebase
jest.mock("@/services/worknote.service", () => ({ worknoteService: globalMockCollaborationService }));
jest.mock("@/services/eor.service", () => ({ eorService: globalMockEORService }));
jest.mock("@/services/admin.service", () => ({ adminService: globalMockAdminService }));
jest.mock("@/api/API", () => ({
return {
onboardingService: globalMockOnboardingService,
collaborationService: globalMockCollaborationService,
worknoteService: globalMockCollaborationService,
eorService: globalMockEORService,
adminService: globalMockAdminService,
API: {
...globalMockOnboardingService,
getFddAssignment: jest.fn().mockResolvedValue({ success: true, data: {} }),
uploadDocument: jest.fn().mockResolvedValue({ success: true }),
submitFddReport: jest.fn().mockResolvedValue({ success: true }),
flagNonResponsive: jest.fn().mockResolvedValue({ success: true }),
}
}));
},
};
};

View File

@ -2,7 +2,6 @@ import React, { PropsWithChildren } from 'react'
import { render } from '@testing-library/react'
import type { RenderOptions } from '@testing-library/react'
import { configureStore } from '@reduxjs/toolkit'
import type { PreloadedState } from '@reduxjs/toolkit'
import { Provider } from 'react-redux'
import { MemoryRouter, Routes, Route } from 'react-router-dom'
@ -14,7 +13,7 @@ import { MEMORY_ROUTER_TEST_FUTURE } from '@/testing/reactRouterTest'
// This type interface extends the default options for render from RTL, as well
// as allows the user to specify other things such as initialState, store.
interface ExtendedRenderOptions extends Omit<RenderOptions, 'queries'> {
preloadedState?: PreloadedState<RootState>
preloadedState?: Partial<RootState>
store?: ReturnType<typeof setupStore>
}
@ -24,13 +23,13 @@ interface ProvidersAndRouteOptions extends ExtendedRenderOptions {
routePath: string
}
export function setupStore(preloadedState?: PreloadedState<RootState>) {
export function setupStore(preloadedState?: Partial<RootState>) {
return configureStore({
reducer: {
auth: authReducer,
master: masterReducer,
},
preloadedState
} as any,
preloadedState: preloadedState as any
})
}

View File

@ -30,7 +30,7 @@ const getStatusColor = (status: string) => {
const getApiErrorMessage = (error: any, fallback: string) =>
error?.response?.data?.message || error?.data?.message || error?.message || fallback;
export function DealerRelocationPage({ currentUser, onViewDetails }: DealerRelocationPageProps) {
export function DealerRelocationPage({ onViewDetails }: DealerRelocationPageProps) {
const [isDialogOpen, setIsDialogOpen] = useState(false);
const [selectedOutlet, setSelectedOutlet] = useState<any | null>(null);
const [newCity, setNewCity] = useState('');
@ -54,7 +54,6 @@ export function DealerRelocationPage({ currentUser, onViewDetails }: DealerReloc
const [requests, setRequests] = useState<any[]>([]);
const [loading, setLoading] = useState(true);
const [submitting, setSubmitting] = useState(false);
const [profile, setProfile] = useState<any>(null);
useEffect(() => {
fetchData();
@ -73,7 +72,6 @@ export function DealerRelocationPage({ currentUser, onViewDetails }: DealerReloc
const relocationRes = await dealerService.getRelocationRequests();
setOutlets(dashboard.outlets || []);
setProfile(dashboard.profile);
setRequests(relocationRes.requests || []);
} catch (error) {
console.error('Fetch relocation data error:', error);
@ -121,11 +119,6 @@ export function DealerRelocationPage({ currentUser, onViewDetails }: DealerReloc
}
};
const handleOpenRelocationDialog = (outlet: any) => {
setSelectedOutlet(outlet);
setIsDialogOpen(true);
};
const handleSubmitRequest = async (e: React.FormEvent) => {
e.preventDefault();

View File

@ -1,9 +1,9 @@
import { FileText, Plus, Eye, Calendar, User, Building2, Store, MapPin, CheckCircle, Clock, RefreshCcw, Loader2 } from 'lucide-react';
import { FileText, Eye, Calendar, Building2, Store, MapPin, CheckCircle, Clock, Loader2 } from 'lucide-react';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog';
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
@ -27,7 +27,7 @@ const getStatusColor = (status: string) => {
return 'bg-slate-100 text-slate-700 border-slate-300';
};
export function DealerResignationPage({ currentUser, onViewDetails }: DealerResignationPageProps) {
export function DealerResignationPage({ onViewDetails }: DealerResignationPageProps) {
const [isDialogOpen, setIsDialogOpen] = useState(false);
const [selectedOutlet, setSelectedOutlet] = useState<any | null>(null);
const [resignationType, setResignationType] = useState('');

View File

@ -30,7 +30,7 @@ const getStatusColor = (status: string) => {
return 'bg-blue-100 text-blue-700 border-blue-300';
};
export function ResignationPage({ currentUser, onViewDetails }: ResignationPageProps) {
export function ResignationPage({ onViewDetails }: ResignationPageProps) {
const [resignations, setResignations] = useState<any[]>([]);
const [loading, setLoading] = useState(true);
const [currentPage, setCurrentPage] = useState(1);

View File

@ -1,7 +1,6 @@
import React, { useState, useEffect } from 'react';
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';
import { Card, CardContent } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { Bell, Check, Clock, ChevronLeft, ChevronRight } from 'lucide-react';
import { notificationService, Notification } from '@/services/notification.service';
import { useNavigate } from 'react-router-dom';

View File

@ -4,6 +4,10 @@ import { defineConfig } from "vite"
export default defineConfig({
plugins: [react()],
build: {
outDir: "../backend/build",
emptyOutDir: true,
},
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),