Files
pragativeer-v2/src/app/admin/settings/page.tsx
ectasy663 c17785e38a design: cyan -> rgb(12,96,96) in light theme, #00F0FF stays in dark theme
- globals.css: add --cyan-ai CSS variable (rgb(12,96,96) light / #00F0FF dark)
  + opacity variants --cyan-ai-10/20/30/40/50/80
- Bulk replace all #00F0FF hardcoded Tailwind arbitrary values with
  var(--cyan-ai) / var(--cyan-ai-10) / etc across 55+ TSX/TS files
- Shadow glow colours also updated (suppressed by box-shadow:none in light mode)
- TypeScript: 0 errors
2026-09-20 12:19:23 +05:30

170 lines
8.5 KiB
TypeScript

"use client";
import { useState, useEffect } from "react";
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
export default function SettingsPage() {
const [settings, setSettings] = useState({
maintenance_mode: false,
allow_new_registrations: true,
enable_free_trial: true,
trial_duration_days: 5,
trial_tier: "Al_Coach"
});
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch("/api/admin/settings")
.then(res => res.json())
.then(data => {
if(data && !data.detail) {
setSettings(prev => ({ ...prev, ...data }));
}
setLoading(false);
})
.catch(err => {
console.error("Failed to load settings:", err);
setLoading(false);
});
}, []);
const saveSettings = async (section: string, overrides: Partial<typeof settings> = {}) => {
try {
const payload = { ...settings, ...overrides };
const res = await fetch("/api/admin/settings", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload)
});
if (res.ok) {
alert(`${section} saved successfully!`);
setSettings(payload);
} else {
alert(`Failed to save ${section}.`);
}
} catch (err) {
alert("Error saving settings.");
}
};
const handleToggle = (key: keyof typeof settings, sectionName: string) => {
const newValue = !settings[key];
setSettings(prev => ({ ...prev, [key]: newValue }));
saveSettings(sectionName, { [key]: newValue });
};
if (loading) return <div className="p-8 animate-pulse text-muted-foreground font-bold">Loading System Settings...</div>;
return (
<div className="p-8 space-y-8 animate-in fade-in slide-in-from-bottom-4 duration-500 max-w-4xl">
<div>
<h1 className="text-3xl font-bold tracking-tight">System Settings</h1>
<p className="text-muted-foreground mt-1">Configure global application variables and security protocols.</p>
</div>
<div className="space-y-6">
<Card className="border-border bg-secondary/10">
<CardHeader>
<CardTitle>AI Inference Configuration</CardTitle>
<CardDescription>Manage the underlying LLM models and API keys for the AI agents.</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-2">
<label className="text-sm font-bold">Primary Model Name</label>
<input type="text" defaultValue="gemini-1.5-pro-experimental" className="w-full bg-background border border-border rounded-lg px-4 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[var(--cyan-ai)]" />
</div>
<div className="space-y-2">
<label className="text-sm font-bold">OpenAI API Key (Fallback)</label>
<input type="password" defaultValue="sk-........................" className="w-full bg-background border border-border rounded-lg px-4 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[var(--cyan-ai)]" />
</div>
<Button onClick={() => alert("Configuration Saved via Admin Panel")} className="bg-[var(--cyan-ai)] text-background hover:bg-[var(--cyan-ai-80)] font-bold">Save Configuration</Button>
</CardContent>
</Card>
<Card className="border-border bg-secondary/10">
<CardHeader>
<CardTitle>Trial Management</CardTitle>
<CardDescription>Configure the trial length and tier access for new signups.</CardDescription>
</CardHeader>
<CardContent className="space-y-6">
<div className="flex items-center justify-between p-4 bg-background border border-border rounded-xl">
<div>
<div className="font-bold">Enable Free Trial</div>
<div className="text-sm text-muted-foreground">Offer a trial to newly registered users.</div>
</div>
<div
onClick={() => handleToggle('enable_free_trial', 'Free Trial')}
className={`h-6 w-11 rounded-full relative cursor-pointer transition-colors ${settings.enable_free_trial ? 'bg-primary border border-primary shadow-[0_0_10px_var(--color-primary)]' : 'bg-secondary border border-border'}`}>
<div className={`absolute top-1 size-4 rounded-full transition-all ${settings.enable_free_trial ? 'right-1 bg-primary-foreground' : 'left-1 bg-muted-foreground'}`}></div>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<label className="text-sm font-bold">Trial Duration (Days)</label>
<input
type="number"
value={settings.trial_duration_days}
onChange={(e) => setSettings(prev => ({ ...prev, trial_duration_days: parseInt(e.target.value) || 0 }))}
className="w-full bg-background border border-border rounded-lg px-4 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[var(--cyan-ai)]"
/>
</div>
<div className="space-y-2">
<label className="text-sm font-bold">Trial Access Tier</label>
<select
value={settings.trial_tier}
onChange={(e) => setSettings(prev => ({ ...prev, trial_tier: e.target.value }))}
className="w-full bg-background border border-border rounded-lg px-4 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[var(--cyan-ai)]">
<option value="Pro">Pro Tier</option>
<option value="Al_Coach">AI Coach (All Features)</option>
</select>
</div>
</div>
<Button onClick={() => saveSettings("Trial Settings")} className="bg-[var(--cyan-ai)] text-background hover:bg-[var(--cyan-ai-80)] font-bold">Update Trial Settings</Button>
</CardContent>
</Card>
<Card className="border-border bg-secondary/10">
<CardHeader>
<CardTitle>Platform Maintenance</CardTitle>
<CardDescription>Global toggles for site availability.</CardDescription>
</CardHeader>
<CardContent className="space-y-6">
<div className="flex items-center justify-between p-4 bg-background border border-border rounded-xl">
<div>
<div className="font-bold">Maintenance Mode</div>
<div className="text-sm text-muted-foreground">Disable all student access and show maintenance screen.</div>
</div>
<div
onClick={() => handleToggle('maintenance_mode', 'Maintenance Mode')}
className={`h-6 w-11 rounded-full relative cursor-pointer transition-colors ${settings.maintenance_mode ? 'bg-red-500 border border-red-500 shadow-[0_0_10px_rgba(239,68,68,0.8)]' : 'bg-secondary border border-border'}`}>
<div className={`absolute top-1 size-4 rounded-full transition-all ${settings.maintenance_mode ? 'right-1 bg-white' : 'left-1 bg-muted-foreground'}`}></div>
</div>
</div>
<div className="flex items-center justify-between p-4 bg-background border border-border rounded-xl">
<div>
<div className="font-bold">Allow New Registrations</div>
<div className="text-sm text-muted-foreground">Open the `/signup` route for new users.</div>
</div>
<div
onClick={() => handleToggle('allow_new_registrations', 'Registration Setting')}
className={`h-6 w-11 rounded-full relative cursor-pointer transition-colors ${settings.allow_new_registrations ? 'bg-primary border border-primary shadow-[0_0_10px_var(--color-primary)]' : 'bg-secondary border border-border'}`}>
<div className={`absolute top-1 size-4 rounded-full transition-all ${settings.allow_new_registrations ? 'right-1 bg-primary-foreground' : 'left-1 bg-muted-foreground'}`}></div>
</div>
</div>
</CardContent>
</Card>
<Card className="border-red-500/20 bg-red-500/5">
<CardHeader>
<CardTitle className="text-red-500">Danger Zone</CardTitle>
</CardHeader>
<CardContent>
<Button onClick={() => alert("Cache Purged.")} className="bg-red-500 text-white hover:bg-red-600 font-bold">Purge Generated Cache</Button>
</CardContent>
</Card>
</div>
</div>
)
}