Instant ai assistant toggle

This commit is contained in:
Emil
2026-02-21 17:28:54 +01:00
parent fa5e14de83
commit f5c9ebaf95
5 changed files with 47 additions and 14 deletions
+1 -11
View File
@@ -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 (
<div className="min-h-screen bg-background">
{/* Skip to content link for keyboard/screen reader users */}
@@ -64,7 +54,7 @@ export default async function DashboardLayout({
{children}
</div>
</main>
{showAiChat && <ChatWidget />}
<ChatWidget />
</div>
)
}
+2 -2
View File
@@ -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'
/**
+36 -1
View File
@@ -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 (
<>
+5
View File
@@ -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
+3
View File
@@ -301,6 +301,8 @@ export function makeInvoice(overrides: Partial<Invoice> = {}): 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,