Files
checkcle/application/src/components/services/ServiceDetailContainer/hooks/useServiceData.tsx
T
2025-05-09 21:28:07 +07:00

174 lines
6.0 KiB
TypeScript

import { useState, useEffect } from "react";
import { pb } from "@/lib/pocketbase";
import { Service, UptimeData } from "@/types/service.types";
import { useToast } from "@/hooks/use-toast";
import { useNavigate } from "react-router-dom";
import { uptimeService } from "@/services/uptimeService";
export const useServiceData = (serviceId: string | undefined, startDate: Date, endDate: Date) => {
const [service, setService] = useState<Service | null>(null);
const [uptimeData, setUptimeData] = useState<UptimeData[]>([]);
const [isLoading, setIsLoading] = useState(true);
const { toast } = useToast();
const navigate = useNavigate();
// Handler for service status changes
const handleStatusChange = async (newStatus: "up" | "down" | "paused" | "warning") => {
if (!service || !serviceId) return;
try {
// Optimistic UI update
setService({ ...service, status: newStatus as Service["status"] });
// Update the service status in PocketBase
await pb.collection('services').update(serviceId, {
status: newStatus
});
toast({
title: "Status updated",
description: `Service status changed to ${newStatus}`,
});
} catch (error) {
console.error("Failed to update service status:", error);
// Revert the optimistic update
setService(prevService => prevService);
toast({
variant: "destructive",
title: "Update failed",
description: "Could not update service status. Please try again.",
});
}
};
// Function to fetch uptime data with date filters
const fetchUptimeData = async (serviceId: string, start: Date, end: Date, selectedRange: string) => {
try {
console.log(`Fetching uptime data from ${start.toISOString()} to ${end.toISOString()}`);
// Set appropriate limits based on time range to ensure enough granularity
let limit = 200; // default
// Adjust limits based on selected range
if (selectedRange === '60min') {
limit = 300; // More points for shorter time ranges
} else if (selectedRange === '24h') {
limit = 200;
} else if (selectedRange === '7d') {
limit = 250;
} else if (selectedRange === '30d' || selectedRange === '1y') {
limit = 300; // More points for longer time ranges
}
console.log(`Using limit ${limit} for range ${selectedRange}`);
const history = await uptimeService.getUptimeHistory(serviceId, limit, start, end);
console.log(`Fetched ${history.length} uptime records for time range ${selectedRange}`);
if (history.length === 0) {
console.log("No data returned from API, checking if we need to fetch with a higher limit");
// If no data, try with a higher limit as fallback
if (limit < 500) {
const extendedHistory = await uptimeService.getUptimeHistory(serviceId, 500, start, end);
console.log(`Fallback: Fetched ${extendedHistory.length} uptime records with higher limit`);
if (extendedHistory.length > 0) {
setUptimeData(extendedHistory);
return extendedHistory;
}
}
}
// Sort data by timestamp (newest first)
const sortedHistory = [...history].sort((a, b) =>
new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
);
setUptimeData(sortedHistory);
return sortedHistory;
} catch (error) {
console.error("Error fetching uptime data:", error);
toast({
variant: "destructive",
title: "Error",
description: "Failed to load uptime history. Please try again.",
});
return [];
}
};
// Initial data loading
useEffect(() => {
const fetchServiceData = async () => {
try {
if (!serviceId) {
setIsLoading(false);
return;
}
setIsLoading(true);
// Add a timeout to prevent hanging
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error("Request timed out")), 10000);
});
const fetchPromise = pb.collection('services').getOne(serviceId);
const serviceData = await Promise.race([fetchPromise, timeoutPromise]) as any;
const formattedService: Service = {
id: serviceData.id,
name: serviceData.name,
url: serviceData.url || "",
type: serviceData.service_type || serviceData.type || "HTTP",
status: serviceData.status || "paused",
responseTime: serviceData.response_time || serviceData.responseTime || 0,
uptime: serviceData.uptime || 0,
lastChecked: serviceData.last_checked || serviceData.lastChecked || new Date().toLocaleString(),
interval: serviceData.heartbeat_interval || serviceData.interval || 60,
retries: serviceData.max_retries || serviceData.retries || 3,
notificationChannel: serviceData.notification_id,
alertTemplate: serviceData.template_id,
alerts: serviceData.alerts || "unmuted"
};
setService(formattedService);
// Fetch uptime history with date range
await fetchUptimeData(serviceId, startDate, endDate, '24h');
} catch (error) {
console.error("Error fetching service:", error);
toast({
variant: "destructive",
title: "Error",
description: "Failed to load service data. Please try again.",
});
navigate("/dashboard");
} finally {
setIsLoading(false);
}
};
fetchServiceData();
}, [serviceId, navigate, toast]);
// Update data when date range changes
useEffect(() => {
if (serviceId && !isLoading) {
fetchUptimeData(serviceId, startDate, endDate, '24h');
}
}, [startDate, endDate]);
return {
service,
setService,
uptimeData,
setUptimeData,
isLoading,
handleStatusChange,
fetchUptimeData
};
};