From 777366b3fa5355bb821099f3e7ba54d4be9c62fb Mon Sep 17 00:00:00 2001 From: Bennet Gallein Date: Sun, 25 May 2025 11:57:28 +0200 Subject: [PATCH] feat: add incidents history page --- pages/incidents.tsx | 130 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 pages/incidents.tsx diff --git a/pages/incidents.tsx b/pages/incidents.tsx new file mode 100644 index 0000000..977967c --- /dev/null +++ b/pages/incidents.tsx @@ -0,0 +1,130 @@ +import Head from 'next/head' + +import { Inter } from 'next/font/google' +import { MaintenanceConfig, MonitorState, MonitorTarget } from '@/types/config' +import { KVNamespace } from '@cloudflare/workers-types' +import { maintenances, pageConfig, workerConfig } from '@/uptime.config' +import OverallStatus from '@/components/OverallStatus' +import Header from '@/components/Header' +import MonitorList from '@/components/MonitorList' +import { Box, Button, Center, Container, Divider, Group, Select, Text } from '@mantine/core' +import MonitorDetail from '@/components/MonitorDetail' +import Footer from '@/components/Footer' +import { useEffect, useState } from 'react' +import MaintenanceAlert from '@/components/MaintenanceAlert' +import NoIncidentsAlert from '@/components/NoIncidents' + +export const runtime = 'experimental-edge' +const inter = Inter({ subsets: ['latin'] }) + +function getSelectedMonth() { + const hash = window.location.hash.replace('#', '') + if (!hash) { + const now = new Date() + return now.getFullYear() + '-' + String(now.getMonth() + 1).padStart(2, '0') + } + return hash +} + +function filterIncidentsByMonth( + incidents: MaintenanceConfig[], + monthStr: string +): (Omit & { monitors: MonitorTarget[] })[] { + return incidents + .filter((incident) => { + const d = new Date(incident.start) + const incidentMonth = d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') + return incidentMonth === monthStr + }) + .map((e) => ({ + ...e, + monitors: (e.monitors || []).map((e) => workerConfig.monitors.find((mon) => mon.id === e)!), + })) +} + +function getPrevNextMonth(monthStr: string) { + const [year, month] = monthStr.split('-').map(Number) + const date = new Date(year, month - 1) + const prev = new Date(date) + prev.setMonth(prev.getMonth() - 1) + const next = new Date(date) + next.setMonth(next.getMonth() + 1) + return { + prev: prev.getFullYear() + '-' + String(prev.getMonth() + 1).padStart(2, '0'), + next: next.getFullYear() + '-' + String(next.getMonth() + 1).padStart(2, '0'), + } +} + +export default function IncidentsPage() { + const [selectedMonitor, setSelectedMonitor] = useState('') + const [selectedMonth, setSelectedMonth] = useState(getSelectedMonth()) + + useEffect(() => { + const onHashChange = () => setSelectedMonth(getSelectedMonth()) + window.addEventListener('hashchange', onHashChange) + return () => window.removeEventListener('hashchange', onHashChange) + }, []) + + const filteredIncidents = filterIncidentsByMonth(maintenances, selectedMonth) + const monitorFilteredIncidents = selectedMonitor + ? filteredIncidents.filter((i) => i.monitors.find((e) => e.id === selectedMonitor)) + : filteredIncidents + + const { prev, next } = getPrevNextMonth(selectedMonth) + + const monitorOptions = [ + { value: '', label: 'All' }, + ...workerConfig.monitors.map((monitor) => ({ + value: monitor.id, + label: monitor.name, + })), + ] + + return ( + <> + + {pageConfig.title} + + + +
+
+
+ + +