'use client' import { useEffect, useState } from 'react' import { useParams, useRouter } from 'next/navigation' import { getSite, updateSite, resetSiteData, deleteSite, type Site } from '@/lib/api/sites' import { toast } from 'sonner' import LoadingOverlay from '@/components/LoadingOverlay' import { APP_URL, API_URL } from '@/lib/api/client' const TIMEZONES = [ 'UTC', 'America/New_York', 'America/Los_Angeles', 'America/Chicago', 'America/Toronto', 'Europe/London', 'Europe/Paris', 'Europe/Berlin', 'Europe/Amsterdam', 'Asia/Tokyo', 'Asia/Singapore', 'Asia/Dubai', 'Australia/Sydney', 'Pacific/Auckland', ] export default function SiteSettingsPage() { const params = useParams() const router = useRouter() const siteId = params.id as string const [site, setSite] = useState(null) const [loading, setLoading] = useState(true) const [saving, setSaving] = useState(false) const [formData, setFormData] = useState({ name: '', timezone: 'UTC', is_public: false, password: '', excluded_paths: '' }) const [scriptCopied, setScriptCopied] = useState(false) useEffect(() => { loadSite() }, [siteId]) const loadSite = async () => { try { setLoading(true) const data = await getSite(siteId) setSite(data) setFormData({ name: data.name, timezone: data.timezone || 'UTC', is_public: data.is_public || false, password: '', // Don't show existing password excluded_paths: (data.excluded_paths || []).join('\n') }) } catch (error: any) { toast.error('Failed to load site: ' + (error.message || 'Unknown error')) } finally { setLoading(false) } } const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() setSaving(true) try { const excludedPathsArray = formData.excluded_paths .split('\n') .map(p => p.trim()) .filter(p => p.length > 0) await updateSite(siteId, { name: formData.name, timezone: formData.timezone, is_public: formData.is_public, password: formData.password || undefined, excluded_paths: excludedPathsArray }) toast.success('Site updated successfully') loadSite() } catch (error: any) { toast.error('Failed to update site: ' + (error.message || 'Unknown error')) } finally { setSaving(false) } } const handleResetData = async () => { if (!confirm('Are you sure you want to delete ALL data for this site? This action cannot be undone.')) { return } try { await resetSiteData(siteId) toast.success('All site data has been reset') } catch (error: any) { toast.error('Failed to reset data: ' + (error.message || 'Unknown error')) } } const handleDeleteSite = async () => { const confirmation = prompt('To confirm deletion, please type the site domain:') if (confirmation !== site?.domain) { if (confirmation) toast.error('Domain does not match') return } try { await deleteSite(siteId) toast.success('Site deleted successfully') router.push('/') } catch (error: any) { toast.error('Failed to delete site: ' + (error.message || 'Unknown error')) } } const copyScript = () => { const script = `` navigator.clipboard.writeText(script) setScriptCopied(true) toast.success('Script copied to clipboard') setTimeout(() => setScriptCopied(false), 2000) } if (loading) { return } if (!site) { return (

Site not found

) } return (

Site Settings

Tracking Script

Add this script to your website to start tracking visitors.

{``}
{/* General Configuration */}

General Configuration

setFormData({ ...formData, name: e.target.value })} className="w-full px-4 py-2 border border-neutral-300 dark:border-neutral-700 rounded-lg bg-white dark:bg-neutral-800 text-neutral-900 dark:text-white focus:ring-2 focus:ring-brand-orange focus:border-transparent" />

Domain cannot be changed after creation

{/* Data Filters */}

Data Filters

Enter paths to exclude from tracking (one per line). Supports simple matching (e.g., /admin/*).