Files
Web-Frontend/client/src/components/Widgets/CommCoorReport.jsx
T
vkuchenik d4fb170e14 fix:
- alert level changes now display accurate color.
- comm coor report no longer has dark loading screen in lt mode. login input text no longer white in dark mode
2026-11-03 13:27:47 -08:00

140 lines
5.0 KiB
React

import {Flex, Button, Spinner, Text} from "@chakra-ui/react";
import useBuildUrl from "../../hooks/useBuildUrl.js";
import VdapApi from '../../hooks/useVdapApi.js';
import { useRef, useEffect } from 'react';
import {useDashboardStore} from "../../store/useDashboardStore.jsx";
export default function CommCoorReport({ settings, widgetID }) {
const reportRef = useRef(null);
const updateSettings = useDashboardStore(state => state.updateWidgetSettings);
// build url, defaults to 7 days past
const url = useBuildUrl('/api/v2/comm_coor_report', settings?.startDate, settings?.endDate);
console.log(url);
// 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);
console.log(apiData);
const handleDownloadReport = () => {
if (apiData.length === 0) return;
const element = document.createElement('a');
element.style.display = 'none';
// Appends HTML right inside the element, after its last child
element.insertAdjacentHTML('afterbegin', apiData?.report_html);
// 1. Create a blob object with text content and text/plain mime type
const blob = new Blob([element.textContent || ""], { type: 'text/plain' });
// 2. Generate a temporary URL pointing to that blob
const fileUrl = URL.createObjectURL(blob);
// 3. Create a hidden anchor element
const linkElement = document.createElement('a');
linkElement.href = fileUrl;
linkElement.download = `comm_coor_report_${apiData?.start_date}_${apiData?.end_date}`; // Sets the target file name
linkElement.style.display = 'none';
// 4. Append to body, trigger click, and remove it immediately
document.body.appendChild(linkElement);
linkElement.click();
document.body.removeChild(linkElement);
document.body.removeChild(element);
// 5. Free up memory by revoking the blob URL
URL.revokeObjectURL(fileUrl);
}
const handleCopyReport = () => {
if (apiData.length === 0) return;
const element = document.createElement('a');
element.style.display = 'none';
// Appends HTML right inside the element, after its last child
element.insertAdjacentHTML('afterbegin', apiData?.report_html);
navigator.clipboard.writeText(element.textContent || "")
.then(() => {
alert('Copied to clipboard!');
})
.catch((err => {
console.error('Failed to copy: ', err);
}));
document.body.removeChild(element);
}
useEffect(() => {
if (reportRef.current) {
reportRef.current.innerHTML = apiData?.report_html;
const p = reportRef.current.querySelectorAll('p');
const b = reportRef.current.querySelectorAll('b');
p[0].remove();
b[0].remove();
}
}, [apiData]);
// copy data to clipboard in formatted way when user clicks on copy btn in widget settings
useEffect(() => {
if (settings?.copyToClipboard === true && reportRef.current) {
navigator.clipboard.writeText(reportRef.current.innerText)
.then(() => {
alert('Copied to clipboard!');
})
.catch((err => {
console.error('Failed to copy: ', err);
}));
updateSettings(widgetID, {copyToClipboard: false});
}
}, [settings, widgetID, updateSettings]);
// download report
useEffect(() => {
if (settings?.downloadReport === true && reportRef.current) {
// 1. Create a blob object with text content and text/plain mime type
const blob = new Blob([reportRef.current.innerText || ""], { type: 'text/plain' });
// 2. Generate a temporary URL pointing to that blob
const fileUrl = URL.createObjectURL(blob);
// 3. Create a hidden anchor element
const linkElement = document.createElement('a');
linkElement.href = fileUrl;
linkElement.download = `comm_coor_report_${apiData?.start_date}_${apiData?.end_date}`; // Sets the target file name
linkElement.style.display = 'none';
// 4. Append to body, trigger click, and remove it immediately
document.body.appendChild(linkElement);
linkElement.click();
document.body.removeChild(linkElement);
// 5. Free up memory by revoking the blob URL
URL.revokeObjectURL(fileUrl);
updateSettings(widgetID, {downloadReport: false});
}
}, [settings, widgetID, updateSettings, apiData]);
if (isLoading) return (
<Flex w="100%" h="100%" align="center" justify="center" borderRadius="lg" bg="transparent">
<Spinner size="xl" color="blue.400" thickness="4px"/>
</Flex>
);
if (error) return (
<Flex w="100%" h="100%" align="center" justify="center" textAlign="center" borderRadius="lg" bg="transparent">
<Text color="red.400">{error}</Text>
</Flex>
);
if (!apiData) return (
<Flex w="100%" h="100%" align="center" justify="center" borderRadius="lg" bg="transparent">
<Text textAlign="center" color="gray.400">No data</Text>
</Flex>
);
return (
<Flex direction="row" w="100%" h="100%" p={1} overflowY="auto">
<Text ref={reportRef}></Text>
</Flex>
)
}