import { useState, useEffect } from 'react'; import { useAuth } from '../components/AuthContext'; import toast from 'react-hot-toast'; import Profile from './Profile'; export const AlertSettingsPage = () => { const { token, user, reloadUser } = useAuth(); const [activeTab, setActiveTab] = useState(() => { return localStorage.getItem('settingsActiveTab') || 'profile'; }); // profile, notifications, apiKeys, team, billing, scheduler useEffect(() => { localStorage.setItem('settingsActiveTab', activeTab); }, [activeTab]); // Notification states (connected to backend) const [emailNotifications, setEmailNotifications] = useState(true); const [webhookUrl, setWebhookUrl] = useState(''); const [severityThreshold, setSeverityThreshold] = useState('Medium'); const [reportLogoUrl, setReportLogoUrl] = useState(''); const [teamUsers, setTeamUsers] = useState([]); const [loadingTeam, setLoadingTeam] = useState(false); const [newUserFirstName, setNewUserFirstName] = useState(''); const [newUserLastName, setNewUserLastName] = useState(''); const [newUserEmail, setNewUserEmail] = useState(''); const [newUserPassword, setNewUserPassword] = useState(''); const [newUserRole, setNewUserRole] = useState('soc_analyst'); const [invitingUser, setInvitingUser] = useState(false); const [showAddMember, setShowAddMember] = useState(false); const [showNewUserPassword, setShowNewUserPassword] = useState(false); const [editingUser, setEditingUser] = useState(null); const [updatingUser, setUpdatingUser] = useState(false); const [userToDelete, setUserToDelete] = useState(null); const [deletingUser, setDeletingUser] = useState(false); const [passwordData, setPasswordData] = useState({ currentPassword: '', newPassword: '', confirmPassword: '' }); const [passwordStatus, setPasswordStatus] = useState({ loading: false, error: null, success: false }); const [showPassword, setShowPassword] = useState({ current: false, new: false, confirm: false }); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [message, setMessage] = useState(''); const [error, setError] = useState(''); const [billingHistory, setBillingHistory] = useState([]); const [loadingBilling, setLoadingBilling] = useState(false); const [scanQuotas, setScanQuotas] = useState([]); const [loadingQuotas, setLoadingQuotas] = useState(false); // Demo Bookings State const [demoBookings, setDemoBookings] = useState([]); const [loadingDemoBookings, setLoadingDemoBookings] = useState(false); const [rescheduleModal, setRescheduleModal] = useState({ isOpen: false, bookingId: null, email: '', meetingDate: '', meetingTime: '', status: 'rescheduled' }); const handleUpdateDemoBookingStatus = async (bookingId, status) => { try { const res = await fetch(`/api/demo/bookings/${bookingId}`, { method: 'PUT', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ status }) }); if (res.ok) { toast.success(`Booking status updated to ${status}`); fetchDemoBookings(); } else { toast.error("Failed to update status"); } } catch (err) { toast.error("Error updating status"); } }; const handleOpenReschedule = (booking) => { setRescheduleModal({ isOpen: true, bookingId: booking.id, email: booking.email, meetingDate: booking.meeting_date || '', meetingTime: booking.meeting_time || '', status: 'rescheduled' }); }; const handleSaveReschedule = async (e) => { e.preventDefault(); try { const res = await fetch(`/api/demo/bookings/${rescheduleModal.bookingId}`, { method: 'PUT', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ meeting_date: rescheduleModal.meetingDate, meeting_time: rescheduleModal.meetingTime, status: rescheduleModal.status }) }); if (res.ok) { toast.success("Demo booking rescheduled successfully!"); setRescheduleModal({ isOpen: false, bookingId: null, email: '', meetingDate: '', meetingTime: '', status: 'rescheduled' }); fetchDemoBookings(); } else { toast.error("Failed to reschedule demo booking"); } } catch (err) { toast.error("Error rescheduling booking"); } }; const handleDeleteDemoBooking = async (bookingId) => { if (!window.confirm("Are you sure you want to delete this booking lead?")) return; try { const res = await fetch(`/api/demo/bookings/${bookingId}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${token}` } }); if (res.ok) { toast.success("Booking lead deleted successfully"); fetchDemoBookings(); } else { toast.error("Failed to delete booking lead"); } } catch (err) { toast.error("Error deleting lead"); } }; // Scheduled Scans const [scheduledScans, setScheduledScans] = useState([]); const [loadingScans, setLoadingScans] = useState(false); const [newSchedule, setNewSchedule] = useState({ target_url: '', scan_type: 'Full', schedule_time: '20:00' }); // Notification History const [notificationHistory, setNotificationHistory] = useState([]); const [loadingHistory, setLoadingHistory] = useState(false); const [sortTeamCol, setSortTeamCol] = useState('Name'); const [sortTeamDir, setSortTeamDir] = useState('asc'); const [sortBillCol, setSortBillCol] = useState('Date'); const [sortBillDir, setSortBillDir] = useState('desc'); const handleTeamSort = (column) => { if (column === 'Actions') return; if (sortTeamCol === column) { setSortTeamDir(sortTeamDir === 'asc' ? 'desc' : 'asc'); } else { setSortTeamCol(column); setSortTeamDir('asc'); } }; const getSortedTeam = () => { return [...teamUsers].sort((a, b) => { let aVal, bVal; switch (sortTeamCol) { case 'Name': aVal = `${a.first_name || ''} ${a.last_name || ''}`.trim(); bVal = `${b.first_name || ''} ${b.last_name || ''}`.trim(); break; case 'Email': aVal = a.email || ''; bVal = b.email || ''; break; case 'Assigned Role': aVal = a.role || ''; bVal = b.role || ''; break; case 'Status': aVal = a.status || ''; bVal = b.status || ''; break; default: return 0; } if (aVal < bVal) return sortTeamDir === 'asc' ? -1 : 1; if (aVal > bVal) return sortTeamDir === 'asc' ? 1 : -1; return 0; }); }; const handleBillSort = (column) => { if (sortBillCol === column) { setSortBillDir(sortBillDir === 'asc' ? 'desc' : 'asc'); } else { setSortBillCol(column); setSortBillDir('desc'); } }; const getSortedBilling = () => { return [...billingHistory].sort((a, b) => { let aVal, bVal; switch (sortBillCol) { case 'Date': aVal = new Date(a.created_at).getTime(); bVal = new Date(b.created_at).getTime(); break; case 'Plan': aVal = a.tier_id || ''; bVal = b.tier_id || ''; break; case 'Amount': aVal = a.amount || 0; bVal = b.amount || 0; break; case 'Status': aVal = a.status || ''; bVal = b.status || ''; break; default: return 0; } if (aVal < bVal) return sortBillDir === 'asc' ? -1 : 1; if (aVal > bVal) return sortBillDir === 'asc' ? 1 : -1; return 0; }); }; useEffect(() => { fetchSettings(); }, [token]); const fetchSettings = async () => { try { const res = await fetch('/api/vulnerabilities/settings', { headers: { 'Authorization': `Bearer ${token}` } }); if (res.ok) { const data = await res.json(); setEmailNotifications(data.settings.email_notifications); setWebhookUrl(data.settings.webhook_url || ''); setSeverityThreshold(data.settings.severity_threshold); } } catch (err) { console.error("Error loading alert settings", err); } finally { setLoading(false); } }; const fetchNotificationHistory = async () => { setLoadingHistory(true); try { const res = await fetch('/api/auth/notifications', { headers: { 'Authorization': `Bearer ${token}` } }); if (res.ok) { const data = await res.json(); setNotificationHistory(data.notifications || []); } } catch (err) { console.error("Error loading notification history", err); } finally { setLoadingHistory(false); } }; const fetchTeamUsers = async () => { setLoadingTeam(true); try { const endpoint = user?.org_id ? `/api/auth/organizations/${user.org_id}/users` : '/api/auth/users'; const res = await fetch(endpoint, { headers: { 'Authorization': `Bearer ${token}` } }); if (res.ok) { const data = await res.json(); const filteredUsers = (data.users || []).filter(u => u.role !== 'super_admin'); setTeamUsers(filteredUsers); } } catch (err) { console.error('Failed to fetch org users', err); } finally { setLoadingTeam(false); } }; useEffect(() => { if (activeTab === 'team' && (user?.role === 'org_admin' || user?.role === 'super_admin')) { fetchTeamUsers(); } }, [activeTab, user]); const handleInviteUser = async (e) => { e.preventDefault(); if (!newUserEmail) return; setInvitingUser(true); try { const res = await fetch('/api/auth/users/invite', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ email: newUserEmail, role: newUserRole, first_name: newUserFirstName, last_name: newUserLastName, password: newUserPassword }) }); const data = await res.json(); if (res.ok) { toast.success(`User added successfully!`); setNewUserFirstName(''); setNewUserLastName(''); setNewUserEmail(''); setNewUserPassword(''); setShowAddMember(false); setShowNewUserPassword(false); fetchTeamUsers(); } else { toast.error(data.message || 'Failed to invite user'); } } catch (err) { toast.error("Error inviting user"); } finally { setInvitingUser(false); } }; const handleUpdateUser = async (e) => { e.preventDefault(); if (!editingUser) return; setUpdatingUser(true); try { const res = await fetch(`/api/auth/users/${editingUser.id}`, { method: 'PUT', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ first_name: editingUser.first_name, last_name: editingUser.last_name, email: editingUser.email, password: editingUser.new_password, role: editingUser.role }) }); if (res.ok) { toast.success(`User updated successfully!`); setEditingUser(null); fetchTeamUsers(); } else { const data = await res.json(); toast.error(data.message || 'Failed to update user'); } } catch (err) { toast.error("Error updating user"); } finally { setUpdatingUser(false); } }; const executeDeleteUser = async () => { if (!userToDelete) return; setDeletingUser(true); try { const res = await fetch(`/api/auth/users/${userToDelete.id}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${token}` } }); if (res.ok) { toast.success("User removed successfully!"); setUserToDelete(null); fetchTeamUsers(); } else { const data = await res.json(); toast.error(data.message || "Failed to remove user"); } } catch (err) { toast.error("Error removing user"); } finally { setDeletingUser(false); } }; const handlePasswordChange = async (e) => { e.preventDefault(); setPasswordStatus({ loading: true, error: null, success: false }); if (passwordData.newPassword !== passwordData.confirmPassword) { setPasswordStatus({ loading: false, error: "New passwords do not match", success: false }); return; } if (passwordData.newPassword.length < 6) { setPasswordStatus({ loading: false, error: "New password must be at least 6 characters", success: false }); return; } try { const res = await fetch('/api/auth/password', { method: 'PUT', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify({ currentPassword: passwordData.currentPassword, newPassword: passwordData.newPassword }) }); let data = {}; try { data = await res.json(); } catch (e) { } if (res.ok) { setPasswordStatus({ loading: false, error: null, success: true }); setPasswordData({ currentPassword: '', newPassword: '', confirmPassword: '' }); toast.success("Password updated successfully!"); setTimeout(() => setPasswordStatus(prev => ({ ...prev, success: false })), 3000); } else { const errorMsg = data.message || "Failed to update password"; setPasswordStatus({ loading: false, error: errorMsg, success: false }); toast.error(errorMsg); } } catch (err) { setPasswordStatus({ loading: false, error: "Network error occurred", success: false }); toast.error("Network error occurred"); } }; // Auto-refresh user data (e.g., subscription upgrades) when Billing tab is active useEffect(() => { let intervalId; if (activeTab === 'billing' && reloadUser) { intervalId = setInterval(() => { reloadUser(); fetchQuotas(true); fetchBillingHistory(true); }, 15000); // Poll every 15 seconds silently } return () => { if (intervalId) clearInterval(intervalId); }; }, [activeTab, reloadUser]); useEffect(() => { if (activeTab === 'billing') { fetchBillingHistory(); fetchQuotas(); } if (activeTab === 'notifications') { fetchNotificationHistory(); } }, [activeTab, user?.org_id, user?.id]); const fetchQuotas = async (isSilent = false) => { if (!isSilent && scanQuotas.length === 0) setLoadingQuotas(true); try { // If user has organization_id, fetch from it. Otherwise we might fetch from a general endpoint if it existed, or we just try to fetch the first organization. // Usually users belong to one organization. Let's try to get their organization ID first, or fetch from /api/auth/organizations let orgId = user?.org_id; if (!orgId) { const orgRes = await fetch('/api/auth/organizations', { headers: { 'Authorization': `Bearer ${token}` } }); if (orgRes.ok) { const orgsData = await orgRes.json(); if (orgsData.organizations && orgsData.organizations.length > 0) { orgId = orgsData.organizations[0].id; } } } if (orgId) { const res = await fetch(`/api/auth/organizations/${orgId}/quotas`, { headers: { 'Authorization': `Bearer ${token}` } }); if (res.ok) { const data = await res.json(); setScanQuotas(data.quotas || []); } } } catch (err) { console.error("Error loading quotas", err); } finally { setLoadingQuotas(false); } }; const fetchBillingHistory = async (isSilent = false) => { if (!isSilent && billingHistory.length === 0) setLoadingBilling(true); try { const res = await fetch('/api/billing/history', { headers: { 'Authorization': `Bearer ${token}` } }); if (res.ok) { const data = await res.json(); setBillingHistory(data.history || []); } } catch (err) { console.error("Error loading billing history", err); } finally { setLoadingBilling(false); } }; useEffect(() => { if (activeTab === 'scheduler') { fetchScheduledScans(); } }, [activeTab, token]); const fetchScheduledScans = async () => { setLoadingScans(true); try { const res = await fetch('/api/scans/schedule', { headers: { 'Authorization': `Bearer ${token}` } }); if (res.ok) { const data = await res.json(); setScheduledScans(data.schedules || []); } } catch (err) { console.error("Error loading scheduled scans", err); } finally { setLoadingScans(false); } }; const fetchDemoBookings = async () => { setLoadingDemoBookings(true); try { const res = await fetch('/api/demo/bookings', { headers: { 'Authorization': `Bearer ${token}` } }); if (res.ok) { const data = await res.json(); setDemoBookings(data || []); } } catch (err) { console.error("Error loading demo bookings", err); } finally { setLoadingDemoBookings(false); } }; useEffect(() => { if (activeTab === 'demoBookings') { fetchDemoBookings(); } }, [activeTab, token]); const handleCreateSchedule = async (e) => { e.preventDefault(); setMessage(''); setError(''); if (user?.subscription_tier === 'Free') { setError('Scheduled scans require a premium subscription.'); return; } try { const res = await fetch('/api/scans/schedule', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify({ ...newSchedule, frequency: 'daily' }) }); const data = await res.json(); if (res.ok) { setMessage('Scan scheduled successfully!'); setNewSchedule({ target_url: '', scan_type: 'Full', schedule_time: '20:00' }); fetchScheduledScans(); } else { setError(data.message || 'Failed to schedule scan.'); } } catch (err) { setError('Connection error.'); } }; const handleDeleteSchedule = async (id) => { try { const res = await fetch(`/api/scans/schedule/${id}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${token}` } }); if (res.ok) { setScheduledScans(prev => prev.filter(s => s.id !== id)); } } catch (err) { console.error('Failed to delete schedule', err); } }; const handleSave = async (e) => { e.preventDefault(); setSaving(true); setMessage(''); setError(''); try { const res = await fetch('/api/vulnerabilities/settings', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify({ email_notifications: emailNotifications, webhook_url: webhookUrl, severity_threshold: severityThreshold }) }); const data = await res.json(); if (res.ok) { setMessage('Alert preferences successfully updated!'); } else { setError(data.message || 'Failed to update alert configurations.'); } } catch (err) { setError('Could not establish connection to the security server API.'); console.error(err); } finally { setSaving(false); } }; const isSchedulerAllowed = ['super_admin', 'support_engineer', 'admin', 'org_admin', 'soc_analyst'].includes(user?.role); const isDemoBookingsAllowed = ['super_admin', 'support_engineer', 'admin', 'org_admin', 'soc_analyst'].includes(user?.role); const isNotificationsAllowed = ['super_admin', 'support_engineer', 'admin', 'org_admin'].includes(user?.role); const isApiKeysAllowed = ['super_admin', 'support_engineer', 'admin', 'org_admin'].includes(user?.role); const isTeamAllowed = ['super_admin', 'support_engineer', 'admin', 'org_admin'].includes(user?.role); const isBillingAllowed = ['super_admin', 'support_engineer', 'admin', 'org_admin'].includes(user?.role); const tabItems = [ { id: 'profile', label: 'My Profile', icon: 'person' } ]; if (isSchedulerAllowed) tabItems.push({ id: 'scheduler', label: 'Scheduler', icon: 'schedule' }); if (isDemoBookingsAllowed) tabItems.push({ id: 'demoBookings', label: 'Demo Bookings', icon: 'event_available' }); if (isNotificationsAllowed) tabItems.push({ id: 'notifications', label: 'Notifications', icon: 'notifications' }); if (isApiKeysAllowed) tabItems.push({ id: 'apiKeys', label: 'API Keys', icon: 'key' }); if (isTeamAllowed) tabItems.push({ id: 'team', label: 'Team', icon: 'group' }); if (isBillingAllowed) tabItems.push({ id: 'billing', label: 'Billing', icon: 'credit_card' }); useEffect(() => { const isAllowed = tabItems.some(t => t.id === activeTab); if (!isAllowed) { setActiveTab('profile'); } }, [user?.role, activeTab]); if (loading) { return (
sync Loading Settings...
); } // Pre-fill user profile info or fallback to Mercer placeholder const profileName = user ? user.email.split('@')[0] : 'Alex'; const profileLastName = user ? 'User' : 'Mercer'; const profileEmail = user ? user.email : 'alex.mercer@larxiuswss.io'; const profileRole = user?.role ? `Role: ${user.role}` : 'Lead Security Engineer'; return (
{/* Settings Header & Tabs */}

Settings

Manage your account preferences, security protocols, and team access.

{/* Scrollable Tabs row */}
{tabItems.map((tab) => { const isActive = activeTab === tab.id; return ( ); })}
{/* Tab Switch Contents */} {activeTab === 'scheduler' && isSchedulerAllowed && (

schedule Schedule Automated Scans

Set up daily automated scans for your targets. The scanner will run automatically at your specified time.

{message && (
check_circle
{message}
)} {error && (
error
{error}
)}
setNewSchedule({ ...newSchedule, target_url: e.target.value })} />
setNewSchedule({ ...newSchedule, schedule_time: e.target.value })} />

Active Schedules

{loadingScans ? (

Loading schedules...

) : scheduledScans.length === 0 ? (

No automated scans scheduled yet.

) : (
{scheduledScans.map(scan => (
{scan.target_url}
schedule {scan.schedule_time} (Daily) troubleshoot {scan.scan_type} Scan {scan.last_run_at && history Last run: {new Date(scan.last_run_at).toLocaleDateString()}}
))}
)}
)} {activeTab === 'demoBookings' && isDemoBookingsAllowed && (

event_available Discovery Call Bookings

{loadingDemoBookings ? (
) : demoBookings.length > 0 ? ( demoBookings.map((b) => { const statusStyle = b.status === 'completed' ? 'bg-emerald-100 text-emerald-700 border-emerald-300' : b.status === 'cancelled' ? 'bg-rose-100 text-rose-700 border-rose-300' : b.status === 'rescheduled' ? 'bg-indigo-100 text-indigo-700 border-indigo-300' : 'bg-amber-100 text-amber-700 border-amber-300'; const statusLabel = b.status === 'completed' ? 'Completed' : b.status === 'cancelled' ? 'Cancelled / Not Conducted' : b.status === 'rescheduled' ? 'Rescheduled' : 'Pending'; return (
{b.email} {statusLabel}
calendar_today {b.meeting_date} schedule {b.meeting_time} business {b.company_size}
Booked: {new Date(b.created_at).toLocaleDateString()}
{b.status !== 'completed' && ( )} {b.status !== 'cancelled' && ( )}
); }) ) : (
event_busy

No demo bookings found.

)}
)} {/* 2. Notifications Tab (History) */} {activeTab === 'notifications' && isNotificationsAllowed && (
{/* Notification History Panel */}

history Notification History

{loadingHistory ? (
) : notificationHistory.length > 0 ? ( notificationHistory.map((notif, idx) => (
{notif.icon}
{notif.title}
{notif.message}
{new Date(notif.timestamp).toLocaleString()}
)) ) : (
notifications_paused

No recent notifications.

)}
)} {/* 3. Billing Tab */} {activeTab === 'billing' && isBillingAllowed && (
{/* Subscription & Billing */}

credit_card Subscription & Billing

{/* Current Plan - Compact Horizontal Layout */}
workspace_premium

Current Plan

{user?.role === 'super_admin' ? 'Enterprise' : user?.subscription_tier || 'Free'}

{user?.role === 'super_admin' ? 'Active' : user?.subscription_status || 'Inactive'}
{user?.role !== 'super_admin' && ( Upgrade arrow_forward )}
{/* Scan Quotas - Compact Grid */}

pie_chart Scan Quotas

{loadingQuotas ? (
sync Loading...
) : scanQuotas.length > 0 ? (
{scanQuotas.filter(q => ['Quick', 'Advanced', 'Deep'].includes(q.scan_type)).map((q, idx) => { const icon = q.scan_type.toLowerCase().includes('quick') ? 'bolt' : q.scan_type.toLowerCase().includes('advanced') ? 'security' : q.scan_type.toLowerCase().includes('deep') ? 'radar' : 'pie_chart'; return (
{icon}
{q.scan_type} {q.allocated_count === -1 ? 'Unlimited' : Math.max(0, q.allocated_count - (q.used_count || 0))}
); })}
) : (
No scan quotas assigned.
)}
{/* Billing History */}

history Payment History

{loadingBilling ? (
sync Loading transactions...
) : billingHistory.length === 0 ? (
No past transactions found.
) : (
{['Date', 'Plan', 'Amount', 'Status'].map((h, i) => ( ))} {getSortedBilling().map((tx, idx) => ( ))}
handleBillSort(h)} className="p-sm font-label-sm text-on-surface-variant uppercase cursor-pointer hover:bg-surface-container-highest transition-colors group" >
{h} {sortBillCol === h && sortBillDir === 'desc' ? 'arrow_downward' : 'arrow_upward'}
{new Date(tx.created_at).toLocaleDateString()} {tx.tier_id} ${(tx.amount / 100).toFixed(2)} {tx.status}
)}
)} {/* Profile Tab */} {activeTab === 'profile' && ( )} {/* Team Tab */} {activeTab === 'team' && isTeamAllowed && (

group Active Team Members

{(user?.role === 'org_admin' || user?.role === 'super_admin') && ( )}
{loadingTeam ? (
Loading team members...
) : (
{['Name', 'Email', 'Assigned Role', 'Status', 'Actions'].map((h, i) => ( ))} {getSortedTeam().map((member) => ( ))}
handleTeamSort(h)} className={`px-6 py-4 font-semibold ${i === 4 ? 'text-right' : ''} ${h !== 'Actions' ? 'cursor-pointer hover:bg-surface-container-highest transition-colors group' : ''}`} >
{h} {h !== 'Actions' && ( {sortTeamCol === h && sortTeamDir === 'desc' ? 'arrow_downward' : 'arrow_upward'} )}
{member.first_name || member.last_name ? `${member.first_name || ''} ${member.last_name || ''}`.trim() : 'N/A'} {member.email} {member.role.replace('_', ' ')} {member.status}
)}
{/* Add New Member Modal Overlay */} {showAddMember && (user?.role === 'org_admin' || user?.role === 'super_admin') && (

person_add Add New Member

setNewUserFirstName(e.target.value)} className="w-full bg-surface border border-outline-variant text-on-surface font-body-md px-4 py-3 rounded-lg focus:border-primary focus:ring-2 focus:ring-primary/20 focus:outline-none transition-all" placeholder="John" />
setNewUserLastName(e.target.value)} className="w-full bg-surface border border-outline-variant text-on-surface font-body-md px-4 py-3 rounded-lg focus:border-primary focus:ring-2 focus:ring-primary/20 focus:outline-none transition-all" placeholder="Doe" />
setNewUserEmail(e.target.value)} className="w-full bg-surface border border-outline-variant text-on-surface font-body-md px-4 py-3 rounded-lg focus:border-primary focus:ring-2 focus:ring-primary/20 focus:outline-none transition-all" placeholder="user@example.com" />
setNewUserPassword(e.target.value)} className="w-full bg-surface border border-outline-variant text-on-surface font-body-md px-4 py-3 pr-12 rounded-lg focus:border-primary focus:ring-2 focus:ring-primary/20 focus:outline-none transition-all" placeholder="Leave blank for auto-generated" />
)} {/* Edit Member Modal Overlay */} {editingUser && (user?.role === 'org_admin' || user?.role === 'super_admin') && (

manage_accounts Edit Member

setEditingUser({ ...editingUser, first_name: e.target.value })} className="w-full bg-surface border border-outline-variant text-on-surface font-body-md px-4 py-3 rounded-lg focus:border-primary focus:ring-2 focus:ring-primary/20 focus:outline-none transition-all" />
setEditingUser({ ...editingUser, last_name: e.target.value })} className="w-full bg-surface border border-outline-variant text-on-surface font-body-md px-4 py-3 rounded-lg focus:border-primary focus:ring-2 focus:ring-primary/20 focus:outline-none transition-all" />
setEditingUser({ ...editingUser, email: e.target.value })} className="w-full bg-surface border border-outline-variant text-on-surface font-body-md px-4 py-3 rounded-lg focus:border-primary focus:ring-2 focus:ring-primary/20 focus:outline-none transition-all" />
setEditingUser({ ...editingUser, new_password: e.target.value })} className="w-full bg-surface border border-outline-variant text-on-surface font-body-md px-4 py-3 pr-12 rounded-lg focus:border-primary focus:ring-2 focus:ring-primary/20 focus:outline-none transition-all" placeholder="Leave blank to keep unchanged" />
)} {/* Delete Confirmation Modal */} {userToDelete && (
warning

Remove Team Member?

Are you sure you want to remove {userToDelete.email} from the organization? This action cannot be undone and they will lose all access immediately.

)}
)} {/* API Keys Tab (Placeholder) */} {activeTab === 'apiKeys' && isApiKeysAllowed && (
{/* Background decorative elements */}
{/* Subtle grid pattern overlay */}
vpn_key
Coming Soon

Developer API Access

We are actively building a robust, high-performance API for LarShield. Soon, you will be able to programmatically manage scans, retrieve security reports, and integrate seamlessly with your CI/CD pipelines.

)} {/* Reschedule Demo Call Modal */} {rescheduleModal.isOpen && (
setRescheduleModal({ ...rescheduleModal, isOpen: false })}>

edit_calendar Reschedule Demo Call

setRescheduleModal({ ...rescheduleModal, meetingDate: e.target.value })} className="w-full border border-slate-300 rounded-lg p-2.5 text-xs text-slate-900 dark:text-white dark:bg-slate-800 focus:outline-none focus:border-primary" />
setRescheduleModal({ ...rescheduleModal, meetingTime: e.target.value })} className="w-full border border-slate-300 rounded-lg p-2.5 text-xs text-slate-900 dark:text-white dark:bg-slate-800 focus:outline-none focus:border-primary" />
)}
); };