'use client' import { useState, useEffect, useRef } from 'react' import { Button, Select, Toggle, toast, Spinner } from '@ciphera-net/ui' import { useSite, useSubscription, usePageSpeedConfig } from '@/lib/swr/dashboard' import { updateSite } from '@/lib/api/sites' import { updatePageSpeedConfig } from '@/lib/api/pagespeed' import { getRetentionOptionsForPlan, formatRetentionMonths } from '@/lib/plans' import { generatePrivacySnippet } from '@/lib/utils/privacySnippet' import { Copy, CheckCircle } from '@phosphor-icons/react' import Link from 'next/link' const GEO_OPTIONS = [ { value: 'full', label: 'Full (country, region, city)' }, { value: 'country', label: 'Country only' }, { value: 'none', label: 'Disabled' }, ] function PrivacyToggle({ label, desc, checked, onToggle }: { label: string; desc: string; checked: boolean; onToggle: () => void }) { return (

{label}

{desc}

) } export default function SitePrivacyTab({ siteId, onDirtyChange }: { siteId: string; onDirtyChange?: (dirty: boolean) => void }) { const { data: site, mutate } = useSite(siteId) const { data: subscription, error: subscriptionError, mutate: mutateSubscription } = useSubscription() const { data: psiConfig, mutate: mutatePSIConfig } = usePageSpeedConfig(siteId) const [collectPagePaths, setCollectPagePaths] = useState(true) const [collectReferrers, setCollectReferrers] = useState(true) const [collectDeviceInfo, setCollectDeviceInfo] = useState(true) const [collectScreenRes, setCollectScreenRes] = useState(true) const [collectGeoData, setCollectGeoData] = useState('full') const [hideUnknownLocations, setHideUnknownLocations] = useState(false) const [dataRetention, setDataRetention] = useState(6) const [excludedPaths, setExcludedPaths] = useState('') const [snippetCopied, setSnippetCopied] = useState(false) const [saving, setSaving] = useState(false) const [isDirty, setIsDirty] = useState(false) const initialRef = useRef('') // Sync form state from site data — only on first load, not on SWR revalidation const hasInitialized = useRef(false) useEffect(() => { if (!site || hasInitialized.current) return setCollectPagePaths(site.collect_page_paths ?? true) setCollectReferrers(site.collect_referrers ?? true) setCollectDeviceInfo(site.collect_device_info ?? true) setCollectScreenRes(site.collect_screen_resolution ?? true) setCollectGeoData(site.collect_geo_data ?? 'full') setHideUnknownLocations(site.hide_unknown_locations ?? false) setDataRetention(site.data_retention_months ?? 6) setExcludedPaths((site.excluded_paths || []).join('\n')) initialRef.current = JSON.stringify({ collectPagePaths: site.collect_page_paths ?? true, collectReferrers: site.collect_referrers ?? true, collectDeviceInfo: site.collect_device_info ?? true, collectScreenRes: site.collect_screen_resolution ?? true, collectGeoData: site.collect_geo_data ?? 'full', hideUnknownLocations: site.hide_unknown_locations ?? false, dataRetention: site.data_retention_months ?? 6, excludedPaths: (site.excluded_paths || []).join('\n'), }) hasInitialized.current = true setIsDirty(false) }, [site]) // Track dirty state useEffect(() => { if (!initialRef.current) return const current = JSON.stringify({ collectPagePaths, collectReferrers, collectDeviceInfo, collectScreenRes, collectGeoData, hideUnknownLocations, dataRetention, excludedPaths }) const dirty = current !== initialRef.current setIsDirty(dirty) onDirtyChange?.(dirty) }, [collectPagePaths, collectReferrers, collectDeviceInfo, collectScreenRes, collectGeoData, hideUnknownLocations, dataRetention, excludedPaths, onDirtyChange]) const handleSave = async () => { setSaving(true) try { await updateSite(siteId, { name: site?.name || '', collect_page_paths: collectPagePaths, collect_referrers: collectReferrers, collect_device_info: collectDeviceInfo, collect_screen_resolution: collectScreenRes, collect_geo_data: collectGeoData as 'full' | 'country' | 'none', hide_unknown_locations: hideUnknownLocations, data_retention_months: dataRetention, excluded_paths: excludedPaths.split('\n').map(p => p.trim()).filter(Boolean), }) await mutate() initialRef.current = JSON.stringify({ collectPagePaths, collectReferrers, collectDeviceInfo, collectScreenRes, collectGeoData, hideUnknownLocations, dataRetention, excludedPaths }) onDirtyChange?.(false) toast.success('Privacy settings updated') } catch { toast.error('Failed to save') } finally { setSaving(false) } } if (!site) return
return (

Data & Privacy

Control what data is collected from your visitors.

setCollectPagePaths(v => !v)} /> setCollectReferrers(v => !v)} /> setCollectDeviceInfo(v => !v)} /> setCollectScreenRes(v => !v)} /> setHideUnknownLocations(v => !v)} />
setDataRetention(Number(v))} options={getRetentionOptionsForPlan(subscription?.plan_id).map(o => ({ value: String(o.value), label: o.label }))} variant="input" className="min-w-[160px]" />
{subscription && (

Your {subscription.plan_id?.includes('pro') ? 'Pro' : 'Free'} plan supports up to {formatRetentionMonths(Math.max(...getRetentionOptionsForPlan(subscription.plan_id).map(o => o.value)))} of data retention.

)} {(!subscription || subscription.plan_id?.includes('free')) && (

Upgrade for longer retention.

)}
{/* Path Filtering */}

Path Filtering