import { useState, useEffect, useCallback, useRef } from 'react'; import ppmService from '../services/ppmService'; import type { AssetMaintenance, PPMFilters, CreatePPMData } from '../services/ppmService'; /** * Hook to fetch list of asset maintenances (PPM schedules) with filters and pagination */ export function usePPMs( filters?: PPMFilters, limit: number = 20, offset: number = 0, orderBy?: string ) { const [ppms, setPPMs] = useState([]); const [totalCount, setTotalCount] = useState(0); const [hasMore, setHasMore] = useState(false); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [refetchTrigger, setRefetchTrigger] = useState(0); const hasAttemptedRef = useRef(false); const filtersJson = JSON.stringify(filters); useEffect(() => { if (hasAttemptedRef.current && error) { return; } let isCancelled = false; hasAttemptedRef.current = true; const fetchPPMs = async () => { try { setLoading(true); const response = await ppmService.getAssetMaintenances(filters, undefined, limit, offset, orderBy); if (!isCancelled) { setPPMs(response.asset_maintenances); setTotalCount(response.total_count); setHasMore(response.has_more); setError(null); } } catch (err) { if (!isCancelled) { const errorMessage = err instanceof Error ? err.message : 'Failed to fetch PPM schedules'; if (errorMessage.includes('417') || errorMessage.includes('Expectation Failed') || errorMessage.includes('has no attribute')) { setError('API endpoint not deployed. Please deploy ppm_api.py to your Frappe server.'); } else { setError(errorMessage); } setPPMs([]); setTotalCount(0); setHasMore(false); } } finally { if (!isCancelled) { setLoading(false); } } }; fetchPPMs(); return () => { isCancelled = true; }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [filtersJson, limit, offset, orderBy, refetchTrigger]); const refetch = useCallback(() => { hasAttemptedRef.current = false; setRefetchTrigger(prev => prev + 1); }, []); return { ppms, totalCount, hasMore, loading, error, refetch }; } /** * Hook to fetch a single PPM schedule by name */ export function usePPMDetails(ppmName: string | null) { const [ppm, setPPM] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const fetchPPM = useCallback(async () => { if (!ppmName) { setPPM(null); setLoading(false); return; } try { setLoading(true); setError(null); const data = await ppmService.getAssetMaintenanceDetails(ppmName); setPPM(data); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to fetch PPM details'); } finally { setLoading(false); } }, [ppmName]); useEffect(() => { fetchPPM(); }, [fetchPPM]); const refetch = useCallback(() => { fetchPPM(); }, [fetchPPM]); return { ppm, loading, error, refetch }; } /** * Hook to manage PPM operations (create, update, delete) */ export function usePPMMutations() { const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const createPPM = useCallback(async (data: CreatePPMData) => { try { setLoading(true); setError(null); const result = await ppmService.createAssetMaintenance(data); return result; } catch (err) { const errorMessage = err instanceof Error ? err.message : 'Failed to create PPM schedule'; setError(errorMessage); throw err; } finally { setLoading(false); } }, []); const updatePPM = useCallback(async (ppmName: string, data: Partial) => { try { setLoading(true); setError(null); const result = await ppmService.updateAssetMaintenance(ppmName, data); return result; } catch (err) { const errorMessage = err instanceof Error ? err.message : 'Failed to update PPM schedule'; setError(errorMessage); throw err; } finally { setLoading(false); } }, []); const deletePPM = useCallback(async (ppmName: string) => { try { setLoading(true); setError(null); const result = await ppmService.deleteAssetMaintenance(ppmName); return result; } catch (err) { const errorMessage = err instanceof Error ? err.message : 'Failed to delete PPM schedule'; setError(errorMessage); throw err; } finally { setLoading(false); } }, []); return { createPPM, updatePPM, deletePPM, loading, error }; }