From 6f062bf49bb6a39bdef7eb8ebec1693e4347703e Mon Sep 17 00:00:00 2001 From: CarterPerez-dev Date: Sun, 3 May 2026 19:25:03 -0400 Subject: [PATCH] feat(monitor/frontend): earthquake + outage panels (left + right column, USGS / CF Radar) --- .../frontend/src/api/hooks/index.ts | 2 + .../src/api/hooks/useEarthquakeData.ts | 25 ++++ .../frontend/src/api/hooks/useOutageData.ts | 25 ++++ .../frontend/src/api/types/geo.types.ts | 15 ++- .../src/pages/dashboard/Dashboard.tsx | 4 + .../frontend/src/pages/dashboard/lifecycle.ts | 47 ++++++- .../pages/panels/EarthquakePanel.module.scss | 66 ++++++++++ .../src/pages/panels/EarthquakePanel.tsx | 98 +++++++++++++++ .../src/pages/panels/OutagePanel.module.scss | 69 ++++++++++ .../frontend/src/pages/panels/OutagePanel.tsx | 118 ++++++++++++++++++ .../frontend/src/stores/earthquake.ts | 23 ++++ .../frontend/src/stores/outage.ts | 23 ++++ 12 files changed, 509 insertions(+), 6 deletions(-) create mode 100644 PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/api/hooks/useEarthquakeData.ts create mode 100644 PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/api/hooks/useOutageData.ts create mode 100644 PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/pages/panels/EarthquakePanel.module.scss create mode 100644 PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/pages/panels/EarthquakePanel.tsx create mode 100644 PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/pages/panels/OutagePanel.module.scss create mode 100644 PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/pages/panels/OutagePanel.tsx create mode 100644 PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/stores/earthquake.ts create mode 100644 PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/stores/outage.ts diff --git a/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/api/hooks/index.ts b/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/api/hooks/index.ts index 7dd74f60..5993c0b4 100644 --- a/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/api/hooks/index.ts +++ b/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/api/hooks/index.ts @@ -10,7 +10,9 @@ export * from './useBgpHijackData' export * from './useCoinbasePrices' export * from './useCveData' export * from './useDShieldData' +export * from './useEarthquakeData' export * from './useIssPosition' export * from './useKevData' +export * from './useOutageData' export * from './useRansomwareData' export * from './useSpaceWeather' diff --git a/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/api/hooks/useEarthquakeData.ts b/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/api/hooks/useEarthquakeData.ts new file mode 100644 index 00000000..093c2bf7 --- /dev/null +++ b/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/api/hooks/useEarthquakeData.ts @@ -0,0 +1,25 @@ +// ©AngelaMos | 2026 +// useEarthquakeData.ts + +import { useEffect } from 'react' +import { isValidEarthquakePayload, type EarthquakePayload } from '@/api/types' +import { useSnapshot } from '@/api/snapshot' +import { useEarthquakeStore } from '@/stores/earthquake' + +interface EarthquakeData { + items: EarthquakePayload[] +} + +export function useEarthquakeData(): EarthquakeData { + const { data } = useSnapshot() + const items = useEarthquakeStore((s) => s.items) + const push = useEarthquakeStore((s) => s.push) + + const raw = data?.earthquake + const seed = isValidEarthquakePayload(raw) ? raw : undefined + useEffect(() => { + if (seed) push(seed) + }, [seed, push]) + + return { items } +} diff --git a/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/api/hooks/useOutageData.ts b/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/api/hooks/useOutageData.ts new file mode 100644 index 00000000..0717bafc --- /dev/null +++ b/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/api/hooks/useOutageData.ts @@ -0,0 +1,25 @@ +// ©AngelaMos | 2026 +// useOutageData.ts + +import { useEffect } from 'react' +import { isValidInternetOutage, type InternetOutage } from '@/api/types' +import { useSnapshot } from '@/api/snapshot' +import { useOutageStore } from '@/stores/outage' + +interface OutageData { + items: InternetOutage[] +} + +export function useOutageData(): OutageData { + const { data } = useSnapshot() + const items = useOutageStore((s) => s.items) + const push = useOutageStore((s) => s.push) + + const raw = data?.internet_outage + const seed = isValidInternetOutage(raw) ? raw : undefined + useEffect(() => { + if (seed) push(seed) + }, [seed, push]) + + return { items } +} diff --git a/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/api/types/geo.types.ts b/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/api/types/geo.types.ts index 5633a0fe..b20380e6 100644 --- a/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/api/types/geo.types.ts +++ b/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/api/types/geo.types.ts @@ -14,12 +14,25 @@ export const issPositionSchema = z.object({ export type IssPosition = z.infer +export const earthquakePropertiesSchema = z.object({ + mag: z.number().nullable().optional(), + place: z.string().nullable().optional(), + time: z.number().optional(), + updated: z.number().optional(), + alert: z.string().nullable().optional(), + tsunami: z.number().optional(), + url: z.string().optional(), + type: z.string().optional(), +}) + +export type EarthquakeProperties = z.infer + export const earthquakePayloadSchema = z.object({ id: z.string(), geometry: z .object({ coordinates: z.array(z.number()).optional() }) .optional(), - properties: z.record(z.string(), z.unknown()).optional(), + properties: earthquakePropertiesSchema.optional(), }) export type EarthquakePayload = z.infer diff --git a/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/pages/dashboard/Dashboard.tsx b/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/pages/dashboard/Dashboard.tsx index 6d77b49a..7826df46 100644 --- a/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/pages/dashboard/Dashboard.tsx +++ b/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/pages/dashboard/Dashboard.tsx @@ -6,9 +6,11 @@ import { BGPHijackPanel } from '@/pages/panels/BGPHijackPanel' import { BTCPanel } from '@/pages/panels/BTCPanel' import { CVEVelocityPanel } from '@/pages/panels/CVEVelocityPanel' import { DShieldPanel } from '@/pages/panels/DShieldPanel' +import { EarthquakePanel } from '@/pages/panels/EarthquakePanel' import { ETHPanel } from '@/pages/panels/ETHPanel' import { ISSPanel } from '@/pages/panels/ISSPanel' import { KEVPanel } from '@/pages/panels/KEVPanel' +import { OutagePanel } from '@/pages/panels/OutagePanel' import { RansomwarePanel } from '@/pages/panels/RansomwarePanel' import { SpaceWeatherPanel } from '@/pages/panels/SpaceWeatherPanel' import { useUIStore } from '@/stores/ui' @@ -39,6 +41,7 @@ export function Dashboard(): React.ReactElement { +
@@ -46,6 +49,7 @@ export function Dashboard(): React.ReactElement {