Files
B.Tech-Project-III/negot8/dashboard/app/preferences/page.tsx
2026-04-05 00:43:23 +05:30

352 lines
17 KiB
TypeScript

"use client";
import { useState } from "react";
import Sidebar from "@/components/Sidebar";
function Icon({ name, className = "" }: { name: string; className?: string }) {
return <span className={`material-symbols-outlined ${className}`}>{name}</span>;
}
const PERSONALITIES = [
{
key: "aggressive",
label: "Aggressive",
desc: "Direct, concise, and prioritizes speed over nuance. Best for rapid execution.",
icon: "bolt",
color: "text-red-400",
bg: "bg-red-500/10",
},
{
key: "empathetic",
label: "Empathetic",
desc: "Prioritizes rapport, tone matching, and emotional intelligence. Human-centric.",
icon: "favorite",
color: "text-[#B7A6FB]",
bg: "bg-[#B7A6FB]/20",
},
{
key: "analytical",
label: "Analytical",
desc: "Data-driven, cites sources, and avoids assumptions. Highly logical.",
icon: "query_stats",
color: "text-blue-400",
bg: "bg-blue-500/10",
},
{
key: "balanced",
label: "Balanced",
desc: "The default setting. Adaptable tone that shifts based on the query complexity.",
icon: "balance",
color: "text-emerald-400",
bg: "bg-green-500/10",
},
];
const VOICE_MODELS = [
"Adam (Deep Narration)",
"Bella (Soft & Professional)",
"Charlie (Energetic Male)",
"Dorothy (Warm & Friendly)",
];
export default function PreferencesPage() {
const [personality, setPersonality] = useState("empathetic");
const [voiceModel, setVoiceModel] = useState("Bella (Soft & Professional)");
const [showApiKey, setShowApiKey] = useState(false);
const [showWebhook, setShowWebhook] = useState(false);
const [savedToast, setSavedToast] = useState(false);
const handleSave = () => {
setSavedToast(true);
setTimeout(() => setSavedToast(false), 2500);
};
return (
<div className="flex h-screen w-full overflow-hidden bg-[#020105] text-slate-300 relative">
<div className="absolute inset-0 bg-grid-subtle opacity-20 pointer-events-none" />
<Sidebar />
<main className="flex-1 flex flex-col h-full overflow-hidden relative z-10">
{/* Top bar */}
<header className="h-16 flex items-center justify-between px-6 bg-[#050505]/80 backdrop-blur-md border-b border-white/5 sticky top-0 z-30 shrink-0">
<div>
<h2 className="text-base font-medium text-white tracking-tight">Settings</h2>
<p className="text-[10px] text-slate-600 mt-0.5">
negoT8 <span className="text-[#B7A6FB]/60">| Preferences</span>
</p>
</div>
<div className="flex items-center gap-3">
<button className="size-9 rounded-lg bg-[#B7A6FB]/10 border border-[#B7A6FB]/20 text-[#B7A6FB] flex items-center justify-center hover:bg-[#B7A6FB]/20 transition-colors">
<Icon name="notifications" className="text-lg" />
</button>
<div className="size-9 rounded-full bg-gradient-to-tr from-[#B7A6FB] to-purple-500 flex items-center justify-center font-bold text-[#020105] text-sm">
JD
</div>
</div>
</header>
<div className="flex-1 overflow-y-auto">
<div className="max-w-[1100px] mx-auto p-6 grid grid-cols-1 lg:grid-cols-12 gap-8">
{/* Settings sidebar */}
<aside className="lg:col-span-3 flex flex-col gap-2">
<nav className="flex flex-col gap-1">
{[
{ icon: "person_outline", label: "User Preferences", active: true },
{ icon: "smart_toy", label: "Agent Clusters", active: false },
{ icon: "account_balance_wallet", label: "Billing & Credits", active: false },
{ icon: "shield", label: "Security", active: false },
].map(({ icon, label, active }) => (
<button
key={label}
className={`flex items-center gap-3 px-4 py-3 rounded-lg text-sm transition-all text-left ${
active
? "bg-[#B7A6FB]/10 text-[#B7A6FB] font-medium"
: "text-slate-400 hover:bg-[#B7A6FB]/5 hover:text-[#B7A6FB]"
}`}
>
<Icon name={icon} className="text-lg" />
{label}
</button>
))}
</nav>
<div className="mt-6 p-4 rounded-xl glass-card">
<p className="text-[10px] uppercase tracking-widest text-[#B7A6FB]/50 font-bold mb-2">
Plan Status
</p>
<p className="text-sm font-medium text-white">Pro Developer</p>
<div className="w-full bg-white/10 h-1.5 rounded-full mt-3 overflow-hidden">
<div className="bg-[#B7A6FB] h-full w-[75%] shadow-[0_0_8px_#B7A6FB]" />
</div>
<p className="text-[11px] text-slate-500 mt-2">75% of monthly tokens used</p>
</div>
</aside>
{/* Main settings content */}
<div className="lg:col-span-9 flex flex-col gap-8">
{/* Agent Personality */}
<section className="flex flex-col gap-5">
<div className="border-b border-white/5 pb-3">
<h3 className="text-xl font-bold text-[#B7A6FB]">Agent Personality</h3>
<p className="text-slate-400 text-sm mt-1">
Define the behavioral tone for your primary AI interactions.
</p>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
{PERSONALITIES.map((p) => {
const isActive = personality === p.key;
return (
<button
key={p.key}
onClick={() => setPersonality(p.key)}
className={`rounded-xl p-5 text-left flex flex-col gap-3 transition-all relative overflow-hidden ${
isActive
? "border-2 border-[#B7A6FB] bg-[#B7A6FB]/10 shadow-[0_0_20px_rgba(183,166,251,0.15)]"
: "glass-card hover:border-[#B7A6FB]/30"
}`}
>
{isActive && (
<div className="absolute top-2 right-2 text-[#B7A6FB]">
<Icon name="check_circle" className="text-sm" />
</div>
)}
<div className={`size-11 rounded-lg flex items-center justify-center ${p.bg}`}>
<Icon name={p.icon} className={`${p.color} text-xl`} />
</div>
<div>
<h4 className="font-bold text-white text-sm">{p.label}</h4>
<p className="text-[11px] text-slate-400 mt-1 leading-relaxed">{p.desc}</p>
</div>
</button>
);
})}
</div>
</section>
{/* Voice Synthesis */}
<section className="flex flex-col gap-5">
<div className="border-b border-white/5 pb-3 flex justify-between items-end">
<div>
<h3 className="text-xl font-bold text-[#B7A6FB]">Voice Synthesis</h3>
<p className="text-slate-400 text-sm mt-1">
Configured via ElevenLabs integration for realistic speech.
</p>
</div>
<span className="text-[10px] font-bold uppercase tracking-widest px-2 py-1 bg-[#B7A6FB]/10 text-[#B7A6FB] rounded border border-[#B7A6FB]/20">
API Connected
</span>
</div>
<div className="glass-card rounded-xl p-5 flex flex-col md:flex-row gap-5 items-center">
<div className="flex-1 w-full">
<label className="block text-[10px] font-bold uppercase tracking-tighter text-slate-500 mb-2">
Voice Model Selection
</label>
<div className="relative">
<select
value={voiceModel}
onChange={(e) => setVoiceModel(e.target.value)}
className="w-full bg-black/40 border border-white/10 rounded-lg px-4 py-3 text-slate-200 focus:ring-2 focus:ring-[#B7A6FB]/30 focus:border-[#B7A6FB]/40 outline-none appearance-none cursor-pointer text-sm transition-all"
>
{VOICE_MODELS.map((m) => (
<option key={m}>{m}</option>
))}
</select>
<div className="absolute inset-y-0 right-3 flex items-center pointer-events-none text-slate-500">
<Icon name="expand_more" className="text-lg" />
</div>
</div>
</div>
<div className="flex items-center gap-4 w-full md:w-auto">
<button className="flex-1 md:flex-none flex items-center justify-center gap-2 px-6 py-3 bg-[#B7A6FB] text-[#020105] font-bold rounded-lg hover:brightness-110 transition-all text-sm">
<Icon name="play_circle" className="text-xl" />
Preview
</button>
{/* Waveform visualizer */}
<div className="h-12 w-32 glass-card rounded-lg flex items-center justify-center px-3">
<div className="flex items-center gap-1">
{[3, 6, 4, 8, 5, 7, 3].map((h, i) => (
<div
key={i}
className={`w-1 rounded-full ${i % 2 === 0 ? "bg-[#B7A6FB]/40 animate-pulse" : "bg-[#B7A6FB]"}`}
style={{ height: `${h * 3}px` }}
/>
))}
</div>
</div>
</div>
</div>
</section>
{/* Payments + Security */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{/* Default UPI */}
<section className="flex flex-col gap-4">
<div className="border-b border-white/5 pb-3">
<h3 className="text-lg font-bold text-[#B7A6FB]">Default Payments</h3>
<p className="text-slate-400 text-sm mt-1">Linked UPI ID for automated settlement.</p>
</div>
<div className="glass-card rounded-xl p-4 flex flex-col gap-3">
<div className="flex items-center gap-3 p-3 bg-black/40 rounded-lg border border-white/10">
<div className="text-[#B7A6FB] bg-[#B7A6FB]/10 p-2 rounded">
<Icon name="account_balance" className="text-lg" />
</div>
<div className="flex-1 min-w-0">
<p className="text-[9px] text-slate-500 font-bold uppercase">Linked UPI</p>
<p className="text-sm font-medium text-slate-200 font-mono truncate">
negot8-hq@okaxis
</p>
</div>
<button className="text-slate-500 hover:text-[#B7A6FB] transition-colors">
<Icon name="edit" className="text-xl" />
</button>
</div>
<button className="w-full py-2 border border-dashed border-[#B7A6FB]/20 rounded-lg text-xs font-bold text-[#B7A6FB]/60 hover:bg-[#B7A6FB]/5 hover:border-[#B7A6FB]/40 hover:text-[#B7A6FB] transition-all tracking-widest">
+ ADD SECONDARY METHOD
</button>
</div>
</section>
{/* Security / API Keys */}
<section className="flex flex-col gap-4">
<div className="border-b border-white/5 pb-3 flex justify-between items-center">
<div>
<h3 className="text-lg font-bold text-[#B7A6FB]">Security</h3>
<p className="text-slate-400 text-sm mt-1">Manage environment access.</p>
</div>
<button className="text-[#B7A6FB] text-xs font-bold hover:underline transition-all">
Revoke All
</button>
</div>
<div className="glass-card rounded-xl p-4 flex flex-col gap-4">
{/* Production API Key */}
<div>
<label className="text-[9px] font-bold text-slate-500 uppercase tracking-tighter block mb-1.5">
Production API Key
</label>
<div className="flex items-center gap-2 bg-black/40 border border-white/10 rounded-lg px-3 py-2">
<input
type={showApiKey ? "text" : "password"}
readOnly
value="sk_mesh_live_483299283749"
className="bg-transparent border-none focus:ring-0 text-sm text-slate-300 flex-1 font-mono outline-none min-w-0"
/>
<button
onClick={() => setShowApiKey((v) => !v)}
className="text-slate-500 hover:text-[#B7A6FB] transition-colors shrink-0"
>
<Icon name={showApiKey ? "visibility_off" : "visibility"} className="text-lg" />
</button>
<button className="text-slate-500 hover:text-[#B7A6FB] transition-colors shrink-0">
<Icon name="content_copy" className="text-lg" />
</button>
</div>
</div>
{/* Webhook Secret */}
<div>
<label className="text-[9px] font-bold text-slate-500 uppercase tracking-tighter block mb-1.5">
Webhook Secret
</label>
<div className="flex items-center gap-2 bg-black/40 border border-white/10 rounded-lg px-3 py-2">
<input
type={showWebhook ? "text" : "password"}
readOnly
value="wh_mesh_123456"
className="bg-transparent border-none focus:ring-0 text-sm text-slate-300 flex-1 font-mono outline-none min-w-0"
/>
<button
onClick={() => setShowWebhook((v) => !v)}
className="text-slate-500 hover:text-[#B7A6FB] transition-colors shrink-0"
>
<Icon name={showWebhook ? "visibility_off" : "visibility"} className="text-lg" />
</button>
<button className="text-slate-500 hover:text-[#B7A6FB] transition-colors shrink-0">
<Icon name="content_copy" className="text-lg" />
</button>
</div>
</div>
</div>
</section>
</div>
{/* Footer actions */}
<div className="flex items-center justify-end gap-4 pt-4 border-t border-white/5">
<button className="px-6 py-2.5 rounded-lg font-bold text-slate-400 hover:text-slate-200 transition-all text-sm">
Discard Changes
</button>
<button
onClick={handleSave}
className="px-8 py-2.5 rounded-lg bg-[#B7A6FB] text-[#020105] font-bold shadow-[0_0_20px_rgba(183,166,251,0.2)] hover:scale-[1.02] transition-all text-sm"
>
Save Preferences
</button>
</div>
</div>
</div>
{/* Footer */}
<footer className="border-t border-white/5 py-6 px-6 mt-4">
<div className="max-w-[1100px] mx-auto flex flex-col md:flex-row justify-between items-center gap-4">
<div className="flex items-center gap-2 text-slate-600">
<Icon name="verified_user" className="text-lg" />
<span className="text-xs">End-to-end encryption active for all preference data.</span>
</div>
<div className="flex gap-6 text-xs text-slate-500">
<button className="hover:text-[#B7A6FB] transition-colors">Privacy Policy</button>
<button className="hover:text-[#B7A6FB] transition-colors">Terms of Mesh</button>
<span className="text-emerald-400">Status: Operational</span>
</div>
</div>
</footer>
</div>
</main>
{/* Save toast */}
{savedToast && (
<div className="fixed bottom-6 right-6 z-50 flex items-center gap-2 px-4 py-3 bg-[#B7A6FB] text-[#020105] rounded-xl font-bold text-sm shadow-[0_0_30px_rgba(183,166,251,0.4)] animate-pulse">
<Icon name="check_circle" className="text-lg" />
Preferences saved
</div>
)}
</div>
);
}