import { useState, useEffect, useRef } from 'react' import { Palette, Upload, Trash2, Loader2 } from 'lucide-react' import { getBranding, updateBranding, deleteLogo } from '@/api/branding' import type { BrandingInfo } from '@/api/branding' import { Button } from '@/components/ui/Button' import { cn } from '@/lib/utils' import { toast } from '@/lib/toast' interface BrandingSettingsProps { teamId: string } const MAX_LOGO_SIZE = 2 * 1024 * 1024 // 2MB export function BrandingSettings({ teamId }: BrandingSettingsProps) { const [branding, setBranding] = useState(null) const [isLoading, setIsLoading] = useState(true) const [isSaving, setIsSaving] = useState(false) const [isDeleting, setIsDeleting] = useState(false) const [companyName, setCompanyName] = useState('') const [logoFile, setLogoFile] = useState(null) const [logoPreview, setLogoPreview] = useState(null) const [error, setError] = useState(null) const fileInputRef = useRef(null) useEffect(() => { loadBranding() }, [teamId]) const loadBranding = async () => { setIsLoading(true) try { const data = await getBranding(teamId) setBranding(data) setCompanyName(data.company_display_name || '') if (data.has_logo) { // Construct logo URL from the API const token = localStorage.getItem('access_token') const baseUrl = import.meta.env.VITE_API_URL || 'http://localhost:8000' setLogoPreview(`${baseUrl}/api/v1/teams/${teamId}/branding/logo?token=${token}`) } } catch (err) { console.error('Failed to load branding:', err) } finally { setIsLoading(false) } } const handleFileChange = (e: React.ChangeEvent) => { const file = e.target.files?.[0] if (!file) return if (file.size > MAX_LOGO_SIZE) { setError('Logo must be under 2MB') return } if (!['image/png', 'image/jpeg', 'image/svg+xml'].includes(file.type)) { setError('Only PNG, JPEG, and SVG files are supported') return } setError(null) setLogoFile(file) const reader = new FileReader() reader.onload = () => setLogoPreview(reader.result as string) reader.readAsDataURL(file) } const handleSave = async () => { setIsSaving(true) setError(null) try { const formData = new FormData() if (companyName.trim()) { formData.append('company_display_name', companyName.trim()) } else { formData.append('company_display_name', '') } if (logoFile) { formData.append('logo', logoFile) } const updated = await updateBranding(teamId, formData) setBranding(updated) setLogoFile(null) toast.success('Branding settings saved') } catch (err) { console.error('Failed to save branding:', err) setError('Failed to save. Please try again.') } finally { setIsSaving(false) } } const handleDeleteLogo = async () => { setIsDeleting(true) try { await deleteLogo(teamId) setBranding((prev) => prev ? { ...prev, has_logo: false, logo_content_type: null } : prev) setLogoPreview(null) setLogoFile(null) if (fileInputRef.current) fileInputRef.current.value = '' toast.success('Logo removed') } catch (err) { console.error('Failed to delete logo:', err) toast.error('Failed to remove logo') } finally { setIsDeleting(false) } } if (isLoading) { return (

Branding

) } const hasChanges = companyName !== (branding?.company_display_name || '') || logoFile !== null return (

Branding

Customize your company branding for PDF exports

{/* Company Display Name */}

Shown in the header of exported PDF reports

setCompanyName(e.target.value)} placeholder="Your Company Name" className={cn( 'mt-2 w-full max-w-md rounded-md border border-border bg-card px-3 py-2 text-sm', 'text-foreground placeholder:text-muted-foreground', 'focus:border-[rgba(6,182,212,0.3)] focus:outline-hidden focus:ring-1 focus:ring-primary/20' )} />
{/* Logo Upload */}

PNG, JPEG, or SVG - max 2MB. Displayed in PDF export headers.

{logoPreview ? (
Logo preview
{branding?.has_logo && ( )}
) : (
fileInputRef.current?.click()} className={cn( 'mt-2 flex max-w-md cursor-pointer flex-col items-center justify-center gap-2 rounded-lg border-2 border-dashed border-border', 'bg-card/30 py-8 transition-colors hover:border-muted-foreground' )} >

Click to upload logo

)}
{/* Error */} {error && (

{error}

)} {/* Save */} {hasChanges && (
)}
) } export default BrandingSettings