2026-11-10 17:07:58 +00:00
|
|
|
import {
|
|
|
|
|
Flex,
|
|
|
|
|
Slider,
|
|
|
|
|
Switch,
|
|
|
|
|
Text,
|
|
|
|
|
Field,
|
|
|
|
|
Fieldset,
|
|
|
|
|
Input,
|
|
|
|
|
CheckboxCard,
|
|
|
|
|
CheckboxGroup,
|
|
|
|
|
Combobox,
|
|
|
|
|
Portal,
|
|
|
|
|
useFilter,
|
|
|
|
|
useListCollection,
|
|
|
|
|
Wrap,
|
|
|
|
|
Badge, Separator, HStack, useSlotRecipe
|
|
|
|
|
} from "@chakra-ui/react";
|
|
|
|
|
import { useDashboardStore } from "@/store/useDashboardStore.jsx";
|
|
|
|
|
import { useState, useMemo } from "react";
|
2026-08-18 21:20:49 +00:00
|
|
|
|
2026-11-10 17:07:58 +00:00
|
|
|
export default function AlertChangeSettings({ widgetId, currentSettings }) {
|
|
|
|
|
// STYLING
|
|
|
|
|
const popoverRecipe = useSlotRecipe({ key: "glassPopover" });
|
|
|
|
|
const popoverStyles = popoverRecipe();
|
2026-08-18 21:20:49 +00:00
|
|
|
|
2026-11-10 17:07:58 +00:00
|
|
|
// STATE MANAGEMENT
|
|
|
|
|
const updateSettings = useDashboardStore(
|
|
|
|
|
(state) => state.updateWidgetSettings,
|
|
|
|
|
);
|
|
|
|
|
const [startError, setStartError] = useState(null);
|
|
|
|
|
const [endError, setEndError] = useState(null);
|
|
|
|
|
const [selectedVolcanoes, setSelectedVolcanoes] = useState([]);
|
|
|
|
|
const { startsWith } = useFilter({ sensitivity: "base" });
|
|
|
|
|
|
|
|
|
|
const { collection, filter, reset } = useListCollection({
|
|
|
|
|
initialItems: volcanoes,
|
|
|
|
|
filter: startsWith,
|
|
|
|
|
limit: 10,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// FUNCTIONS
|
|
|
|
|
const handleValueChange = (details) => {
|
|
|
|
|
setSelectedVolcanoes(details.value)
|
|
|
|
|
}
|
2026-10-05 15:21:51 -07:00
|
|
|
|
2026-08-18 21:20:49 +00:00
|
|
|
return (
|
2026-11-10 17:07:58 +00:00
|
|
|
<Flex direction="column" pb={2} overflowY="auto">
|
|
|
|
|
<Fieldset.Root>
|
|
|
|
|
<Fieldset.Content>
|
|
|
|
|
{/* SELECTING DATE RANGE */}
|
|
|
|
|
<HStack>
|
|
|
|
|
<Text flexShrink="0" fontWeight="semibold">Date Range Selection</Text>
|
|
|
|
|
<Separator flex="1" size="sm"/> {/*line seperator*/}
|
|
|
|
|
</HStack>
|
|
|
|
|
<Flex direction="column" w="100%" h="100%" justify="center" gap={2} pr={1}>
|
|
|
|
|
{/* start date */}
|
|
|
|
|
<Field.Root invalid={!!startError}>
|
|
|
|
|
<Flex
|
|
|
|
|
direction="row"
|
|
|
|
|
w="100%"
|
|
|
|
|
h="100%"
|
|
|
|
|
align="center"
|
|
|
|
|
justify="center"
|
|
|
|
|
>
|
|
|
|
|
<Text w="50%" align="center" justify="center" color="text">
|
|
|
|
|
Start Date
|
|
|
|
|
</Text>
|
|
|
|
|
<Flex direction="column" w="100%">
|
|
|
|
|
<Input
|
|
|
|
|
type="date"
|
|
|
|
|
css={popoverStyles.date}
|
|
|
|
|
value={currentSettings?.startDate || ""}
|
|
|
|
|
onChange={(e) => {
|
|
|
|
|
const value = e.target.value;
|
|
|
|
|
updateSettings(widgetId, {
|
|
|
|
|
...currentSettings,
|
|
|
|
|
startDate: value,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const dateSelected = new Date(value);
|
|
|
|
|
const today = new Date();
|
|
|
|
|
today.setHours(0, 0, 0, 0);
|
|
|
|
|
|
|
|
|
|
if (value && dateSelected > today)
|
|
|
|
|
setStartError("Can't Choose a Future Date");
|
|
|
|
|
else setStartError("");
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
{startError && (
|
|
|
|
|
<Field.ErrorText>{startError}</Field.ErrorText>
|
|
|
|
|
)}
|
|
|
|
|
</Flex>
|
|
|
|
|
</Flex>
|
|
|
|
|
</Field.Root>
|
|
|
|
|
|
|
|
|
|
{/* end date */}
|
|
|
|
|
<Field.Root invalid={!!endError}>
|
|
|
|
|
<Flex
|
|
|
|
|
direction="row"
|
|
|
|
|
w="100%"
|
|
|
|
|
h="100%"
|
|
|
|
|
align="center"
|
|
|
|
|
justify="center"
|
|
|
|
|
>
|
|
|
|
|
<Text w="50%" align="center" justify="center" color="text">
|
|
|
|
|
End Date
|
|
|
|
|
</Text>
|
|
|
|
|
<Flex direction="column" w="100%">
|
|
|
|
|
<Input
|
|
|
|
|
type="date"
|
|
|
|
|
css={popoverStyles.date}
|
|
|
|
|
|
|
|
|
|
value={currentSettings?.endDate || ""}
|
|
|
|
|
onChange={(e) => {
|
|
|
|
|
const value = e.target.value;
|
|
|
|
|
updateSettings(widgetId, {
|
|
|
|
|
...currentSettings,
|
|
|
|
|
endDate: value,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const dateSelected = new Date(value);
|
|
|
|
|
const today = new Date();
|
|
|
|
|
today.setHours(0, 0, 0, 0);
|
|
|
|
|
|
|
|
|
|
if (value && dateSelected > today)
|
|
|
|
|
setEndError("Can't Choose a Future Date");
|
|
|
|
|
else setEndError("");
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
{endError && <Field.ErrorText>{endError}</Field.ErrorText>}
|
|
|
|
|
</Flex>
|
|
|
|
|
</Flex>
|
|
|
|
|
</Field.Root>
|
|
|
|
|
</Flex>
|
|
|
|
|
|
|
|
|
|
{/* FILTERS */}
|
|
|
|
|
<CheckboxGroup w="100%">
|
|
|
|
|
<Flex direction="column" w="100%" gap={2}>
|
|
|
|
|
<HStack>
|
|
|
|
|
<Text flexShrink="0" fontWeight="semibold">Filters</Text>
|
|
|
|
|
<Separator flex="1" size="sm"/> {/*line seperator*/}
|
|
|
|
|
</HStack>
|
|
|
|
|
|
|
|
|
|
{/* level increases */}
|
|
|
|
|
<CheckboxCard.Root
|
|
|
|
|
css={popoverStyles.checkboxcard}
|
|
|
|
|
|
|
|
|
|
defaultChecked={currentSettings?.filters?.levelIncreases}
|
|
|
|
|
onCheckedChange={(e) => {
|
|
|
|
|
updateSettings(widgetId, {
|
|
|
|
|
...currentSettings,
|
|
|
|
|
filters: {
|
|
|
|
|
...currentSettings.filters,
|
|
|
|
|
levelIncreases: e.checked,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<CheckboxCard.HiddenInput /> {/* when removed can't check/uncheck box */}
|
|
|
|
|
<CheckboxCard.Control>
|
|
|
|
|
<CheckboxCard.Content>
|
|
|
|
|
<CheckboxCard.Label fontWeight={400}>
|
|
|
|
|
Level Increases
|
|
|
|
|
</CheckboxCard.Label>
|
|
|
|
|
</CheckboxCard.Content>
|
|
|
|
|
<CheckboxCard.Indicator css={popoverStyles.checkbox} />
|
|
|
|
|
</CheckboxCard.Control>
|
|
|
|
|
</CheckboxCard.Root>
|
|
|
|
|
|
|
|
|
|
{/* level decreases */}
|
|
|
|
|
<CheckboxCard.Root
|
|
|
|
|
css={popoverStyles.checkboxcard}
|
|
|
|
|
|
|
|
|
|
defaultChecked={currentSettings?.filters?.levelDecreases}
|
|
|
|
|
onCheckedChange={(e) => {
|
|
|
|
|
updateSettings(widgetId, {
|
|
|
|
|
...currentSettings,
|
|
|
|
|
filters: {
|
|
|
|
|
...currentSettings.filters,
|
|
|
|
|
levelDecreases: e.checked,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<CheckboxCard.HiddenInput />
|
|
|
|
|
<CheckboxCard.Control>
|
|
|
|
|
<CheckboxCard.Content>
|
|
|
|
|
<CheckboxCard.Label fontWeight={400}>
|
|
|
|
|
Level Decreases
|
|
|
|
|
</CheckboxCard.Label>
|
|
|
|
|
</CheckboxCard.Content>
|
|
|
|
|
<CheckboxCard.Indicator css={popoverStyles.checkbox} />
|
|
|
|
|
</CheckboxCard.Control>
|
|
|
|
|
</CheckboxCard.Root>
|
|
|
|
|
|
|
|
|
|
{/* elevated levels */}
|
|
|
|
|
<CheckboxCard.Root
|
|
|
|
|
css={popoverStyles.checkboxcard}
|
|
|
|
|
|
|
|
|
|
defaultChecked={currentSettings?.filters?.elevatedLevels}
|
|
|
|
|
onCheckedChange={(e) => {
|
|
|
|
|
updateSettings(widgetId, {
|
|
|
|
|
...currentSettings,
|
|
|
|
|
filters: {
|
|
|
|
|
...currentSettings.filters,
|
|
|
|
|
elevatedLevels: e.checked,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<CheckboxCard.HiddenInput />
|
|
|
|
|
<CheckboxCard.Control>
|
|
|
|
|
<CheckboxCard.Content>
|
|
|
|
|
<CheckboxCard.Label fontWeight={400}>
|
|
|
|
|
Only Elevated Levels
|
|
|
|
|
</CheckboxCard.Label>
|
|
|
|
|
</CheckboxCard.Content>
|
|
|
|
|
<CheckboxCard.Indicator css={popoverStyles.checkbox}/>
|
|
|
|
|
</CheckboxCard.Control>
|
|
|
|
|
</CheckboxCard.Root>
|
|
|
|
|
</Flex>
|
|
|
|
|
</CheckboxGroup>
|
|
|
|
|
|
|
|
|
|
{/* select volcano to filter on */}
|
|
|
|
|
<Combobox.Root
|
|
|
|
|
mt={1}
|
|
|
|
|
variant="subtle"
|
|
|
|
|
multiple
|
|
|
|
|
openOnClick
|
|
|
|
|
collection={collection}
|
|
|
|
|
onValueChange={handleValueChange}
|
|
|
|
|
onInputValueChange={(e) => filter(e.inputValue)}
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
<Wrap gap="2">
|
|
|
|
|
{selectedVolcanoes.map((volcano) => (
|
|
|
|
|
<Badge key={volcano}>{volcano}</Badge>
|
|
|
|
|
))}
|
|
|
|
|
</Wrap>
|
|
|
|
|
|
|
|
|
|
<Combobox.Label fontSize="xs" >Select Volcano (s)</Combobox.Label>
|
|
|
|
|
|
|
|
|
|
<Combobox.Control>
|
|
|
|
|
<Combobox.Input placeholder="Type to search" borderRadius="lg"/>
|
|
|
|
|
<Combobox.IndicatorGroup>
|
|
|
|
|
<Combobox.ClearTrigger />
|
|
|
|
|
<Combobox.Trigger onClick={reset} />
|
|
|
|
|
</Combobox.IndicatorGroup>
|
|
|
|
|
</Combobox.Control>
|
|
|
|
|
<Portal>
|
|
|
|
|
<Combobox.Positioner>
|
|
|
|
|
<Combobox.Content>
|
|
|
|
|
{volcanoes.map((item) => (
|
|
|
|
|
<Combobox.Item item={item} key={item.value}>
|
|
|
|
|
{item.label}
|
|
|
|
|
<Combobox.ItemIndicator />
|
|
|
|
|
</Combobox.Item>
|
|
|
|
|
))}
|
|
|
|
|
<Combobox.Empty>No items found</Combobox.Empty>
|
|
|
|
|
</Combobox.Content>
|
|
|
|
|
</Combobox.Positioner>
|
|
|
|
|
</Portal>
|
|
|
|
|
</Combobox.Root>
|
|
|
|
|
</Fieldset.Content>
|
|
|
|
|
</Fieldset.Root>
|
2026-08-18 21:20:49 +00:00
|
|
|
</Flex>
|
2026-11-10 17:07:58 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const volcanoes = [
|
|
|
|
|
{ label: "Mt. St. Helens", value: "helens" },
|
|
|
|
|
{ label: "Mt. Adams", value: "adams" },
|
|
|
|
|
{ label: "Rainier", value: "rainier" },
|
|
|
|
|
{ label: "The Three Sisters", value: "three sisters" },
|
|
|
|
|
{ label: "Fuego", value: "fuego" },
|
|
|
|
|
{ label: "Laki Laki", value: "lakilaki" },
|
|
|
|
|
{ label: "Lewotobi", value: "lewotobi" },
|
|
|
|
|
{ label: "Karangatang", value: "karangatang" },
|
|
|
|
|
{ label: "Cotopaxi", value: "cotopaxi" },
|
|
|
|
|
{ label: "Merapi", value: "merapi" },
|
|
|
|
|
{ label: "Marapi", value: "marapi" },
|
|
|
|
|
{ label: "Kick 'Em Jenny", value: "kick em jenny"}
|
|
|
|
|
]
|