From 8e3b63506a57e842e00cdd4fd7ed81e2a70ddb0b Mon Sep 17 00:00:00 2001 From: Nabil-Fareed Alikhan Date: Thu, 6 Aug 2026 18:55:46 +0100 Subject: [PATCH] Simplify bug reporting --- components/BugReportModal.tsx | 187 +++++++--------------------------- docs/troubleshooting.md | 2 +- functions/api/report-bug.ts | 128 ----------------------- src/pages/Home.tsx | 1 - tests/e2e/brigx.spec.ts | 11 +- 5 files changed, 44 insertions(+), 285 deletions(-) delete mode 100644 functions/api/report-bug.ts diff --git a/components/BugReportModal.tsx b/components/BugReportModal.tsx index ba1702f..252ece0 100644 --- a/components/BugReportModal.tsx +++ b/components/BugReportModal.tsx @@ -1,168 +1,49 @@ -import { useEffect, useRef, useState } from 'react'; -import { APP_VERSION } from '@/lib/version'; - interface BugReportModalProps { - debugOutput: string; onClose: () => void; } -interface TurnstileApi { - render: (container: HTMLElement, options: { - sitekey: string; - callback: (token: string) => void; - 'expired-callback': () => void; - 'error-callback': () => void; - }) => string; - remove: (widgetId: string) => void; -} - -declare global { - interface Window { - turnstile?: TurnstileApi; - } -} - -const TURNSTILE_SCRIPT = 'https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit'; -const TEST_SITE_KEY = '1x00000000000000000000AA'; - -export default function BugReportModal({ debugOutput, onClose }: BugReportModalProps) { - const [happened, setHappened] = useState(''); - const [expected, setExpected] = useState(''); - const [steps, setSteps] = useState(''); - const [email, setEmail] = useState(''); - const [includeDebugOutput, setIncludeDebugOutput] = useState(false); - const [turnstileToken, setTurnstileToken] = useState(''); - const [status, setStatus] = useState<'idle' | 'sending' | 'sent' | 'error'>('idle'); - const [errorMessage, setErrorMessage] = useState(''); - const turnstileRef = useRef(null); - - useEffect(() => { - const sitekey = import.meta.env.VITE_TURNSTILE_SITE_KEY || (import.meta.env.DEV ? TEST_SITE_KEY : ''); - if (!sitekey || !turnstileRef.current) return; - - let widgetId: string | null = null; - let cancelled = false; - - const renderWidget = () => { - if (cancelled || !window.turnstile || !turnstileRef.current || widgetId) return; - widgetId = window.turnstile.render(turnstileRef.current, { - sitekey, - callback: setTurnstileToken, - 'expired-callback': () => setTurnstileToken(''), - 'error-callback': () => setTurnstileToken(''), - }); - }; - - const existingScript = document.querySelector(`script[src="${TURNSTILE_SCRIPT}"]`); - if (existingScript) { - if (window.turnstile) renderWidget(); - else existingScript.addEventListener('load', renderWidget, { once: true }); - } else { - const script = document.createElement('script'); - script.src = TURNSTILE_SCRIPT; - script.async = true; - script.defer = true; - script.addEventListener('load', renderWidget, { once: true }); - document.head.appendChild(script); - } - - return () => { - cancelled = true; - if (widgetId && window.turnstile) window.turnstile.remove(widgetId); - }; - }, []); - - const submitReport = async (event: React.FormEvent) => { - event.preventDefault(); - setStatus('sending'); - setErrorMessage(''); - - try { - const response = await fetch('/api/report-bug', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - happened, - expected, - steps, - email, - debugOutput: includeDebugOutput ? debugOutput : '', - turnstileToken, - environment: { - appVersion: APP_VERSION, - page: window.location.href, - userAgent: navigator.userAgent, - }, - }), - }); - - const responseBody = await response.text(); - let result: { error?: string } = {}; - if (responseBody) { - try { - result = JSON.parse(responseBody) as { error?: string }; - } catch { - // Some hosting and proxy errors return HTML or plain text. The HTTP - // status below is more useful to the reporter than a JSON parse error. - } - } - - if (!response.ok) { - const localDevelopmentError = import.meta.env.DEV && response.status === 404 - ? 'Bug reports cannot be sent from the local Vite server because the Cloudflare reporting endpoint is not running. Submit the report from the deployed BRIGX site.' - : ''; - throw new Error(result.error || localDevelopmentError || `The report could not be sent (HTTP ${response.status}).`); - } - setStatus('sent'); - } catch (error) { - setStatus('error'); - setErrorMessage(error instanceof Error ? error.message : 'The report could not be sent.'); - } - }; +const REPORT_EMAIL = 'nabil@happykhan.com'; + +export default function BugReportModal({ onClose }: BugReportModalProps) { + const reportTemplate = [ + 'Hello,', + '', + 'What happened?', + '', + 'What did you expect?', + '', + 'Steps to reproduce:', + '', + `BRIGX page: ${window.location.href}`, + 'Browser and operating system:', + 'Relevant error message:', + ].join('\n'); + const emailHref = `mailto:${REPORT_EMAIL}?subject=${encodeURIComponent('BRIGX bug report')}&body=${encodeURIComponent(reportTemplate)}`; return (
-
event.stopPropagation()}> +
event.stopPropagation()}>

Report a bug

- {status === 'sent' ? ( -
-

Thanks. Your report has been sent.

- -
- ) : ( -
-