import { zodResolver } from '@hookform/resolvers/zod' import { useRouter } from 'next/router' import { useMemo } from 'react' import { SubmitHandler, useForm } from 'react-hook-form' import { toast } from 'sonner' import { Button, Dialog, DialogContent, DialogFooter, DialogHeader, DialogSection, DialogSectionSeparator, DialogTitle, Form, FormControl, FormField, Input, Textarea, } from 'ui' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' import * as z from 'zod' import { useContentUpsertMutation } from '@/data/content/content-upsert-mutation' import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject' import { uuidv4 } from '@/lib/helpers' import { useProfile } from '@/lib/profile' export interface CreateReportModal { visible: boolean onCancel: () => void afterSubmit: () => void } const formSchema = z.object({ name: z.string().min(1, 'Required'), description: z.string().optional(), }) type CustomReport = z.infer export const CreateReportModal = ({ visible, onCancel, afterSubmit }: CreateReportModal) => { const router = useRouter() const { profile } = useProfile() const { data: project } = useSelectedProjectQuery() const ref = project?.ref ?? 'default' // Preserve date range query parameters when navigating to new report const preservedQueryParams = useMemo(() => { const { its, ite, isHelper, helperText } = router.query const params = new URLSearchParams() if (its && typeof its === 'string') params.set('its', its) if (ite && typeof ite === 'string') params.set('ite', ite) if (isHelper && typeof isHelper === 'string') params.set('isHelper', isHelper) if (helperText && typeof helperText === 'string') params.set('helperText', helperText) const queryString = params.toString() return queryString ? `?${queryString}` : '' }, [router.query]) const { mutate: upsertContent, isPending: isCreating } = useContentUpsertMutation({ onSuccess: (_, vars) => { toast.success('Successfully created new report') const newReportId = vars.payload.id router.push(`/project/${ref}/observability/${newReportId}${preservedQueryParams}`) afterSubmit() }, onError: (error) => { toast.error(`Failed to create report: ${error.message}`) }, }) const createCustomReport: SubmitHandler = async ({ name, description }) => { if (!ref) return console.error('Project ref is required') if (!profile) return console.error('Profile is required') upsertContent({ projectRef: ref, payload: { id: uuidv4(), type: 'report', name, description: description || '', visibility: 'project', owner_id: profile?.id, content: { schema_version: 1, period_start: { time_period: '7d', date: '', }, period_end: { time_period: 'today', date: '', }, interval: '1d', layout: [], }, }, }) } const handleCancel = () => { onCancel() form.reset() } const form = useForm({ resolver: zodResolver(formSchema), defaultValues: { name: '', description: '' }, }) const { isDirty } = form.formState return ( Create a custom report
( )} /> (