82 lines
7.1 KiB
TypeScript
82 lines
7.1 KiB
TypeScript
import { useState } from 'react'
|
|
import { cn } from '../lib/utils'
|
|
import { Building2, Bell, Shield, Key, Globe, Save, Loader2, Plus, Copy, Eye, EyeOff, Code2, Trash2 } from 'lucide-react'
|
|
|
|
const tabs = [
|
|
{ id: 'general', label: 'General', icon: Building2 },
|
|
{ id: 'notifications', label: 'Notifications', icon: Bell },
|
|
{ id: 'security', label: 'Security', icon: Shield },
|
|
{ id: 'api', label: 'API Keys', icon: Key },
|
|
{ id: 'webhooks', label: 'Webhooks', icon: Globe },
|
|
]
|
|
|
|
export default function Settings() {
|
|
const [activeTab, setActiveTab] = useState('general')
|
|
const [saving, setSaving] = useState(false)
|
|
const [showToken, setShowToken] = useState(false)
|
|
const handleSave = async () => { setSaving(true); await new Promise(r => setTimeout(r, 800)); setSaving(false) }
|
|
|
|
return (
|
|
<div className="p-6 animate-fade-in">
|
|
<div className="page-header"><div><h1 className="page-title">Settings</h1><p className="page-subtitle">Workspace configuration</p></div></div>
|
|
<div className="flex gap-6">
|
|
<div className="w-48 flex-shrink-0 space-y-0.5">
|
|
{tabs.map(tab => { const Icon = tab.icon; return (
|
|
<button key={tab.id} onClick={() => setActiveTab(tab.id)}
|
|
className={cn("w-full sidebar-item", activeTab === tab.id ? "sidebar-item-active" : "sidebar-item-inactive")}>
|
|
<Icon size={16} /><span>{tab.label}</span>
|
|
</button>
|
|
)})}
|
|
</div>
|
|
<div className="flex-1 max-w-2xl">
|
|
{activeTab === 'general' && (
|
|
<div className="card animate-fade-in"><div className="card-header"><h3 className="text-sm font-semibold">Workspace Details</h3></div>
|
|
<div className="card-body space-y-5">
|
|
<div><label className="block text-xs font-medium text-gray-400 mb-1.5 uppercase tracking-wide">Workspace Name</label><input defaultValue="My Workspace" className="input" /></div>
|
|
<div><label className="block text-xs font-medium text-gray-400 mb-1.5 uppercase tracking-wide">Default Assignee</label><input className="input" placeholder="user@company.com" /></div>
|
|
<div><label className="block text-xs font-medium text-gray-400 mb-1.5 uppercase tracking-wide">Timezone</label>
|
|
<select className="input"><option>America/Sao_Paulo</option><option>America/New_York</option><option>UTC</option></select></div>
|
|
<div className="pt-3 border-t border-gray-800"><button onClick={handleSave} disabled={saving} className="btn btn-primary">{saving ? <Loader2 size={14} className="animate-spin" /> : <Save size={14} />} Save</button></div>
|
|
</div></div>
|
|
)}
|
|
{activeTab === 'notifications' && (
|
|
<div className="card animate-fade-in"><div className="card-header"><h3 className="text-sm font-semibold">Notification Preferences</h3></div>
|
|
<div className="card-body space-y-4">
|
|
{[{ l: 'New ticket', d: 'When a ticket is created' },{ l: 'Status change', d: 'When ticket status updates' },{ l: 'Comments', d: 'When someone comments' },{ l: 'Assignment', d: 'When assigned to you' }].map(item => (
|
|
<div key={item.l} className="flex items-center justify-between py-2"><div><p className="text-sm font-medium text-gray-200">{item.l}</p><p className="text-xs text-gray-500">{item.d}</p></div>
|
|
<label className="relative inline-flex items-center cursor-pointer"><input type="checkbox" defaultChecked className="sr-only peer" /><div className="w-9 h-5 bg-gray-700 rounded-full peer peer-checked:bg-blue-600 after:content-[''] after:absolute after:top-0.5 after:left-0.5 after:bg-white after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:after:translate-x-4" /></label></div>
|
|
))}</div></div>
|
|
)}
|
|
{activeTab === 'security' && (
|
|
<div className="card animate-fade-in"><div className="card-header"><h3 className="text-sm font-semibold">Security</h3></div>
|
|
<div className="card-body space-y-5">
|
|
<div className="flex items-center justify-between py-2"><div><p className="text-sm font-medium text-gray-200">Two-Factor Authentication</p><p className="text-xs text-gray-500">Require 2FA for all members</p></div>
|
|
<label className="relative inline-flex items-center cursor-pointer"><input type="checkbox" className="sr-only peer" /><div className="w-9 h-5 bg-gray-700 rounded-full peer peer-checked:bg-blue-600 after:content-[''] after:absolute after:top-0.5 after:left-0.5 after:bg-white after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:after:translate-x-4" /></label></div>
|
|
<div className="flex items-center justify-between py-2"><div><p className="text-sm font-medium text-gray-200">SSO / SAML</p><p className="text-xs text-gray-500">Enterprise single sign-on</p></div><span className="badge badge-gray">Enterprise</span></div>
|
|
</div></div>
|
|
)}
|
|
{activeTab === 'api' && (
|
|
<div className="card animate-fade-in"><div className="card-header"><h3 className="text-sm font-semibold">API Keys</h3><button className="btn btn-primary btn-sm"><Plus size={14} /> Create</button></div>
|
|
<div className="card-body">
|
|
<div className="flex items-center gap-3 p-3 bg-gray-900/50 rounded-lg border border-gray-800/50">
|
|
<Key size={16} className="text-gray-500" /><div className="flex-1 min-w-0"><p className="text-sm font-medium">Production Key</p>
|
|
<div className="flex items-center gap-2 mt-1"><code className="text-xs text-gray-500 font-mono">{showToken ? 'th_live_sk_a1b2c3...' : 'th_live_sk_••••••...'}</code>
|
|
<button onClick={() => setShowToken(!showToken)} className="text-gray-500 hover:text-gray-300">{showToken ? <EyeOff size={12} /> : <Eye size={12} />}</button>
|
|
<button className="text-gray-500 hover:text-gray-300"><Copy size={12} /></button></div></div>
|
|
<span className="badge badge-green text-[10px]">Active</span><button className="btn btn-danger btn-sm btn-icon"><Trash2 size={12} /></button></div>
|
|
<div className="mt-4 p-4 bg-gray-950 rounded-lg border border-gray-800"><h4 className="text-xs font-semibold text-gray-400 mb-2 flex items-center gap-1.5"><Code2 size={12} /> Quick Start</h4>
|
|
<pre className="text-xs text-gray-400 font-mono overflow-x-auto">{`curl -X POST https://tickethub.startdata.com.br/api/tickets \\
|
|
-H "Authorization: Bearer YOUR_KEY" \\
|
|
-d '{"title": "New bug"}'`}</pre></div>
|
|
</div></div>
|
|
)}
|
|
{activeTab === 'webhooks' && (
|
|
<div className="card animate-fade-in"><div className="card-header"><h3 className="text-sm font-semibold">Webhooks</h3><button className="btn btn-primary btn-sm"><Plus size={14} /> Add</button></div>
|
|
<div className="card-body"><div className="text-center py-8"><Globe size={24} className="text-gray-600 mx-auto mb-2" /><p className="text-sm text-gray-500">No webhooks configured</p></div></div></div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|