Compare commits

..

No commits in common. "main" and "dundu" have entirely different histories.
main ... dundu

8 changed files with 136 additions and 119 deletions

14
package-lock.json generated
View File

@ -78,6 +78,7 @@
"integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.27.1", "@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.3", "@babel/generator": "^7.28.3",
@ -1483,6 +1484,7 @@
"integrity": "sha512-QoiaXANRkSXK6p0Duvt56W208du4P9Uye9hWLWgGMDTEoKPhuenzNcC4vGUmrNkiOKTlIrBoyNQYNpSwfEZXSg==", "integrity": "sha512-QoiaXANRkSXK6p0Duvt56W208du4P9Uye9hWLWgGMDTEoKPhuenzNcC4vGUmrNkiOKTlIrBoyNQYNpSwfEZXSg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"undici-types": "~7.16.0" "undici-types": "~7.16.0"
} }
@ -1492,6 +1494,7 @@
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz",
"integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"csstype": "^3.0.2" "csstype": "^3.0.2"
} }
@ -1573,6 +1576,7 @@
"integrity": "sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==", "integrity": "sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "8.46.2", "@typescript-eslint/scope-manager": "8.46.2",
"@typescript-eslint/types": "8.46.2", "@typescript-eslint/types": "8.46.2",
@ -1825,6 +1829,7 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
}, },
@ -2052,6 +2057,7 @@
} }
], ],
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"baseline-browser-mapping": "^2.8.9", "baseline-browser-mapping": "^2.8.9",
"caniuse-lite": "^1.0.30001746", "caniuse-lite": "^1.0.30001746",
@ -2473,6 +2479,7 @@
"integrity": "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==", "integrity": "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1", "@eslint-community/regexpp": "^4.12.1",
@ -3683,6 +3690,7 @@
} }
], ],
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"nanoid": "^3.3.11", "nanoid": "^3.3.11",
"picocolors": "^1.1.1", "picocolors": "^1.1.1",
@ -3878,6 +3886,7 @@
"resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz",
"integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==",
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@ -3887,6 +3896,7 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz",
"integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"scheduler": "^0.27.0" "scheduler": "^0.27.0"
}, },
@ -4428,6 +4438,7 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=12" "node": ">=12"
}, },
@ -4487,6 +4498,7 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"peer": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"
@ -4580,6 +4592,7 @@
"integrity": "sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==", "integrity": "sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"esbuild": "^0.25.0", "esbuild": "^0.25.0",
"fdir": "^6.5.0", "fdir": "^6.5.0",
@ -4673,6 +4686,7 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=12" "node": ">=12"
}, },

View File

@ -5,6 +5,12 @@ import {
LayoutDashboard, LayoutDashboard,
Package, Package,
Wrench, Wrench,
Users,
BarChart3,
Building2,
Truck,
FileText,
MapPin,
Menu, Menu,
X, X,
Moon, Moon,
@ -39,31 +45,31 @@ const Sidebar: React.FC<SidebarProps> = ({ userEmail }) => {
}; };
// Role-based visibility logic // Role-based visibility logic
// const isMaintenanceManagerKASH = userEmail === 'maintenancemanager-kash@gmail.com'; const isMaintenanceManagerKASH = userEmail === 'maintenancemanager-kash@gmail.com';
// const isMaintenanceManagerTH = userEmail === 'maintenancemanager-th@gmail.com'; const isMaintenanceManagerTH = userEmail === 'maintenancemanager-th@gmail.com';
// const isMaintenanceManagerDAJH = userEmail === 'maintenancemanager-dajh@gmail.com'; const isMaintenanceManagerDAJH = userEmail === 'maintenancemanager-dajh@gmail.com';
const isFinanceManager = userEmail === 'financemanager@gmail.com'; const isFinanceManager = userEmail === 'financemanager@gmail.com';
const isEndUser = userEmail && ( const isEndUser = userEmail && (
userEmail.startsWith('enduser1-kash') || userEmail.startsWith('enduser1-kash') ||
userEmail.startsWith('enduser1-dajh') || userEmail.startsWith('enduser1-dajh') ||
userEmail.startsWith('enduser1-th') userEmail.startsWith('enduser1-th')
); );
// const isTechnician = userEmail && ( const isTechnician = userEmail && (
// userEmail.startsWith('technician1-kash') || userEmail.startsWith('technician1-kash') ||
// userEmail.startsWith('technician1-dajh') || userEmail.startsWith('technician1-dajh') ||
// userEmail.startsWith('technician1-th') userEmail.startsWith('technician1-th')
// ); );
const showAsset = !isFinanceManager && !isEndUser; const showAsset = !isFinanceManager && !isEndUser;
// const showInventory = !isFinanceManager && !isEndUser; const showInventory = !isFinanceManager && !isEndUser;
const showPreventiveMaintenance = !isFinanceManager && !isEndUser; const showPreventiveMaintenance = !isFinanceManager && !isEndUser;
const showGeneralWO = !isFinanceManager && !isEndUser; const showGeneralWO = !isFinanceManager && !isEndUser;
// const showAMTeam = !isFinanceManager && !isEndUser; const showAMTeam = !isFinanceManager && !isEndUser;
// const showProjectDashboard = !isMaintenanceManagerKASH && !isMaintenanceManagerTH && !isMaintenanceManagerDAJH && !isFinanceManager && !isEndUser && !isTechnician; const showProjectDashboard = !isMaintenanceManagerKASH && !isMaintenanceManagerTH && !isMaintenanceManagerDAJH && !isFinanceManager && !isEndUser && !isTechnician;
// const showSiteDashboards = !isFinanceManager && !isEndUser; const showSiteDashboards = !isFinanceManager && !isEndUser;
// const showSupplierDashboard = !isFinanceManager && !isEndUser; const showSupplierDashboard = !isFinanceManager && !isEndUser;
// const showSLA = !isFinanceManager && !isEndUser && !isTechnician; const showSLA = !isFinanceManager && !isEndUser && !isTechnician;
// const showSiteInfo = !isFinanceManager && !isEndUser; const showSiteInfo = !isFinanceManager && !isEndUser;
const links: SidebarLink[] = [ const links: SidebarLink[] = [
{ {

View File

@ -965,7 +965,7 @@ const handlePPMPlan = async () => {
// Generate Status Summary HTML // Generate Status Summary HTML
const statusSummaryHTML = Object.keys(statusCounts).length > 0 const statusSummaryHTML = Object.keys(statusCounts).length > 0
? Object.entries(statusCounts).map(([status, count]) => { ? Object.entries(statusCounts).map(([status, count], index) => {
const statusClass = status === 'Completed' const statusClass = status === 'Completed'
? 'bg-green-100 text-green-800 border-green-200' ? 'bg-green-100 text-green-800 border-green-200'
: status === 'Planned' : status === 'Planned'

View File

@ -2,7 +2,7 @@ import React, { useState, useEffect, useRef } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { useAssets, useAssetMutations } from '../hooks/useAsset'; import { useAssets, useAssetMutations } from '../hooks/useAsset';
import { FaPlus, FaSearch, FaEdit, FaEye, FaTrash, FaCopy, FaEllipsisV, FaDownload, FaPrint, FaFileExport, FaTimes, FaFilter, FaChevronDown, FaChevronUp, FaSave, import { FaPlus, FaSearch, FaEdit, FaEye, FaTrash, FaCopy, FaEllipsisV, FaDownload, FaPrint, FaFileExport, FaTimes, FaFilter, FaChevronDown, FaChevronUp, FaSave,
FaStar } from 'react-icons/fa'; FaStar, FaLock } from 'react-icons/fa';
import LinkField from '../components/LinkField'; import LinkField from '../components/LinkField';
import { useUserPermissions } from '../hooks/useUserPermissions'; import { useUserPermissions } from '../hooks/useUserPermissions';
@ -18,13 +18,13 @@ const AssetList: React.FC = () => {
// ✅ NEW: Get user permissions for Asset doctype // ✅ NEW: Get user permissions for Asset doctype
const { const {
// isAdmin, isAdmin,
permissionFilters, permissionFilters,
// restrictions, restrictions,
loading: permissionsLoading, loading: permissionsLoading,
error: permissionsError, error: permissionsError,
// hasRestriction, hasRestriction,
// getAllowedValues, getAllowedValues,
hasAnyRestrictions hasAnyRestrictions
} = useUserPermissions('Asset'); } = useUserPermissions('Asset');
@ -211,11 +211,11 @@ const AssetList: React.FC = () => {
}; };
// Quick filters // Quick filters
// const applyQuickFilter = (type: 'active' | 'down' | 'recent') => { const applyQuickFilter = (type: 'active' | 'down' | 'recent') => {
// handleClearFilters(); handleClearFilters();
// if (type === 'active') setFilterDeviceStatus('Up'); if (type === 'active') setFilterDeviceStatus('Up');
// else if (type === 'down') setFilterDeviceStatus('Down'); else if (type === 'down') setFilterDeviceStatus('Down');
// }; };
// Cleanup timeouts on unmount // Cleanup timeouts on unmount
useEffect(() => { useEffect(() => {
@ -331,71 +331,71 @@ const AssetList: React.FC = () => {
filterAssetName || filterSerialNumber || searchTerm; filterAssetName || filterSerialNumber || searchTerm;
// ✅ NEW: Helper component for restricted select fields // ✅ NEW: Helper component for restricted select fields
// const RestrictedSelect: React.FC<{ const RestrictedSelect: React.FC<{
// label: string; label: string;
// permissionType: string; permissionType: string;
// value: string; value: string;
// onChange: (val: string) => void; onChange: (val: string) => void;
// doctype: string; doctype: string;
// placeholder?: string; placeholder?: string;
// filters?: Record<string, any>; filters?: Record<string, any>;
// }> = ({ label, permissionType, value, onChange, doctype, placeholder, filters: linkFilters }) => { }> = ({ label, permissionType, value, onChange, doctype, placeholder, filters: linkFilters }) => {
// const isRestricted = hasRestriction(permissionType); const isRestricted = hasRestriction(permissionType);
// const allowedValues = getAllowedValues(permissionType); const allowedValues = getAllowedValues(permissionType);
// if (isRestricted && allowedValues.length > 0) { if (isRestricted && allowedValues.length > 0) {
// return ( return (
// <div className="relative"> <div className="relative">
// <label className="block text-[10px] font-medium text-gray-700 dark:text-gray-300 mb-0.5 flex items-center gap-1"> <label className="block text-[10px] font-medium text-gray-700 dark:text-gray-300 mb-0.5 flex items-center gap-1">
// {label} {label}
// <FaLock size={8} className="text-amber-500" title={`Restricted to ${allowedValues.length} value(s)`} /> <FaLock size={8} className="text-amber-500" title={`Restricted to ${allowedValues.length} value(s)`} />
// </label> </label>
// <select <select
// value={value} value={value}
// onChange={(e) => onChange(e.target.value)} onChange={(e) => onChange(e.target.value)}
// className="w-full px-2 py-1 text-xs border border-amber-300 dark:border-amber-600 rounded focus:outline-none focus:ring-2 focus:ring-amber-500 bg-amber-50 dark:bg-amber-900/20 text-gray-900 dark:text-white" className="w-full px-2 py-1 text-xs border border-amber-300 dark:border-amber-600 rounded focus:outline-none focus:ring-2 focus:ring-amber-500 bg-amber-50 dark:bg-amber-900/20 text-gray-900 dark:text-white"
// > >
// <option value="">All Allowed ({allowedValues.length})</option> <option value="">All Allowed ({allowedValues.length})</option>
// {allowedValues.map(val => ( {allowedValues.map(val => (
// <option key={val} value={val}>{val}</option> <option key={val} value={val}>{val}</option>
// ))} ))}
// </select> </select>
// {value && ( {value && (
// <button <button
// onClick={() => onChange('')} onClick={() => onChange('')}
// className="absolute right-8 top-6 text-gray-400 hover:text-red-500 transition-colors" className="absolute right-8 top-6 text-gray-400 hover:text-red-500 transition-colors"
// > >
// <FaTimes size={10} /> <FaTimes size={10} />
// </button> </button>
// )} )}
// </div> </div>
// ); );
// } }
// // Not restricted - show normal LinkField // Not restricted - show normal LinkField
// return ( return (
// <div className="relative"> <div className="relative">
// <LinkField <LinkField
// label={label} label={label}
// doctype={doctype} doctype={doctype}
// value={value} value={value}
// onChange={onChange} onChange={onChange}
// placeholder={placeholder || `Select ${label}`} placeholder={placeholder || `Select ${label}`}
// disabled={false} disabled={false}
// compact={true} compact={true}
// filters={linkFilters} filters={linkFilters}
// /> />
// {value && ( {value && (
// <button <button
// onClick={() => onChange('')} onClick={() => onChange('')}
// className="absolute right-2 top-6 text-gray-400 hover:text-red-500 transition-colors" className="absolute right-2 top-6 text-gray-400 hover:text-red-500 transition-colors"
// > >
// <FaTimes size={10} /> <FaTimes size={10} />
// </button> </button>
// )} )}
// </div> </div>
// ); );
// }; };
// ✅ NEW: Loading state for permissions // ✅ NEW: Loading state for permissions
if (permissionsLoading) { if (permissionsLoading) {

View File

@ -39,7 +39,7 @@ const ModernDashboard: React.FC = () => {
const { data: assetWiseChart } = useDashboardChart('Maintenance - Asset wise Count'); const { data: assetWiseChart } = useDashboardChart('Maintenance - Asset wise Count');
const { data: assigneesChart } = useDashboardChart('Asset Maintenance Assignees Status Count'); const { data: assigneesChart } = useDashboardChart('Asset Maintenance Assignees Status Count');
const { data: frequencyChart } = useDashboardChart('Asset Maintenance Frequency Chart'); const { data: frequencyChart } = useDashboardChart('Asset Maintenance Frequency Chart');
// const { data: ppmStatusChart } = useDashboardChart('PPM Status'); const { data: ppmStatusChart } = useDashboardChart('PPM Status');
// Generate Up & Down Time Chart data from assets // Generate Up & Down Time Chart data from assets
useEffect(() => { useEffect(() => {
@ -765,28 +765,28 @@ const CustomerSatisfactionCard: React.FC<{ data: any; title: string; description
}; };
// Metric Card Component (Bottom Row - Smaller & Compact) // Metric Card Component (Bottom Row - Smaller & Compact)
// const MetricCard: React.FC<{ const MetricCard: React.FC<{
// icon: React.ReactNode; icon: React.ReactNode;
// label: string; label: string;
// value: string; value: string;
// iconColor?: string; iconColor?: string;
// bgColor: string; bgColor: string;
// textColor?: string; textColor?: string;
// }> = ({ icon, label, value, iconColor = "text-white", bgColor, textColor = "text-gray-900 dark:text-white" }) => ( }> = ({ icon, label, value, iconColor = "text-white", bgColor, textColor = "text-gray-900 dark:text-white" }) => (
// <div className={`${bgColor} rounded-lg shadow hover:shadow-md transition-all p-5 border border-gray-200 dark:border-gray-700`}> <div className={`${bgColor} rounded-lg shadow hover:shadow-md transition-all p-5 border border-gray-200 dark:border-gray-700`}>
// <div className="flex items-center justify-between mb-3"> <div className="flex items-center justify-between mb-3">
// <div className={`text-2xl ${iconColor}`}> <div className={`text-2xl ${iconColor}`}>
// {icon} {icon}
// </div> </div>
// </div> </div>
// <div> <div>
// <div className={`text-[10px] font-medium uppercase tracking-wide mb-1 ${textColor.includes('white') ? 'text-white/80' : 'text-gray-600 dark:text-gray-400'}`}> <div className={`text-[10px] font-medium uppercase tracking-wide mb-1 ${textColor.includes('white') ? 'text-white/80' : 'text-gray-600 dark:text-gray-400'}`}>
// {label} {label}
// </div> </div>
// <div className={`text-2xl font-semibold ${textColor}`}>{value}</div> <div className={`text-2xl font-semibold ${textColor}`}>{value}</div>
// </div> </div>
// </div> </div>
// ); );
// Mini Area Chart Component // Mini Area Chart Component
const MiniAreaChart: React.FC = () => { const MiniAreaChart: React.FC = () => {

View File

@ -1,7 +1,7 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { useParams, useNavigate, useSearchParams } from 'react-router-dom'; import { useParams, useNavigate, useSearchParams } from 'react-router-dom';
import { usePPMDetails, usePPMMutations } from '../hooks/usePPM'; import { usePPMDetails, usePPMMutations } from '../hooks/usePPM';
import { FaArrowLeft, FaSave, FaEdit, FaTools } from 'react-icons/fa'; import { FaArrowLeft, FaSave, FaEdit, FaBuilding, FaTools, FaCalendarCheck, FaDollarSign } from 'react-icons/fa';
import type { CreatePPMData } from '../services/ppmService'; import type { CreatePPMData } from '../services/ppmService';
const PPMDetail: React.FC = () => { const PPMDetail: React.FC = () => {

View File

@ -1,7 +1,7 @@
import React, { useState, useEffect, useRef } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { usePPMs, usePPMMutations } from '../hooks/usePPM'; import { usePPMs, usePPMMutations } from '../hooks/usePPM';
import { FaPlus, FaSearch, FaEdit, FaEye, FaTrash, FaCopy, FaEllipsisV, FaFileExport, FaCalendarCheck, FaBuilding } from 'react-icons/fa'; import { FaPlus, FaSearch, FaEdit, FaEye, FaTrash, FaCopy, FaEllipsisV, FaFileExport, FaCalendarCheck, FaTools, FaBuilding } from 'react-icons/fa';
const PPMList: React.FC = () => { const PPMList: React.FC = () => {
const navigate = useNavigate(); const navigate = useNavigate();

View File

@ -3,10 +3,7 @@ import react from '@vitejs/plugin-react'
// https://vite.dev/config/ // https://vite.dev/config/
export default defineConfig({ export default defineConfig({
base: '/seera-app/',
plugins: [react()], plugins: [react()],
server: { server: {
port: 3000, port: 3000,
allowedHosts: [ allowedHosts: [
@ -39,14 +36,15 @@ export default defineConfig({
}); });
}, },
}, },
// Proxy file requests to Frappe backend // Proxy file requests to Frappe backend
'/files': { '/files': {
target: process.env.VITE_FRAPPE_BASE_URL || 'https://seeraasm-med.seeraarabia.com', target: process.env.VITE_FRAPPE_BASE_URL || 'https://seeraasm-med.seeraarabia.com',
changeOrigin: true, changeOrigin: true,
secure: true, secure: true,
// Keep the /files path as-is when forwarding to the target
configure: (proxy, _options) => { configure: (proxy, _options) => {
proxy.on('proxyReq', (proxyReq, req, _res) => { proxy.on('proxyReq', (proxyReq, req, _res) => {
// Log for debugging
if (process.env.DEV) { if (process.env.DEV) {
console.log('Proxying file request:', req.url, 'to', proxyReq.path); console.log('Proxying file request:', req.url, 'to', proxyReq.path);
} }
@ -55,7 +53,6 @@ export default defineConfig({
} }
} }
}, },
build: { build: {
outDir: 'dist', outDir: 'dist',
assetsDir: 'assets', assetsDir: 'assets',