From f5c9ebaf953a11a78ce748452e447abd5f1c2d58 Mon Sep 17 00:00:00 2001 From: Emil Date: Sat, 21 Feb 2026 17:28:54 +0100 Subject: [PATCH] Instant ai assistant toggle --- app/(dashboard)/layout.tsx | 12 +-------- app/api/invoices/preview-pdf/route.ts | 4 +-- components/chat/ChatWidget.tsx | 37 ++++++++++++++++++++++++++- lib/extensions/hooks.ts | 5 ++++ tests/helpers.ts | 3 +++ 5 files changed, 47 insertions(+), 14 deletions(-) diff --git a/app/(dashboard)/layout.tsx b/app/(dashboard)/layout.tsx index 58119570..bc6ec7fc 100644 --- a/app/(dashboard)/layout.tsx +++ b/app/(dashboard)/layout.tsx @@ -35,16 +35,6 @@ export default async function DashboardLayout({ .eq('user_id', user.id) .eq('enabled', true) - // Check if ai-chat is explicitly disabled (legacy default: enabled when no row exists) - const { data: aiChatToggle } = await supabase - .from('extension_toggles') - .select('enabled') - .eq('user_id', user.id) - .eq('sector_slug', 'general') - .eq('extension_slug', 'ai-chat') - .single() - const showAiChat = aiChatToggle ? aiChatToggle.enabled : true - return (
{/* Skip to content link for keyboard/screen reader users */} @@ -64,7 +54,7 @@ export default async function DashboardLayout({ {children}
- {showAiChat && } + ) } diff --git a/app/api/invoices/preview-pdf/route.ts b/app/api/invoices/preview-pdf/route.ts index b864a1a6..0dd8b28a 100644 --- a/app/api/invoices/preview-pdf/route.ts +++ b/app/api/invoices/preview-pdf/route.ts @@ -1,8 +1,8 @@ import { createClient } from '@/lib/supabase/server' import { NextResponse } from 'next/server' import { renderToBuffer } from '@react-pdf/renderer' -import { InvoicePDF } from '@/lib/invoice/pdf-template' -import { getVatRules } from '@/lib/invoice/vat-rules' +import { InvoicePDF } from '@/lib/invoices/pdf-template' +import { getVatRules } from '@/lib/invoices/vat-rules' import type { Invoice, InvoiceItem, Customer, CompanySettings, InvoiceDocumentType } from '@/types' /** diff --git a/components/chat/ChatWidget.tsx b/components/chat/ChatWidget.tsx index 7b44d80a..ad50594a 100644 --- a/components/chat/ChatWidget.tsx +++ b/components/chat/ChatWidget.tsx @@ -1,6 +1,6 @@ 'use client' -import { useState } from 'react' +import { useState, useEffect } from 'react' import { Button } from '@/components/ui/button' import { ChatPanel } from './ChatPanel' import { MessageCircle, X } from 'lucide-react' @@ -8,6 +8,41 @@ import { cn } from '@/lib/utils' export function ChatWidget() { const [isOpen, setIsOpen] = useState(false) + // Default to true for legacy compatibility (ai-chat defaults to enabled) + const [enabled, setEnabled] = useState(true) + const [loaded, setLoaded] = useState(false) + + // Fetch initial toggle state + useEffect(() => { + const check = async () => { + try { + const res = await fetch('/api/extensions/toggles/general/ai-chat') + if (res.ok) { + const { data } = await res.json() + // Legacy: enabled by default when no toggle row exists + setEnabled(data?.enabled ?? true) + } + } finally { + setLoaded(true) + } + } + check() + }, []) + + // Listen for real-time toggle changes + useEffect(() => { + const handler = (e: Event) => { + const { sectorSlug, extensionSlug, enabled: newValue } = (e as CustomEvent).detail + if (sectorSlug === 'general' && extensionSlug === 'ai-chat') { + setEnabled(newValue) + if (!newValue) setIsOpen(false) + } + } + window.addEventListener('extension-toggle-changed', handler) + return () => window.removeEventListener('extension-toggle-changed', handler) + }, []) + + if (!loaded || !enabled) return null return ( <> diff --git a/lib/extensions/hooks.ts b/lib/extensions/hooks.ts index 267cb15d..ba41a3b6 100644 --- a/lib/extensions/hooks.ts +++ b/lib/extensions/hooks.ts @@ -62,6 +62,11 @@ export function useExtensionToggle(sectorSlug: string, extensionSlug: string) { }) if (!res.ok) { setEnabled(!newValue) // Revert on error + } else { + // Notify other components about the toggle change + window.dispatchEvent(new CustomEvent('extension-toggle-changed', { + detail: { sectorSlug, extensionSlug, enabled: newValue }, + })) } } catch { setEnabled(!newValue) // Revert on error diff --git a/tests/helpers.ts b/tests/helpers.ts index 6b8b80c2..20b4b60b 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -301,6 +301,8 @@ export function makeInvoice(overrides: Partial = {}): Invoice { notes: null, reverse_charge_text: null, credited_invoice_id: null, + document_type: 'invoice', + converted_from_id: null, paid_at: null, paid_amount: null, created_at: '2024-06-15T14:30:00Z', @@ -435,6 +437,7 @@ export function makeCompanySettings( invoice_prefix: 'F', next_invoice_number: 1, invoice_default_days: 30, + invoice_default_notes: null, onboarding_step: 6, onboarding_complete: true, sector_slug: null,