diff --git a/apps/insights/package.json b/apps/insights/package.json index 5cdaa97702..105b397948 100644 --- a/apps/insights/package.json +++ b/apps/insights/package.json @@ -32,6 +32,8 @@ "bs58": "catalog:", "clsx": "catalog:", "cryptocurrency-icons": "catalog:", + "date-fns": "catalog:", + "csv-stringify": "catalog:", "dnum": "catalog:", "ioredis": "^5.7.0", "lightweight-charts": "catalog:", @@ -46,8 +48,8 @@ "superjson": "catalog:", "swr": "catalog:", "zod": "catalog:", - "zod-validation-error": "catalog:", - "zod-search-params": "catalog:" + "zod-search-params": "catalog:", + "zod-validation-error": "catalog:" }, "devDependencies": { "@cprussin/eslint-config": "catalog:", diff --git a/apps/insights/src/app/api/pyth/get-feeds/route.ts b/apps/insights/src/app/api/pyth/get-feeds/route.ts index 426c587807..9b9d02b3ff 100644 --- a/apps/insights/src/app/api/pyth/get-feeds/route.ts +++ b/apps/insights/src/app/api/pyth/get-feeds/route.ts @@ -37,5 +37,5 @@ export const GET = async (request: NextRequest) => { const queryParamsSchema = z.object({ cluster: z.enum(CLUSTER_NAMES).transform((value) => toCluster(value)), - excludePriceComponents: z.boolean(), + excludePriceComponents: z.boolean().optional().default(false), }); diff --git a/apps/insights/src/components/ConformanceReport/conformance-report.module.scss b/apps/insights/src/components/ConformanceReport/conformance-report.module.scss new file mode 100644 index 0000000000..b6f8793efc --- /dev/null +++ b/apps/insights/src/components/ConformanceReport/conformance-report.module.scss @@ -0,0 +1,6 @@ +@use "@pythnetwork/component-library/theme"; + +.conformanceReport { + display: flex; + gap: theme.spacing(2); +} diff --git a/apps/insights/src/components/ConformanceReport/conformance-report.tsx b/apps/insights/src/components/ConformanceReport/conformance-report.tsx new file mode 100644 index 0000000000..eec9df5f06 --- /dev/null +++ b/apps/insights/src/components/ConformanceReport/conformance-report.tsx @@ -0,0 +1,71 @@ +"use client"; + +import { Download } from "@phosphor-icons/react/dist/ssr/Download"; +import { Button } from "@pythnetwork/component-library/Button"; +import { Select } from "@pythnetwork/component-library/Select"; +import { useAlert } from "@pythnetwork/component-library/useAlert"; +import { useLogger } from "@pythnetwork/component-library/useLogger"; +import { useCallback, useState } from "react"; + +import styles from "./conformance-report.module.scss"; +import type { Interval } from "./types"; +import { INTERVALS } from "./types"; + +type ConformanceReportProps = { + onClick: (timeframe: Interval) => Promise; +}; + +const ConformanceReport = (props: ConformanceReportProps) => { + const [timeframe, setTimeframe] = useState(INTERVALS[0]); + const [isGeneratingReport, setIsGeneratingReport] = useState(false); + const { open } = useAlert(); + const logger = useLogger(); + + /** + * Download the conformance report for the given symbol or publisher + */ + const downloadReport = useCallback(async () => { + await props.onClick(timeframe); + }, [props, timeframe]); + + const handleReport = () => { + setIsGeneratingReport(true); + downloadReport() + .catch((error: unknown) => { + open({ + title: "Error", + contents: "Error generating conformance report", + }); + logger.error(error); + }) + .finally(() => { + setIsGeneratingReport(false); + }); + }; + + return ( +
+