fix(settings): normalize Visibility, Privacy, BotSpam tabs to design standards
This commit is contained in:
@@ -91,7 +91,7 @@ export default function SiteBotSpamTab({ siteId, onDirtyChange, onRegisterSave }
|
||||
<ShieldCheck weight="bold" className="w-5 h-5 text-brand-orange" />
|
||||
<div>
|
||||
<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>
|
||||
<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="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-xs text-neutral-400 mt-1">Sessions filtered</p>
|
||||
<p className="text-xs text-neutral-500 mt-1">Sessions filtered</p>
|
||||
</div>
|
||||
<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-xs text-neutral-400 mt-1">Events filtered</p>
|
||||
<p className="text-xs text-neutral-500 mt-1">Events filtered</p>
|
||||
</div>
|
||||
<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-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>
|
||||
)}
|
||||
@@ -138,16 +138,13 @@ export default function SiteBotSpamTab({ siteId, onDirtyChange, onRegisterSave }
|
||||
|
||||
{/* Suspicious only filter (review mode only) */}
|
||||
{botView === 'review' && (
|
||||
<label className="flex items-center gap-2 text-sm text-neutral-400">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={suspiciousOnly}
|
||||
onChange={e => setSuspiciousOnly(e.target.checked)}
|
||||
className="w-4 h-4 rounded"
|
||||
style={{ accentColor: '#FD5E0F' }}
|
||||
/>
|
||||
Suspicious only
|
||||
</label>
|
||||
<div className="flex items-center justify-between py-3 px-4 rounded-xl bg-neutral-800/30 border border-neutral-800">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-white">Suspicious only</p>
|
||||
<p className="text-xs text-neutral-500">Show only sessions flagged as suspicious.</p>
|
||||
</div>
|
||||
<Toggle checked={suspiciousOnly} onChange={() => setSuspiciousOnly(v => !v)} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Bulk actions bar */}
|
||||
@@ -168,7 +165,7 @@ export default function SiteBotSpamTab({ siteId, onDirtyChange, onRegisterSave }
|
||||
{(sessions || [])
|
||||
.filter(s => botView === 'blocked' ? s.bot_filtered : !s.bot_filtered)
|
||||
.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
|
||||
type="checkbox"
|
||||
checked={selectedSessions.has(session.session_id)}
|
||||
|
||||
@@ -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>
|
||||
<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>
|
||||
<Toggle checked={checked} onChange={onToggle} />
|
||||
</div>
|
||||
@@ -162,11 +162,11 @@ export default function SitePrivacyTab({ siteId, onDirtyChange, onRegisterSave }
|
||||
</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>
|
||||
<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>
|
||||
<Select
|
||||
value={String(dataRetention)}
|
||||
@@ -199,7 +199,7 @@ export default function SitePrivacyTab({ siteId, onDirtyChange, onRegisterSave }
|
||||
onChange={e => setExcludedPaths(e.target.value)}
|
||||
rows={4}
|
||||
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>
|
||||
</div>
|
||||
@@ -208,11 +208,11 @@ export default function SitePrivacyTab({ siteId, onDirtyChange, onRegisterSave }
|
||||
{/* PageSpeed Monitoring */}
|
||||
<div className="space-y-3 pt-6 border-t border-neutral-800">
|
||||
<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>
|
||||
<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>
|
||||
{psiConfig?.enabled ? (
|
||||
<Select
|
||||
@@ -236,14 +236,14 @@ export default function SitePrivacyTab({ siteId, onDirtyChange, onRegisterSave }
|
||||
{/* Privacy Policy */}
|
||||
<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>
|
||||
<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-amber-600">This is provided for convenience and is not legal advice. Consult a lawyer for compliance requirements.</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 dark:text-amber-500">This is provided for convenience and is not legal advice. Consult a lawyer for compliance requirements.</p>
|
||||
<div className="relative">
|
||||
<textarea
|
||||
readOnly
|
||||
rows={6}
|
||||
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
|
||||
type="button"
|
||||
|
||||
@@ -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>
|
||||
<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>
|
||||
<Toggle checked={isPublic} onChange={() => setIsPublic(p => !p)} />
|
||||
</div>
|
||||
@@ -107,7 +107,7 @@ export default function SiteVisibilityTab({ siteId, onDirtyChange, onRegisterSav
|
||||
<Lock weight="bold" className="w-4 h-4 text-neutral-500" />
|
||||
<div>
|
||||
<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>
|
||||
<Toggle checked={passwordEnabled} onChange={() => setPasswordEnabled(p => !p)} />
|
||||
|
||||
Reference in New Issue
Block a user