Compare commits
No commits in common. "main" and "dundu" have entirely different histories.
14
package-lock.json
generated
14
package-lock.json
generated
@ -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"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -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[] = [
|
||||||
{
|
{
|
||||||
|
|||||||
@ -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'
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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 = () => {
|
||||||
|
|||||||
@ -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 = () => {
|
||||||
|
|||||||
@ -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();
|
||||||
|
|||||||
@ -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',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user