add differentiation in capability according to sizing in ivans widget

This commit is contained in:
2026-08-19 09:52:08 -07:00
parent 0381bc3ce8
commit a5f2f012dc
+45 -92
View File
@@ -1,14 +1,17 @@
import {Button, Flex, Spinner, Text, Box, Collapsible} from "@chakra-ui/react"; import {Button, Flex, Spinner, Text, Box, Collapsible} from "@chakra-ui/react";
import {useEffect, useMemo } from 'react'; import {useEffect, useMemo, useCallback } from 'react';
import {useDashboardStore} from "@/store/useDashboardStore.jsx"; import {useDashboardStore} from "@/store/useDashboardStore.jsx";
import VdapApi from '../../hooks/useVdapApi.js'; import VdapApi from '../../hooks/useVdapApi.js';
import useBuildUrl from "@/hooks/useBuildUrl.js"; import useBuildUrl from "@/hooks/useBuildUrl.js";
export default function IvansAlerts({ settings, widgetID }) { export default function IvansAlerts({ settings, widgetID }) {
console.log("IvansAlerts widget ID: ", widgetID); console.log("Ivans settings: ", settings, "Ivans widgetID: ", widgetID);
const updateSettings = useDashboardStore(state => state.updateWidgetSettings); const updateSettings = useDashboardStore(state => state.updateWidgetSettings);
const isCopy = settings?.copyToClipboard === true; // acts as a fail-safe if no default setting is set
const sorts = settings?.activeSorts; // find this specific widgets object in the state list of active/displayed widgets and extract its uuid
const thisWidget = useDashboardStore(useCallback((state) =>
state.widgets.find((widget) => widget.id === widgetID), [widgetID]
));
// build url, default is 7 days past // build url, default is 7 days past
const url = useBuildUrl('/api/v2/comm_coor_ivans', settings?.startDate, settings?.endDate); const url = useBuildUrl('/api/v2/comm_coor_ivans', settings?.startDate, settings?.endDate);
@@ -16,90 +19,21 @@ export default function IvansAlerts({ settings, widgetID }) {
// VdapApi hook only calls api if the url changes and apiData remains stable since vdapApi uses state to track the data // VdapApi hook only calls api if the url changes and apiData remains stable since vdapApi uses state to track the data
const {data: apiData, isLoading, error} = VdapApi(url); const {data: apiData, isLoading, error} = VdapApi(url);
// TEST DATA // sort the apiData
// const apiData = useMemo(() => {
// return ([
// {
// id: 277,
// volcano_number: 268010,
// report_num: "2026-01",
// report_date: "2026-05-08T22:05:44Z",
// preparer: "hwright",
// reviewer: "dramsey",
// send_time: "2026-05-08T22:05:52Z",
// volcano_name: "Dukono",
// summary: "At 07:41 local time on 8 May 2026, an explosion of persistently active Dukono volcano occurred, producing an ash plume that rose over 15 km (52,000 feet) above sea level and ejecting ballistic blocks of lava beyond the crater rim. The eruption killed three tourists who were hiking within the official exclusion zone; other hikers were rescued and returned to safety.",
// files: [
// {
// name: "277-268010-Dukono-2026-01.pdf",
// url: "https://vdap.org/ivans/sitrep/277-268010-Dukono-2026-01.pdf",
// type: "pdf"
// }
// ]
// },
// {
// id: 279,
// volcano_number: 250030,
// report_num: "2026-01",
// report_date: "2026-05-15T05:11:53Z",
// preparer: "charpel",
// reviewer: "jlwnstrn",
// send_time: "2026-05-15T05:12:01Z",
// volcano_name: "Central Bismarck Sea",
// summary: "A M5.4 earthquake occurred on 14 May 2026 at 17:13 (UTC) during the ongoing eruption of the submarine Central Bismarck Sea volcano that began 8 May 2026. The volcano's current activity does not threaten any populated areas, but today’s earthquake indicates that eruptive activity will continue or increase.",
// files: [
// {
// name: "279-250030-Central Bismarck Sea-2026-01.pdf",
// url: "https://vdap.org/ivans/sitrep/279-250030-Central Bismarck Sea-2026-01.pdf",
// type: "pdf"
// }
// ]
// },
// {
// id: 275,
// volcano_number: 273030,
// report_num: "2026-02",
// report_date: "2026-05-03T05:28:12Z",
// preparer: "dramsey",
// reviewer: "hwright",
// send_time: "2026-05-03T05:28:20Z",
// volcano_name: "Mayon",
// summary: "At around 5:30 PM local time on May 2, 2026, a pyroclastic flow (cloud of searing ash and rock particles) from erupting Mayon Volcano traveled around 4 km (~2.5 miles) down the southwestern slope of the volcano and produced an ash plume that drifted to the west-southwest. At least 52 villages in various towns in Albay province were heavily affected by thick ash fall, reducing visibility to near zero and making travel extremely difficult. There were no reports of casualties and the volcano alert level remained at Level 3 (on a 0-5 level scale).",
// files: [
// {
// name: "275-273030-Mayon-2026-02.pdf",
// url: "https://vdap.org/ivans/sitrep/275-273030-Mayon-2026-02.pdf",
// type: "pdf"
// },
// {
// name: "275-273030-Mayon-2026-02.pdf",
// url: "https://vdap.org/ivans/sitrep/275-273030-Mayon-2026-02.pdf",
// type: "pdf"
// }
// ]
// }
// ])
// }, []);
const data = useMemo(() => { const data = useMemo(() => {
if (apiData?.length === 0) return []; if (apiData?.length === 0) return [];
let sorted; const sorts = settings?.activeSorts;
if (sorts?.volcanoSort && sorts?.timeSort === "asc") { if (sorts?.volcanoSort && sorts?.timeSort === "asc") return [...apiData].sort(ascTimeVolcanoSort);
sorted = [...apiData].sort(ascTimeVolcanoSort); else if (sorts?.volcanoSort && sorts?.timeSort === "desc") return [...apiData].sort(descTimeVolcanoSort);
} else if (sorts?.volcanoSort && sorts?.timeSort === "desc") { else if (sorts?.timeSort === "asc") return [...apiData].sort(ascTimeSort);
sorted = [...apiData].sort(descTimeVolcanoSort); else return [...apiData].sort(descTimeSort);
} else if (sorts?.timeSort === "asc") {
sorted = [...apiData].sort(ascTimeSort);
} else {
sorted = [...apiData].sort(descTimeSort);
}
return sorted; }, [apiData, settings]);
}, [apiData, sorts]);
// copy data to clipboard in formatted way when user clicks on copy btn in widget settings
useEffect(() => { useEffect(() => {
if(isCopy) { if (settings?.copyToClipboard === true) {
const dataText = data.map((item) => { const dataText = data.map((item) => {
return `${item.volcano_name}\n` + return `${item.volcano_name}\n` +
`Report Number: ${item.report_num}\n` + `Report Number: ${item.report_num}\n` +
@@ -116,7 +50,7 @@ export default function IvansAlerts({ settings, widgetID }) {
})); }));
updateSettings(widgetID, {copyToClipboard: false}); updateSettings(widgetID, {copyToClipboard: false});
} }
}, [isCopy, data, widgetID, updateSettings]); }, [settings, data, widgetID, updateSettings]);
if (isLoading) return ( if (isLoading) return (
<Flex w="100%" h="100%" align="center" justify="center" borderRadius="lg" bg="gray.800"> <Flex w="100%" h="100%" align="center" justify="center" borderRadius="lg" bg="gray.800">
@@ -147,21 +81,22 @@ export default function IvansAlerts({ settings, widgetID }) {
bg="gray.800" bg="gray.800"
> >
{data.map((item, index) => { {data.map((item, index) => {
return ( if (thisWidget?.size === "large") return (
<Collapsible.Root key={index} w="100%"> <Collapsible.Root key={index} w="100%">
{/* Using context to dynamically change the border radii of the triggers */} {/* Using context to dynamically change the border radii of the triggers */}
<Collapsible.Context> <Collapsible.Context>
{(collapsible) => ( {(collapsible) => (
<> <>
<Collapsible.Trigger w="100%"> <Collapsible.Trigger w="100%">
<Flex direction="row" <Flex
w="100%" h="100%" direction="row"
justify="space-between" align="center" w="100%" h="100%"
p={1} pl={3} pr={3} justify="space-between" align="center"
gap={2} p={1} pl={3} pr={3}
borderTopRadius="lg" gap={2}
borderBottomRadius={collapsible.open ? "0" : "lg"} borderTopRadius="lg"
bg="gray.600" borderBottomRadius={collapsible.open ? "0" : "lg"}
bg="gray.600"
> >
<Flex direction="column" w="100%" minW={0} textAlign="left" color="gray.100"> <Flex direction="column" w="100%" minW={0} textAlign="left" color="gray.100">
<Text truncate>{item.volcano_name}</Text> <Text truncate>{item.volcano_name}</Text>
@@ -214,6 +149,24 @@ export default function IvansAlerts({ settings, widgetID }) {
</Collapsible.Context> </Collapsible.Context>
</Collapsible.Root> </Collapsible.Root>
) )
else if (thisWidget?.size === "small") return (
<Flex direction="row"
w="100%"
justify="space-between" align="center"
p={1} pl={3} pr={3}
gap={2}
borderRadius="lg"
bg="gray.600"
>
<Flex direction="column" w="100%" minW={0} textAlign="left" color="gray.100">
<Text truncate>{item.volcano_name}</Text>
<Text truncate fontSize="xs" color="gray.300/90">{item.send_time}</Text>
</Flex>
<Flex w="100%" minW={0} justify="right">
<Text truncate pl={2} pr={2} borderRadius="lg" bg="gray.800/50" color="gray.100" fontWeight="semibold">{item.report_num}</Text>
</Flex>
</Flex>
)
})} })}
</Flex> </Flex>
); );