"use client"; import { MessageSquareText } from "lucide-react"; import { usePathname } from "next/navigation"; import posthogClient from "posthog-js"; import type { Survey } from "posthog-js"; import { useEffect, useState } from "react"; import { Button } from "@/components/shadcn/button/button"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/shadcn/popover"; import { useMediaQuery } from "@/hooks/use-media-query"; import { useMountEffect } from "@/hooks/use-mount-effect"; import { useStore } from "@/hooks/use-store"; import { isLighthouseChatRoute } from "@/lib/lighthouse-routes"; import { clampSidePanelWidth, SIDE_PANEL_PUSH_MEDIA_QUERY, } from "@/lib/ui-layout"; import { cn } from "@/lib/utils"; import { useSidePanelStore } from "@/store/side-panel"; import { FeedbackForm } from "./feedback-form"; const SURVEY_NAME = "Prowler Feedback"; const FEEDBACK_GUTTER_PX = 24; const SURVEY_EVENT = { SHOWN: "survey shown", SENT: "survey sent", DISMISSED: "survey dismissed", } as const; interface RuntimeFeedbackSurveyProps { posthogKey: string; posthogHost: string; } export default function RuntimeFeedbackSurvey({ posthogKey, posthogHost, }: RuntimeFeedbackSurveyProps) { const pathname = usePathname(); const [survey, setSurvey] = useState(null); const [open, setOpen] = useState(false); const [response, setResponse] = useState(""); const [submitted, setSubmitted] = useState(false); const sidePanelOpen = useStore(useSidePanelStore, (state) => state.isOpen); const sidePanelWidth = useStore(useSidePanelStore, (state) => state.width); const sidePanelResizing = useStore( useSidePanelStore, (state) => state.isResizing, ); const isPushViewport = useMediaQuery(SIDE_PANEL_PUSH_MEDIA_QUERY); const sidePanelVisible = Boolean(sidePanelOpen) && !isLighthouseChatRoute(pathname); useMountEffect(() => { if (!posthogClient.__loaded) { posthogClient.init(posthogKey, { api_host: posthogHost, ui_host: posthogHost, autocapture: false, capture_pageview: false, capture_pageleave: false, }); } return posthogClient.onSurveysLoaded((surveys) => { setSurvey( surveys.find( (item) => item.name === SURVEY_NAME && item.type === "api", ) ?? null, ); }); }); useEffect(() => { if (sidePanelVisible && !isPushViewport) setOpen(false); }, [sidePanelVisible, isPushViewport]); const question = survey?.questions?.[0]; if (!survey || question?.type !== "open") return null; if (sidePanelVisible && !isPushViewport) return null; const questionId = question.id ?? ""; const appearance = survey.appearance; const trimmedResponse = response.trim(); const identity = { $survey_id: survey.id, $survey_name: survey.name }; const pushedRight = sidePanelVisible && sidePanelWidth !== undefined && isPushViewport ? clampSidePanelWidth(sidePanelWidth) + FEEDBACK_GUTTER_PX : undefined; const handleOpenChange = (nextOpen: boolean) => { setOpen(nextOpen); if (nextOpen) { setSubmitted(false); setResponse(""); posthogClient.capture(SURVEY_EVENT.SHOWN, identity); return; } if (!submitted) posthogClient.capture(SURVEY_EVENT.DISMISSED, identity); }; const handleSubmit = () => { if (!trimmedResponse) return; posthogClient.capture(SURVEY_EVENT.SENT, { ...identity, $survey_questions: [ { id: questionId, question: question.question, response: trimmedResponse, }, ], [`$survey_response_${questionId}`]: trimmedResponse, $survey_response: trimmedResponse, }); setSubmitted(true); }; return ( {submitted ? (

{appearance?.thankYouMessageHeader ?? "Thanks for the feedback!"}

{appearance?.thankYouMessageDescription ? (

{appearance.thankYouMessageDescription}

) : null}
) : ( )}
); }