diff --git a/src/ReportSnapshots.tsx b/src/ReportSnapshots.tsx deleted file mode 100644 index 3bfac2d..0000000 --- a/src/ReportSnapshots.tsx +++ /dev/null @@ -1,303 +0,0 @@ -import * as React from "react"; -import { - Box, - Container, - Paper, - Typography, - Button, - IconButton, - CircularProgress, - Alert, - Snackbar, - Dialog, - DialogTitle, - DialogContent, - DialogContentText, - DialogActions, - Chip, - TextField, -} from "@mui/material"; -import DeleteIcon from "@mui/icons-material/Delete"; -import AddCircleIcon from "@mui/icons-material/AddCircle"; -import RefreshIcon from "@mui/icons-material/Refresh"; -import ContentCopyIcon from "@mui/icons-material/ContentCopy"; -import { useResource } from "../react-openapi"; -import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; - -interface ReportSnapshotQuery { - accounts?: string[]; - ignore_self?: boolean; - start_date?: string; - end_date?: string; -} - -interface ReportSnapshot { - id: string; - snapshot_id: string; - created_at: string; - query?: ReportSnapshotQuery; -} - -function formatDate(iso: string) { - const d = new Date(iso); - return d.toLocaleString(); -} - -export default function ReportSnapshots() { - const [ignoreSelf, setIgnoreSelf] = React.useState(true); - const [startDate, setStartDate] = React.useState(""); - const [endDate, setEndDate] = React.useState(""); - const [minAmount, setMinAmount] = React.useState(""); - const [maxAmount, setMaxAmount] = React.useState(""); - const [snackbar, setSnackbar] = React.useState<{ message: string; severity: "success" | "error" } | null>(null); - const [deleteTarget, setDeleteTarget] = React.useState(null); - const [createdSnapshotId, setCreatedSnapshotId] = React.useState(null); - - const { list, create, remove } = useResource("reports"); - - const { data: listData, isLoading, isFetching, refetch } = useQuery({ - queryKey: ["reports", "list"], - queryFn: () => list(), - }); - const createMutation = useMutation({ - mutationFn: (data: any) => create(data), - }); - const queryClient = useQueryClient(); - const deleteMutation = useMutation({ - mutationFn: (id: string) => remove(id), - onSuccess: () => { - queryClient.invalidateQueries({ queryKey: ["reports", "list"] }); - }, - }); - - const snapshots: ReportSnapshot[] = listData?.items ?? []; - - const handleCreate = async () => { - try { - const payload: Record = {}; - if (ignoreSelf) payload.ignore_self = true; - if (startDate) payload.start_date = new Date(startDate).toISOString(); - if (endDate) payload.end_date = new Date(endDate).toISOString(); - if (minAmount) payload.min_amount = parseFloat(minAmount); - if (maxAmount) payload.max_amount = parseFloat(maxAmount); - - const result = await createMutation.mutateAsync(payload); - const snapshotId = (result as any)?.snapshot_id; - if (snapshotId) { - setCreatedSnapshotId(snapshotId); - setSnackbar({ message: `Snapshot created: ${snapshotId}`, severity: "success" }); - } else { - setSnackbar({ message: "Snapshot created", severity: "success" }); - } - resetForm(); - } catch (err: any) { - setSnackbar({ message: err?.response?.data?.detail || "Failed to create snapshot", severity: "error" }); - } - }; - - const resetForm = () => { - setIgnoreSelf(true); - setStartDate(""); - setEndDate(""); - setMinAmount(""); - setMaxAmount(""); - }; - - const handleDelete = async () => { - if (!deleteTarget) return; - try { - await deleteMutation.mutateAsync(deleteTarget.snapshot_id); - setSnackbar({ message: "Snapshot deleted", severity: "success" }); - } catch { - setSnackbar({ message: "Failed to delete snapshot", severity: "error" }); - } - setDeleteTarget(null); - }; - - return ( - - - Report Snapshots - - - - - Generate New Snapshot - - - - - - ) => setStartDate(e.target.value)} - size="small" - InputLabelProps={{ shrink: true }} - inputProps={{ max: new Date().toISOString().split("T")[0] }} - /> - - - ) => setEndDate(e.target.value)} - size="small" - InputLabelProps={{ shrink: true }} - inputProps={{ max: new Date().toISOString().split("T")[0] }} - /> - - - - - - ) => setMinAmount(e.target.value)} - size="small" - /> - - - ) => setMaxAmount(e.target.value)} - size="small" - /> - - - - - - {createdSnapshotId && ( - setCreatedSnapshotId(null)}> - Snapshot created: {createdSnapshotId}. Use it in the Dashboard snapshot selector. - - )} - - - - - - - Existing Snapshots - - refetch()} disabled={isFetching}> - - - - - {isLoading ? ( - - - - ) : snapshots.length === 0 ? ( - - No snapshots yet - - ) : ( - - - - - {["Snapshot ID", "Created", "Query", "Actions"].map((h) => ( - - {h} - - ))} - - - - {snapshots.map((snap: ReportSnapshot) => ( - - - - {snap.snapshot_id} - { - navigator.clipboard.writeText(snap.snapshot_id); - setSnackbar({ message: "Copied!", severity: "success" }); - }} - sx={{ opacity: 0.5, '&:hover': { opacity: 1 } }} - > - - - - - - {formatDate(snap.created_at)} - - - {snap.query ? ( - - {snap.query.accounts && } - {snap.query.ignore_self && } - {snap.query.start_date && } - {snap.query.end_date && } - - ) : ( - \u2014 - )} - - - - setDeleteTarget(snap)}> - - - - - - ))} - - - - )} - - - setSnackbar(null)} - anchorOrigin={{ vertical: "bottom", horizontal: "center" }} - > - {snackbar ? setSnackbar(null)}>{snackbar.message} : undefined} - - - setDeleteTarget(null)}> - Delete Snapshot? - - - This will permanently delete the report snapshot. - - - - - - - - - ); -}