update: comm coor widget settings ui
wip: themes for checkboxes
This commit is contained in:
@@ -114,23 +114,26 @@ export default function CommCoorReport({ settings, widgetID }) {
|
|||||||
}
|
}
|
||||||
}, [settings, widgetID, updateSettings, apiData]);
|
}, [settings, widgetID, updateSettings, apiData]);
|
||||||
|
|
||||||
if (isLoading) return (
|
if (isLoading)
|
||||||
<Flex w="100%" h="100%" align="center" justify="center" borderRadius="lg" bg="transparent">
|
return (
|
||||||
<Spinner size="xl" color="blue.400" thickness="4px"/>
|
<Flex w="100%" h="100%" align="center" justify="center" borderRadius="lg" bg="transparent">
|
||||||
</Flex>
|
<Spinner size="xl" color="blue.400" thickness="4px"/>
|
||||||
);
|
</Flex>
|
||||||
|
);
|
||||||
|
|
||||||
if (error) return (
|
if (error)
|
||||||
<Flex w="100%" h="100%" align="center" justify="center" textAlign="center" borderRadius="lg" bg="transparent">
|
return (
|
||||||
<Text color="red.400">{error}</Text>
|
<Flex w="100%" h="100%" align="center" justify="center" textAlign="center" borderRadius="lg" bg="transparent">
|
||||||
</Flex>
|
<Text color="red.400">{error}</Text>
|
||||||
);
|
</Flex>
|
||||||
|
);
|
||||||
|
|
||||||
if (!apiData) return (
|
if (!apiData)
|
||||||
<Flex w="100%" h="100%" align="center" justify="center" borderRadius="lg" bg="transparent">
|
return (
|
||||||
<Text textAlign="center" color="gray.400">No data</Text>
|
<Flex w="100%" h="100%" align="center" justify="center" borderRadius="lg" bg="transparent">
|
||||||
</Flex>
|
<Text textAlign="center" color="gray.400">No data</Text>
|
||||||
);
|
</Flex>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex direction="row" w="100%" h="100%" p={1} overflowY="auto">
|
<Flex direction="row" w="100%" h="100%" p={1} overflowY="auto">
|
||||||
|
|||||||
@@ -117,16 +117,14 @@ export default function IvansAlerts({ settings, widgetID }) {
|
|||||||
</Flex>
|
</Flex>
|
||||||
{item?.files?.map((file, index) => {
|
{item?.files?.map((file, index) => {
|
||||||
return (
|
return (
|
||||||
<Box w="100%" h="100%" key={index} p={1}>
|
<Box w="100%" h="100%" key={index}>
|
||||||
<Flex direction="row" mb={2} gap={1} justify="space-between">
|
<Flex direction="row" w="100%">
|
||||||
|
<Text w="100%" p={1} fontWeight="semibold" bg="widgetBadgeBg" borderLeftRadius="lg" fontSize="sm" color="text">File: </Text>
|
||||||
<a href={`${file?.url}#view=FitV&toolbar=0`} target="_blank" rel="noopener noreferrer">
|
<a href={`${file?.url}#view=FitV&toolbar=0`} target="_blank" rel="noopener noreferrer">
|
||||||
<Text mr={1} truncate p={1} bg="widgetBadgeBg" borderRadius="lg" fontSize="sm" color="text">
|
<Text truncate w="100%" p={1} bg="widgetBadgeBg" borderRightRadius="lg" fontSize="sm" color="text">
|
||||||
File: {file?.name}
|
{file?.name}
|
||||||
</Text>
|
</Text>
|
||||||
</a>
|
</a>
|
||||||
{/*<Box borderRadius="lg" bg="widgetBadgeBg" color="text" p={1} fontSize="sm" asChild>*/}
|
|
||||||
{/* Open*/}
|
|
||||||
{/*</Box>*/}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
<object
|
<object
|
||||||
data={`${file?.url}#view=FitH&toolbar=1`}
|
data={`${file?.url}#view=FitH&toolbar=1`}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {Button, Field, Flex, Input, Switch, Text} from "@chakra-ui/react";
|
import {Button, Field, Flex, Input, Switch, Text, Fieldset, Separator, HStack} from "@chakra-ui/react";
|
||||||
import {useDashboardStore} from "@/store/useDashboardStore.jsx";
|
import {useDashboardStore} from "@/store/useDashboardStore.jsx";
|
||||||
import {useState} from "react";
|
import {useState} from "react";
|
||||||
|
|
||||||
@@ -17,67 +17,80 @@ export default function CommCoorReportSettings({ widgetId, currentSettings }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex flexDirection="column" justifyContent="space-between" gap={2} overflowY="auto">
|
<Flex flexDirection="column" justifyContent="space-between" gap={2} overflowY="auto">
|
||||||
{/* COPY TO CLIPBOARD */}
|
<Fieldset.Root>
|
||||||
<Button w="fit" size="xs" onClick={handleCopyToClipboard}>Copy Report</Button>
|
<Fieldset.Content>
|
||||||
|
<HStack>
|
||||||
|
<Text flexShrink="0" fontWeight="semibold">Date Range Selection</Text>
|
||||||
|
<Separator flex="1" size="sm"/> {/*line seperator*/}
|
||||||
|
</HStack>
|
||||||
|
{/* SELECTING DATE RANGE */}
|
||||||
|
<Flex direction="column" w="100%" h="100%" justify="center" gap="2">
|
||||||
|
<Field.Root invalid={!!startError}>
|
||||||
|
<Flex direction="row" w="100%" h="100%" align="center" justify="center">
|
||||||
|
<Text w="50%" align="center" justify="center" mt={2} color="text">
|
||||||
|
Start Date
|
||||||
|
</Text>
|
||||||
|
<Flex direction="column" w="100%">
|
||||||
|
<Input
|
||||||
|
w="100%"
|
||||||
|
type="date"
|
||||||
|
value={currentSettings?.startDate || ""}
|
||||||
|
onChange={(e) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
updateSettings(widgetId, {...currentSettings, startDate: value});
|
||||||
|
|
||||||
{/* DOWNLOAD REPORT */}
|
const dateSelected = new Date(value);
|
||||||
<Button w="fit" size="xs" onClick={handleDownloadReport}>Download Report</Button>
|
const today = new Date();
|
||||||
|
today.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
{/* SELECTING DATE RANGE */}
|
if (value && (dateSelected > today)) setStartError("Can't Choose a Future Date");
|
||||||
<Flex direction="column" w="100%" h="100%" align="center" justify="center" gap="2">
|
else setStartError("");
|
||||||
<Field.Root invalid={!!startError}>
|
}}
|
||||||
<Flex direction="row" w="100%" h="100%" align="center" justify="center">
|
/>
|
||||||
<Text w="50%" align="center" justify="center" mt={2} color="gray.700">
|
{startError && <Field.ErrorText>{startError}</Field.ErrorText>}
|
||||||
Start Date
|
</Flex>
|
||||||
</Text>
|
</Flex>
|
||||||
<Flex direction="column" w="100%">
|
</Field.Root>
|
||||||
<Input
|
<Field.Root invalid={!!endError}>
|
||||||
w="100%"
|
<Flex direction="row" w="100%" h="100%" align="center" justify="center">
|
||||||
type="date"
|
<Text w="50%" align="center" justify="center" mt={2} color="text">
|
||||||
value={currentSettings?.startDate || ""}
|
End Date
|
||||||
onChange={(e) => {
|
</Text>
|
||||||
const value = e.target.value;
|
<Flex direction="column" w="100%">
|
||||||
updateSettings(widgetId, {...currentSettings, startDate: value});
|
<Input
|
||||||
|
w="100%"
|
||||||
|
type="date"
|
||||||
|
value={currentSettings?.endDate || ""}
|
||||||
|
onChange={(e) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
updateSettings(widgetId, {...currentSettings, endDate: value});
|
||||||
|
|
||||||
const dateSelected = new Date(value);
|
const dateSelected = new Date(value);
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
today.setHours(0, 0, 0, 0);
|
today.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
if (value && (dateSelected > today)) setStartError("Can't Choose a Future Date");
|
if (value && (dateSelected > today)) setEndError("Can't Choose a Future Date");
|
||||||
else setStartError("");
|
else setEndError("");
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{startError && <Field.ErrorText>{startError}</Field.ErrorText>}
|
{endError && <Field.ErrorText>{endError}</Field.ErrorText>}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</Field.Root>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Field.Root>
|
|
||||||
<Field.Root invalid={!!endError}>
|
|
||||||
<Flex direction="row" w="100%" h="100%" align="center" justify="center">
|
|
||||||
<Text w="50%" align="center" justify="center" mt={2} color="gray.700">
|
|
||||||
End Date
|
|
||||||
</Text>
|
|
||||||
<Flex direction="column" w="100%">
|
|
||||||
<Input
|
|
||||||
w="100%"
|
|
||||||
type="date"
|
|
||||||
value={currentSettings?.endDate || ""}
|
|
||||||
onChange={(e) => {
|
|
||||||
const value = e.target.value;
|
|
||||||
updateSettings(widgetId, {...currentSettings, endDate: value});
|
|
||||||
|
|
||||||
const dateSelected = new Date(value);
|
<HStack>
|
||||||
const today = new Date();
|
<Text flexShrink="0" fontWeight="semibold">Tools</Text>
|
||||||
today.setHours(0, 0, 0, 0);
|
<Separator flex="1" size="sm"/> {/*line seperator*/}
|
||||||
|
</HStack>
|
||||||
if (value && (dateSelected > today)) setEndError("Can't Choose a Future Date");
|
<Flex direction="column" w="100%" h="100%" justify="center" gap={2}>
|
||||||
else setEndError("");
|
{/* COPY TO CLIPBOARD */}
|
||||||
}}
|
<Button w="100%" size="xs" borderRadius="lg" variant="subtle" onClick={handleCopyToClipboard}>Copy Report</Button>
|
||||||
/>
|
{/* DOWNLOAD REPORT */}
|
||||||
{endError && <Field.ErrorText>{endError}</Field.ErrorText>}
|
<Button w="100%" size="xs" borderRadius="lg" variant="subtle" onClick={handleDownloadReport}>Download Report</Button>
|
||||||
</Flex>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</Field.Root>
|
</Fieldset.Content>
|
||||||
</Flex>
|
</Fieldset.Root>
|
||||||
</Flex>
|
</Flex>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,16 @@
|
|||||||
import {Button, Field, Flex, Input, Switch, Text, Fieldset, CheckboxCard} from "@chakra-ui/react";
|
import {
|
||||||
|
Button,
|
||||||
|
Field,
|
||||||
|
Flex,
|
||||||
|
Input,
|
||||||
|
Switch,
|
||||||
|
Text,
|
||||||
|
Fieldset,
|
||||||
|
CheckboxCard,
|
||||||
|
Separator,
|
||||||
|
HStack,
|
||||||
|
useSlotRecipe
|
||||||
|
} from "@chakra-ui/react";
|
||||||
import {useDashboardStore} from "../../../store/useDashboardStore.jsx";
|
import {useDashboardStore} from "../../../store/useDashboardStore.jsx";
|
||||||
import {useState} from "react";
|
import {useState} from "react";
|
||||||
|
|
||||||
@@ -7,6 +19,10 @@ export default function IvansAlertsSettings({ widgetId, currentSettings }) {
|
|||||||
const [startError, setStartError] = useState(null);
|
const [startError, setStartError] = useState(null);
|
||||||
const [endError, setEndError] = useState(null);
|
const [endError, setEndError] = useState(null);
|
||||||
|
|
||||||
|
const popoverRecipe = useSlotRecipe({ key: "glassPopover" });
|
||||||
|
const popoverStyles = popoverRecipe();
|
||||||
|
|
||||||
|
|
||||||
const handleCopyToClipboard = () => {
|
const handleCopyToClipboard = () => {
|
||||||
updateSettings(widgetId, {copyToClipboard: true});
|
updateSettings(widgetId, {copyToClipboard: true});
|
||||||
}
|
}
|
||||||
@@ -25,12 +41,11 @@ export default function IvansAlertsSettings({ widgetId, currentSettings }) {
|
|||||||
<Fieldset.Content>
|
<Fieldset.Content>
|
||||||
{/* SELECTING DATE RANGE */}
|
{/* SELECTING DATE RANGE */}
|
||||||
<Flex direction="column" w="100%" h="100%" justify="center" gap={2}>
|
<Flex direction="column" w="100%" h="100%" justify="center" gap={2}>
|
||||||
<Flex direction="column">
|
<HStack>
|
||||||
<Text w="100%" fontWeight="bold">
|
<Separator flex="1" size="md"/> {/*line seperator*/}
|
||||||
Date Range Selection
|
<Text flexShrink="0" fontWeight="semibold">Date Range Selection</Text>
|
||||||
</Text>
|
<Separator flex="1" size="md"/> {/*line seperator*/}
|
||||||
<hr style={{borderColor: "red.700"}} /> {/*line seperator*/}
|
</HStack>
|
||||||
</Flex>
|
|
||||||
|
|
||||||
{/* start date */}
|
{/* start date */}
|
||||||
<Field.Root invalid={!!startError}>
|
<Field.Root invalid={!!startError}>
|
||||||
@@ -49,6 +64,7 @@ export default function IvansAlertsSettings({ widgetId, currentSettings }) {
|
|||||||
type="date"
|
type="date"
|
||||||
w="100%"
|
w="100%"
|
||||||
borderRadius="lg"
|
borderRadius="lg"
|
||||||
|
bg="widgetBadgeBg"
|
||||||
value={currentSettings?.startDate || ""}
|
value={currentSettings?.startDate || ""}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const value = e.target.value;
|
const value = e.target.value;
|
||||||
@@ -90,6 +106,7 @@ export default function IvansAlertsSettings({ widgetId, currentSettings }) {
|
|||||||
type="date"
|
type="date"
|
||||||
w="100%"
|
w="100%"
|
||||||
borderRadius="lg"
|
borderRadius="lg"
|
||||||
|
bg="widgetBadgeBg"
|
||||||
value={currentSettings?.endDate || ""}
|
value={currentSettings?.endDate || ""}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const value = e.target.value;
|
const value = e.target.value;
|
||||||
@@ -114,18 +131,17 @@ export default function IvansAlertsSettings({ widgetId, currentSettings }) {
|
|||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
{/* SORTS */}
|
{/* SORTS */}
|
||||||
<Flex direction="column">
|
<HStack>
|
||||||
<Text w="100%" fontWeight="bold">
|
<Separator flex="1" size="md"/> {/*line seperator*/}
|
||||||
Sorts
|
<Text flexShrink="0" fontWeight="semibold">Sorts</Text>
|
||||||
</Text>
|
<Separator flex="1" size="md"/> {/*line seperator*/}
|
||||||
<hr /> {/*line seperator*/}
|
</HStack>
|
||||||
</Flex>
|
|
||||||
|
|
||||||
{/* time sort */}
|
{/* time sort */}
|
||||||
<Switch.Root
|
<Switch.Root
|
||||||
checked={currentSettings?.activeSorts?.timeSort === "asc"}
|
checked={currentSettings?.activeSorts?.timeSort === "asc"}
|
||||||
onCheckedChange={handleTimeSort}
|
onCheckedChange={handleTimeSort}
|
||||||
colorPalette="blue"
|
colorPalette="orange"
|
||||||
>
|
>
|
||||||
<Switch.HiddenInput />
|
<Switch.HiddenInput />
|
||||||
<Switch.Control>
|
<Switch.Control>
|
||||||
@@ -138,7 +154,7 @@ export default function IvansAlertsSettings({ widgetId, currentSettings }) {
|
|||||||
<Switch.Root
|
<Switch.Root
|
||||||
checked={currentSettings?.activeSorts?.volcanoSort}
|
checked={currentSettings?.activeSorts?.volcanoSort}
|
||||||
onCheckedChange={handleVolcanoSort}
|
onCheckedChange={handleVolcanoSort}
|
||||||
colorPalette="blue"
|
colorPalette="orange"
|
||||||
>
|
>
|
||||||
<Switch.HiddenInput />
|
<Switch.HiddenInput />
|
||||||
<Switch.Control>
|
<Switch.Control>
|
||||||
@@ -147,18 +163,19 @@ export default function IvansAlertsSettings({ widgetId, currentSettings }) {
|
|||||||
<Switch.Label fontWeight={400}>Alphabetically by Volcano</Switch.Label>
|
<Switch.Label fontWeight={400}>Alphabetically by Volcano</Switch.Label>
|
||||||
</Switch.Root>
|
</Switch.Root>
|
||||||
|
|
||||||
<Flex direction="column">
|
<HStack>
|
||||||
<Text w="100%" fontWeight="bold">
|
<Separator flex="1" size="md"/> {/*line seperator*/}
|
||||||
Filters
|
<Text flexShrink="0" fontWeight="semibold">Filters</Text>
|
||||||
</Text>
|
<Separator flex="1" size="md"/> {/*line seperator*/}
|
||||||
<hr /> {/*line seperator*/}
|
</HStack>
|
||||||
</Flex>
|
|
||||||
|
|
||||||
{/* elevated levels */}
|
{/* elevated levels */}
|
||||||
<CheckboxCard.Root
|
<CheckboxCard.Root
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="surface"
|
variant="surface"
|
||||||
borderRadius="lg"
|
borderRadius="lg"
|
||||||
|
css={popoverStyles.checkboxcard}
|
||||||
|
|
||||||
defaultChecked={currentSettings?.filters?.elevatedLevels}
|
defaultChecked={currentSettings?.filters?.elevatedLevels}
|
||||||
onCheckedChange={(e) => {
|
onCheckedChange={(e) => {
|
||||||
updateSettings(widgetId, {
|
updateSettings(widgetId, {
|
||||||
@@ -177,18 +194,17 @@ export default function IvansAlertsSettings({ widgetId, currentSettings }) {
|
|||||||
Only Elevated Levels
|
Only Elevated Levels
|
||||||
</CheckboxCard.Label>
|
</CheckboxCard.Label>
|
||||||
</CheckboxCard.Content>
|
</CheckboxCard.Content>
|
||||||
<CheckboxCard.Indicator />
|
<CheckboxCard.Indicator css={popoverStyles.checkboxcard} />
|
||||||
</CheckboxCard.Control>
|
</CheckboxCard.Control>
|
||||||
</CheckboxCard.Root>
|
</CheckboxCard.Root>
|
||||||
|
|
||||||
{/* COPY TO CLIPBOARD */}
|
{/* COPY TO CLIPBOARD */}
|
||||||
<Flex direction="column">
|
<HStack>
|
||||||
<Text w="100%" fontWeight="bold">
|
<Separator flex="1" size="md"/> {/*line seperator*/}
|
||||||
Tools
|
<Text flexShrink="0" fontWeight="semibold">Tools</Text>
|
||||||
</Text>
|
<Separator flex="1" size="md"/> {/*line seperator*/}
|
||||||
<hr /> {/*line seperator*/}
|
</HStack>
|
||||||
<Button mt={2} w="100%" size="xs" borderRadius="lg" variant="subtle" onClick={handleCopyToClipboard}>Copy All IVANS</Button>
|
<Button mt={-2} colorPalette="orange" w="100%" size="xs" borderRadius="lg" variant="subtle" onClick={handleCopyToClipboard}>Copy All IVANS</Button>
|
||||||
</Flex>
|
|
||||||
</Fieldset.Content>
|
</Fieldset.Content>
|
||||||
</Fieldset.Root>
|
</Fieldset.Root>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
+28
-1
@@ -346,7 +346,7 @@ const widgetRecipe = defineSlotRecipe({
|
|||||||
|
|
||||||
// 6. TRUE POPOVER: Compact floating card for 3-dots menus
|
// 6. TRUE POPOVER: Compact floating card for 3-dots menus
|
||||||
const glassPopoverRecipe = defineSlotRecipe({
|
const glassPopoverRecipe = defineSlotRecipe({
|
||||||
slots: ["content", "arrow", "positioner"],
|
slots: ["content", "arrow", "positioner", "checkboxcard", "checkbox"],
|
||||||
base: {
|
base: {
|
||||||
content: {
|
content: {
|
||||||
...glassSurface,
|
...glassSurface,
|
||||||
@@ -357,6 +357,33 @@ const glassPopoverRecipe = defineSlotRecipe({
|
|||||||
backdropFilter: "blur(15px)",
|
backdropFilter: "blur(15px)",
|
||||||
WebkitBackdropFilter: "blur(15px)",
|
WebkitBackdropFilter: "blur(15px)",
|
||||||
},
|
},
|
||||||
|
checkboxcard: {
|
||||||
|
bg: "widgetItemBg",
|
||||||
|
_hover: {
|
||||||
|
bg: "widgetBadgeBg"
|
||||||
|
},
|
||||||
|
_checked: {
|
||||||
|
bg: "orange.700"
|
||||||
|
},
|
||||||
|
_dark: {
|
||||||
|
bg: "widgetBadgeBg",
|
||||||
|
_hover: {
|
||||||
|
bg: "widgetInnerBadgeBg"
|
||||||
|
},
|
||||||
|
_checked: {
|
||||||
|
bg: "orange.700",
|
||||||
|
_hover: {
|
||||||
|
bg: "orange.700/50"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
checkbox: {
|
||||||
|
bg: "widgetInnerBadgeBg",
|
||||||
|
_checked: {
|
||||||
|
bg: "orange"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user