feat(ui): Add dropdown for Add User/Origin button

- Single dropdown button shows both options
- Selecting an option switches to that tab and opens modal
- Cleaner UX than separate buttons per tab

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Kelly
2025-12-13 23:06:42 -07:00
parent 4cb4e1c502
commit 4eaf7e50d7

View File

@@ -2,7 +2,7 @@ import { useState, useEffect } from 'react';
import { Layout } from '../components/Layout'; import { Layout } from '../components/Layout';
import { api } from '../lib/api'; import { api } from '../lib/api';
import { useAuthStore } from '../store/authStore'; import { useAuthStore } from '../store/authStore';
import { Users as UsersIcon, Plus, Pencil, Trash2, X, Check, AlertCircle, Globe, Shield, Power, PowerOff } from 'lucide-react'; import { Users as UsersIcon, Plus, Pencil, Trash2, X, Check, AlertCircle, Globe, Shield, Power, PowerOff, ChevronDown } from 'lucide-react';
interface User { interface User {
id: number; id: number;
@@ -56,6 +56,9 @@ export function Users() {
const [originsLoading, setOriginsLoading] = useState(true); const [originsLoading, setOriginsLoading] = useState(true);
const [originsError, setOriginsError] = useState<string | null>(null); const [originsError, setOriginsError] = useState<string | null>(null);
const [showOriginModal, setShowOriginModal] = useState(false); const [showOriginModal, setShowOriginModal] = useState(false);
// Add dropdown state
const [showAddDropdown, setShowAddDropdown] = useState(false);
const [editingOrigin, setEditingOrigin] = useState<TrustedOrigin | null>(null); const [editingOrigin, setEditingOrigin] = useState<TrustedOrigin | null>(null);
const [originFormData, setOriginFormData] = useState<OriginFormData>({ name: '', origin_type: 'domain', origin_value: '', description: '' }); const [originFormData, setOriginFormData] = useState<OriginFormData>({ name: '', origin_type: 'domain', origin_value: '', description: '' });
const [originFormError, setOriginFormError] = useState<string | null>(null); const [originFormError, setOriginFormError] = useState<string | null>(null);
@@ -344,24 +347,46 @@ export function Users() {
<p className="text-sm text-gray-500">Manage users and trusted origins</p> <p className="text-sm text-gray-500">Manage users and trusted origins</p>
</div> </div>
</div> </div>
{activeTab === 'users' ? ( <div className="relative">
<button <button
onClick={() => { setShowCreateModal(true); setFormError(null); }} onClick={() => setShowAddDropdown(!showAddDropdown)}
onBlur={() => setTimeout(() => setShowAddDropdown(false), 150)}
className="flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors" className="flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
> >
<Plus className="w-4 h-4" /> <Plus className="w-4 h-4" />
Add
<ChevronDown className="w-4 h-4" />
</button>
{showAddDropdown && (
<div className="absolute right-0 mt-2 w-48 bg-white rounded-lg shadow-lg border border-gray-200 py-1 z-50">
<button
onClick={() => {
setActiveTab('users');
setShowCreateModal(true);
setFormError(null);
setShowAddDropdown(false);
}}
className="w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-100 flex items-center gap-2"
>
<UsersIcon className="w-4 h-4" />
Add User Add User
</button> </button>
) : (
<button <button
onClick={() => { setShowOriginModal(true); setOriginFormError(null); }} onClick={() => {
className="flex items-center gap-2 px-4 py-2 bg-emerald-600 text-white rounded-lg hover:bg-emerald-700 transition-colors" setActiveTab('origins');
setShowOriginModal(true);
setOriginFormError(null);
setShowAddDropdown(false);
}}
className="w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-100 flex items-center gap-2"
> >
<Plus className="w-4 h-4" /> <Globe className="w-4 h-4" />
Add Origin Add Origin
</button> </button>
</div>
)} )}
</div> </div>
</div>
{/* Tabs */} {/* Tabs */}
<div className="border-b border-gray-200"> <div className="border-b border-gray-200">