From 8608b6a263fcfd35888e7ab2f2b967775780af35 Mon Sep 17 00:00:00 2001 From: Tola Leng Date: Fri, 6 Jun 2025 18:49:11 +0800 Subject: [PATCH] feat: Display 90-day uptime history --- .../public/hooks/usePublicStatusPageData.ts | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 application/src/components/public/hooks/usePublicStatusPageData.ts diff --git a/application/src/components/public/hooks/usePublicStatusPageData.ts b/application/src/components/public/hooks/usePublicStatusPageData.ts new file mode 100644 index 0000000..2a0842b --- /dev/null +++ b/application/src/components/public/hooks/usePublicStatusPageData.ts @@ -0,0 +1,86 @@ + +import { useState, useEffect } from 'react'; +import { OperationalPageRecord } from '@/types/operational.types'; +import { StatusPageComponentRecord } from '@/types/statusPageComponents.types'; +import { Service, UptimeData } from '@/types/service.types'; +import { operationalPageService } from '@/services/operationalPageService'; +import { statusPageComponentsService } from '@/services/statusPageComponentsService'; +import { serviceService } from '@/services/serviceService'; +import { uptimeService } from '@/services/uptimeService'; + +export const usePublicStatusPageData = (slug: string | undefined) => { + const [page, setPage] = useState(null); + const [components, setComponents] = useState([]); + const [services, setServices] = useState([]); + const [uptimeData, setUptimeData] = useState>({}); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + const fetchPublicPage = async () => { + if (!slug) return; + + try { + setLoading(true); + + // Fetch operational page + const pages = await operationalPageService.getOperationalPages(); + const foundPage = pages.find(p => p.slug === slug && p.is_public === 'true'); + + if (!foundPage) { + setError('Status page not found or not public'); + return; + } + + setPage(foundPage); + + // Fetch components for this page + const pageComponents = await statusPageComponentsService.getStatusPageComponentsByOperationalId(foundPage.id); + setComponents(pageComponents); + + // Fetch all services + const allServices = await serviceService.getServices(); + setServices(allServices); + + // Fetch uptime data for each component that has a service + const uptimePromises = pageComponents + .filter(component => component.service_id) + .map(async (component) => { + try { + const endDate = new Date(); + const startDate = new Date(Date.now() - 90 * 24 * 60 * 60 * 1000); // Last 90 days + const history = await uptimeService.getUptimeHistory(component.service_id, 2000, startDate, endDate); + return { serviceId: component.service_id, history }; + } catch (error) { + console.error(`Error fetching uptime for service ${component.service_id}:`, error); + return { serviceId: component.service_id, history: [] }; + } + }); + + const uptimeResults = await Promise.all(uptimePromises); + const uptimeMap: Record = {}; + uptimeResults.forEach(result => { + uptimeMap[result.serviceId] = result.history; + }); + setUptimeData(uptimeMap); + + } catch (err) { + console.error('Error fetching public page:', err); + setError('Failed to load status page'); + } finally { + setLoading(false); + } + }; + + fetchPublicPage(); + }, [slug]); + + return { + page, + components, + services, + uptimeData, + loading, + error + }; +}; \ No newline at end of file