fix(settings): normalize Visibility, Privacy, BotSpam tabs to design standards

This commit is contained in:
Usman Baig
2026-03-25 22:21:41 +01:00
parent 1cbc8064e2
commit 4d9c3aeabd
3 changed files with 23 additions and 26 deletions

View File

@@ -91,7 +91,7 @@ export default function SiteBotSpamTab({ siteId, onDirtyChange, onRegisterSave }
<ShieldCheck weight="bold" className="w-5 h-5 text-brand-orange" /> <ShieldCheck weight="bold" className="w-5 h-5 text-brand-orange" />
<div> <div>
<p className="text-sm font-medium text-white">Enable bot filtering</p> <p className="text-sm font-medium text-white">Enable bot filtering</p>
<p className="text-xs text-neutral-400">Filter known bots, crawlers, referrer spam, and suspicious traffic.</p> <p className="text-xs text-neutral-500">Filter known bots, crawlers, referrer spam, and suspicious traffic.</p>
</div> </div>
</div> </div>
<Toggle checked={filterBots} onChange={() => setFilterBots(p => !p)} /> <Toggle checked={filterBots} onChange={() => setFilterBots(p => !p)} />
@@ -102,15 +102,15 @@ export default function SiteBotSpamTab({ siteId, onDirtyChange, onRegisterSave }
<div className="grid grid-cols-3 gap-3"> <div className="grid grid-cols-3 gap-3">
<div className="rounded-xl border border-neutral-800 bg-neutral-800/30 p-4 text-center"> <div className="rounded-xl border border-neutral-800 bg-neutral-800/30 p-4 text-center">
<p className="text-2xl font-bold text-white">{botStats.filtered_sessions ?? 0}</p> <p className="text-2xl font-bold text-white">{botStats.filtered_sessions ?? 0}</p>
<p className="text-xs text-neutral-400 mt-1">Sessions filtered</p> <p className="text-xs text-neutral-500 mt-1">Sessions filtered</p>
</div> </div>
<div className="rounded-xl border border-neutral-800 bg-neutral-800/30 p-4 text-center"> <div className="rounded-xl border border-neutral-800 bg-neutral-800/30 p-4 text-center">
<p className="text-2xl font-bold text-white">{botStats.filtered_events ?? 0}</p> <p className="text-2xl font-bold text-white">{botStats.filtered_events ?? 0}</p>
<p className="text-xs text-neutral-400 mt-1">Events filtered</p> <p className="text-xs text-neutral-500 mt-1">Events filtered</p>
</div> </div>
<div className="rounded-xl border border-neutral-800 bg-neutral-800/30 p-4 text-center"> <div className="rounded-xl border border-neutral-800 bg-neutral-800/30 p-4 text-center">
<p className="text-2xl font-bold text-white">{botStats.auto_blocked_this_month ?? 0}</p> <p className="text-2xl font-bold text-white">{botStats.auto_blocked_this_month ?? 0}</p>
<p className="text-xs text-neutral-400 mt-1">Auto-blocked this month</p> <p className="text-xs text-neutral-500 mt-1">Auto-blocked this month</p>
</div> </div>
</div> </div>
)} )}
@@ -138,16 +138,13 @@ export default function SiteBotSpamTab({ siteId, onDirtyChange, onRegisterSave }
{/* Suspicious only filter (review mode only) */} {/* Suspicious only filter (review mode only) */}
{botView === 'review' && ( {botView === 'review' && (
<label className="flex items-center gap-2 text-sm text-neutral-400"> <div className="flex items-center justify-between py-3 px-4 rounded-xl bg-neutral-800/30 border border-neutral-800">
<input <div>
type="checkbox" <p className="text-sm font-medium text-white">Suspicious only</p>
checked={suspiciousOnly} <p className="text-xs text-neutral-500">Show only sessions flagged as suspicious.</p>
onChange={e => setSuspiciousOnly(e.target.checked)} </div>
className="w-4 h-4 rounded" <Toggle checked={suspiciousOnly} onChange={() => setSuspiciousOnly(v => !v)} />
style={{ accentColor: '#FD5E0F' }} </div>
/>
Suspicious only
</label>
)} )}
{/* Bulk actions bar */} {/* Bulk actions bar */}
@@ -168,7 +165,7 @@ export default function SiteBotSpamTab({ siteId, onDirtyChange, onRegisterSave }
{(sessions || []) {(sessions || [])
.filter(s => botView === 'blocked' ? s.bot_filtered : !s.bot_filtered) .filter(s => botView === 'blocked' ? s.bot_filtered : !s.bot_filtered)
.map(session => ( .map(session => (
<div key={session.session_id} className="flex items-center gap-3 p-3 rounded-xl border border-neutral-800 hover:border-neutral-700 transition-colors"> <div key={session.session_id} className="flex items-center gap-3 p-3 rounded-xl border border-neutral-800 hover:bg-neutral-800/40 hover:border-neutral-700 transition-colors">
<input <input
type="checkbox" type="checkbox"
checked={selectedSessions.has(session.session_id)} checked={selectedSessions.has(session.session_id)}

View File

@@ -21,7 +21,7 @@ function PrivacyToggle({ label, desc, checked, onToggle }: { label: string; desc
<div className="flex items-center justify-between py-3 px-4 rounded-xl hover:bg-neutral-800/20 transition-colors"> <div className="flex items-center justify-between py-3 px-4 rounded-xl hover:bg-neutral-800/20 transition-colors">
<div> <div>
<p className="text-sm font-medium text-white">{label}</p> <p className="text-sm font-medium text-white">{label}</p>
<p className="text-xs text-neutral-400">{desc}</p> <p className="text-xs text-neutral-500">{desc}</p>
</div> </div>
<Toggle checked={checked} onChange={onToggle} /> <Toggle checked={checked} onChange={onToggle} />
</div> </div>
@@ -162,11 +162,11 @@ export default function SitePrivacyTab({ siteId, onDirtyChange, onRegisterSave }
</div> </div>
)} )}
<div className="p-4 bg-neutral-900/50 rounded-xl border border-neutral-800"> <div className="p-4 bg-neutral-800/30 rounded-xl border border-neutral-800">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div> <div>
<p className="font-medium text-white text-sm">Keep raw event data for</p> <p className="font-medium text-white text-sm">Keep raw event data for</p>
<p className="text-xs text-neutral-400 mt-0.5">Events older than this are automatically deleted. Aggregated daily stats are kept permanently.</p> <p className="text-xs text-neutral-500 mt-0.5">Events older than this are automatically deleted. Aggregated daily stats are kept permanently.</p>
</div> </div>
<Select <Select
value={String(dataRetention)} value={String(dataRetention)}
@@ -199,7 +199,7 @@ export default function SitePrivacyTab({ siteId, onDirtyChange, onRegisterSave }
onChange={e => setExcludedPaths(e.target.value)} onChange={e => setExcludedPaths(e.target.value)}
rows={4} rows={4}
placeholder={"/admin/*\n/staging/*"} placeholder={"/admin/*\n/staging/*"}
className="w-full px-4 py-3 border border-neutral-800 rounded-lg bg-neutral-900/50 text-white font-mono text-sm focus:border-brand-orange focus:ring-4 focus:ring-brand-orange/10 outline-none transition-all" className="w-full px-4 py-3 border border-neutral-800 rounded-lg bg-neutral-800/30 text-white font-mono text-sm focus:border-brand-orange focus:ring-4 focus:ring-brand-orange/10 outline-none transition-all"
/> />
<p className="text-xs text-neutral-500 mt-1">Enter paths to exclude from tracking (one per line). Supports wildcards (e.g., /admin/*).</p> <p className="text-xs text-neutral-500 mt-1">Enter paths to exclude from tracking (one per line). Supports wildcards (e.g., /admin/*).</p>
</div> </div>
@@ -208,11 +208,11 @@ export default function SitePrivacyTab({ siteId, onDirtyChange, onRegisterSave }
{/* PageSpeed Monitoring */} {/* PageSpeed Monitoring */}
<div className="space-y-3 pt-6 border-t border-neutral-800"> <div className="space-y-3 pt-6 border-t border-neutral-800">
<h4 className="text-sm font-medium text-neutral-300">PageSpeed Monitoring</h4> <h4 className="text-sm font-medium text-neutral-300">PageSpeed Monitoring</h4>
<div className="p-4 bg-neutral-900/50 rounded-xl border border-neutral-800"> <div className="p-4 bg-neutral-800/30 rounded-xl border border-neutral-800">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div> <div>
<p className="font-medium text-white text-sm">Check frequency</p> <p className="font-medium text-white text-sm">Check frequency</p>
<p className="text-xs text-neutral-400 mt-0.5">How often PageSpeed Insights runs automated checks.</p> <p className="text-xs text-neutral-500 mt-0.5">How often PageSpeed Insights runs automated checks.</p>
</div> </div>
{psiConfig?.enabled ? ( {psiConfig?.enabled ? (
<Select <Select
@@ -236,14 +236,14 @@ export default function SitePrivacyTab({ siteId, onDirtyChange, onRegisterSave }
{/* Privacy Policy */} {/* Privacy Policy */}
<div className="space-y-3 pt-6 border-t border-neutral-800"> <div className="space-y-3 pt-6 border-t border-neutral-800">
<h4 className="text-sm font-medium text-neutral-300">For your privacy policy</h4> <h4 className="text-sm font-medium text-neutral-300">For your privacy policy</h4>
<p className="text-xs text-neutral-400">Copy the text below into your Privacy Policy. It updates automatically based on your saved settings.</p> <p className="text-xs text-neutral-500">Copy the text below into your Privacy Policy. It updates automatically based on your saved settings.</p>
<p className="text-xs text-amber-600">This is provided for convenience and is not legal advice. Consult a lawyer for compliance requirements.</p> <p className="text-xs text-amber-600 dark:text-amber-500">This is provided for convenience and is not legal advice. Consult a lawyer for compliance requirements.</p>
<div className="relative"> <div className="relative">
<textarea <textarea
readOnly readOnly
rows={6} rows={6}
value={generatePrivacySnippet(site)} value={generatePrivacySnippet(site)}
className="w-full px-4 py-3 pr-12 border border-neutral-800 rounded-xl bg-neutral-900/50 text-neutral-300 text-xs font-mono" className="w-full px-4 py-3 pr-12 border border-neutral-800 rounded-xl bg-neutral-800/30 text-neutral-300 text-xs font-mono"
/> />
<button <button
type="button" type="button"

View File

@@ -76,7 +76,7 @@ export default function SiteVisibilityTab({ siteId, onDirtyChange, onRegisterSav
<div className="flex items-center justify-between py-3 px-4 rounded-xl bg-neutral-800/30 border border-neutral-800"> <div className="flex items-center justify-between py-3 px-4 rounded-xl bg-neutral-800/30 border border-neutral-800">
<div> <div>
<p className="text-sm font-medium text-white">Public Dashboard</p> <p className="text-sm font-medium text-white">Public Dashboard</p>
<p className="text-xs text-neutral-400">Allow anyone with the link to view this dashboard.</p> <p className="text-xs text-neutral-500">Allow anyone with the link to view this dashboard.</p>
</div> </div>
<Toggle checked={isPublic} onChange={() => setIsPublic(p => !p)} /> <Toggle checked={isPublic} onChange={() => setIsPublic(p => !p)} />
</div> </div>
@@ -107,7 +107,7 @@ export default function SiteVisibilityTab({ siteId, onDirtyChange, onRegisterSav
<Lock weight="bold" className="w-4 h-4 text-neutral-500" /> <Lock weight="bold" className="w-4 h-4 text-neutral-500" />
<div> <div>
<p className="text-sm font-medium text-white">Password Protection</p> <p className="text-sm font-medium text-white">Password Protection</p>
<p className="text-xs text-neutral-400">Require a password to view the public dashboard.</p> <p className="text-xs text-neutral-500">Require a password to view the public dashboard.</p>
</div> </div>
</div> </div>
<Toggle checked={passwordEnabled} onChange={() => setPasswordEnabled(p => !p)} /> <Toggle checked={passwordEnabled} onChange={() => setPasswordEnabled(p => !p)} />