From 1ae20dba4ce51f138c45b563852fd7ed42183795 Mon Sep 17 00:00:00 2001 From: Usman Baig Date: Sat, 21 Feb 2026 18:21:43 +0100 Subject: [PATCH] feat: add data retention settings to SiteSettingsPage, including subscription-based options and UI updates for user interaction --- app/sites/[id]/settings/page.tsx | 63 ++++++++++++++++++++++++++++++-- lib/api/sites.ts | 4 ++ lib/plans.ts | 39 ++++++++++++++++++++ lib/utils/privacySnippet.ts | 5 +++ 4 files changed, 108 insertions(+), 3 deletions(-) diff --git a/app/sites/[id]/settings/page.tsx b/app/sites/[id]/settings/page.tsx index c537b68..4a0dc84 100644 --- a/app/sites/[id]/settings/page.tsx +++ b/app/sites/[id]/settings/page.tsx @@ -13,6 +13,8 @@ import { PasswordInput } from '@ciphera-net/ui' import { Select, Modal, Button } from '@ciphera-net/ui' import { APP_URL } from '@/lib/api/client' import { generatePrivacySnippet } from '@/lib/utils/privacySnippet' +import { getSubscription, type SubscriptionDetails } from '@/lib/api/billing' +import { getRetentionOptionsForPlan, formatRetentionMonths } from '@/lib/plans' import { motion, AnimatePresence } from 'framer-motion' import { useAuth } from '@/lib/auth/context' import { @@ -68,8 +70,11 @@ export default function SiteSettingsPage() { // Performance insights setting enable_performance_insights: false, // Bot and noise filtering - filter_bots: true + filter_bots: true, + // Data retention + data_retention_months: 12 }) + const [subscription, setSubscription] = useState(null) const [linkCopied, setLinkCopied] = useState(false) const [snippetCopied, setSnippetCopied] = useState(false) const [showVerificationModal, setShowVerificationModal] = useState(false) @@ -83,6 +88,7 @@ export default function SiteSettingsPage() { useEffect(() => { loadSite() + loadSubscription() }, [siteId]) useEffect(() => { @@ -91,6 +97,15 @@ export default function SiteSettingsPage() { } }, [activeTab, siteId]) + const loadSubscription = async () => { + try { + const sub = await getSubscription() + setSubscription(sub) + } catch { + // * Non-critical; free tier assumed if billing unavailable + } + } + const loadSite = async () => { try { setLoading(true) @@ -111,7 +126,9 @@ export default function SiteSettingsPage() { // Performance insights setting (default to false) enable_performance_insights: data.enable_performance_insights ?? false, // Bot and noise filtering (default to true) - filter_bots: data.filter_bots ?? true + filter_bots: data.filter_bots ?? true, + // Data retention + data_retention_months: data.data_retention_months ?? 12 }) if (data.has_password) { setIsPasswordEnabled(true) @@ -226,7 +243,9 @@ export default function SiteSettingsPage() { // Performance insights setting enable_performance_insights: formData.enable_performance_insights, // Bot and noise filtering - filter_bots: formData.filter_bots + filter_bots: formData.filter_bots, + // Data retention + data_retention_months: formData.data_retention_months }) toast.success('Site updated successfully') loadSite() @@ -821,6 +840,44 @@ export default function SiteSettingsPage() { + {/* Data Retention */} +
+

Data Retention

+
+
+
+

Keep raw event data for

+

+ Events older than this are automatically deleted. Aggregated daily stats are kept permanently. +

+
+