import { useState, useEffect } from "react"; import { useNavigate } from "react-router-dom"; import Layout from "@/components/Layout"; import { Button } from "@/components/ui/button"; import { useAuth } from "@/contexts/AuthContext"; import { aethexToast } from "@/lib/aethex-toast"; import { supabase } from "@/lib/supabase"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { Switch } from "@/components/ui/switch"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Separator } from "@/components/ui/separator"; import LoadingScreen from "@/components/LoadingScreen"; import { Settings, ArrowLeft, Building2, Bell, CreditCard, Users, Shield, Save, Upload, Trash2, Plus, Mail, Phone, MapPin, Globe, Key, AlertTriangle, } from "lucide-react"; const API_BASE = import.meta.env.VITE_API_BASE || ""; interface CompanyProfile { name: string; logo_url: string; website: string; industry: string; address: { street: string; city: string; state: string; zip: string; country: string; }; billing_email: string; phone: string; } interface TeamMember { id: string; email: string; name: string; role: "admin" | "member" | "viewer"; invited_at: string; accepted: boolean; } interface NotificationSettings { email_invoices: boolean; email_milestones: boolean; email_reports: boolean; email_team_updates: boolean; sms_urgent: boolean; } export default function ClientSettings() { const navigate = useNavigate(); const { user, loading: authLoading } = useAuth(); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [activeTab, setActiveTab] = useState("company"); const [company, setCompany] = useState({ name: "", logo_url: "", website: "", industry: "", address: { street: "", city: "", state: "", zip: "", country: "" }, billing_email: "", phone: "", }); const [teamMembers, setTeamMembers] = useState([]); const [newMemberEmail, setNewMemberEmail] = useState(""); const [notifications, setNotifications] = useState({ email_invoices: true, email_milestones: true, email_reports: true, email_team_updates: true, sms_urgent: false, }); useEffect(() => { if (!authLoading && user) { loadSettings(); } }, [user, authLoading]); const loadSettings = async () => { try { setLoading(true); const { data: { session } } = await supabase.auth.getSession(); const token = session?.access_token; if (!token) throw new Error("No auth token"); // Load company profile const companyRes = await fetch(`${API_BASE}/api/corp/company`, { headers: { Authorization: `Bearer ${token}` }, }); if (companyRes.ok) { const data = await companyRes.json(); if (data) setCompany(data); } // Load team members const teamRes = await fetch(`${API_BASE}/api/corp/team/members`, { headers: { Authorization: `Bearer ${token}` }, }); if (teamRes.ok) { const data = await teamRes.json(); setTeamMembers(Array.isArray(data) ? data : []); } // Load notification settings const notifRes = await fetch(`${API_BASE}/api/user/notifications`, { headers: { Authorization: `Bearer ${token}` }, }); if (notifRes.ok) { const data = await notifRes.json(); if (data) setNotifications(data); } } catch (error) { console.error("Failed to load settings", error); } finally { setLoading(false); } }; const handleSaveCompany = async () => { try { setSaving(true); const { data: { session } } = await supabase.auth.getSession(); const token = session?.access_token; if (!token) throw new Error("No auth token"); const res = await fetch(`${API_BASE}/api/corp/company`, { method: "PUT", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", }, body: JSON.stringify(company), }); if (res.ok) { aethexToast({ message: "Company profile saved", type: "success" }); } else { throw new Error("Failed to save"); } } catch (error) { aethexToast({ message: "Failed to save company profile", type: "error" }); } finally { setSaving(false); } }; const handleSaveNotifications = async () => { try { setSaving(true); const { data: { session } } = await supabase.auth.getSession(); const token = session?.access_token; if (!token) throw new Error("No auth token"); const res = await fetch(`${API_BASE}/api/user/notifications`, { method: "PUT", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", }, body: JSON.stringify(notifications), }); if (res.ok) { aethexToast({ message: "Notification preferences saved", type: "success" }); } else { throw new Error("Failed to save"); } } catch (error) { aethexToast({ message: "Failed to save notifications", type: "error" }); } finally { setSaving(false); } }; const handleInviteTeamMember = async () => { if (!newMemberEmail) return; try { const { data: { session } } = await supabase.auth.getSession(); const token = session?.access_token; if (!token) throw new Error("No auth token"); const res = await fetch(`${API_BASE}/api/corp/team/invite`, { method: "POST", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", }, body: JSON.stringify({ email: newMemberEmail, role: "member" }), }); if (res.ok) { aethexToast({ message: "Invitation sent", type: "success" }); setNewMemberEmail(""); loadSettings(); } else { throw new Error("Failed to invite"); } } catch (error) { aethexToast({ message: "Failed to send invitation", type: "error" }); } }; const handleRemoveTeamMember = async (memberId: string) => { try { const { data: { session } } = await supabase.auth.getSession(); const token = session?.access_token; if (!token) throw new Error("No auth token"); const res = await fetch(`${API_BASE}/api/corp/team/members/${memberId}`, { method: "DELETE", headers: { Authorization: `Bearer ${token}` }, }); if (res.ok) { aethexToast({ message: "Team member removed", type: "success" }); loadSettings(); } } catch (error) { aethexToast({ message: "Failed to remove member", type: "error" }); } }; if (authLoading || loading) { return ; } return (
{/* Header */}

Settings

Manage your account and preferences

{/* Tabs */} Company Team Notifications Billing Security {/* Company Tab */} Company Profile Update your organization's information
setCompany({ ...company, name: e.target.value })} className="bg-slate-800/50 border-slate-700" />
setCompany({ ...company, industry: e.target.value })} className="bg-slate-800/50 border-slate-700" />
setCompany({ ...company, website: e.target.value })} className="pl-10 bg-slate-800/50 border-slate-700" placeholder="https://" />
setCompany({ ...company, phone: e.target.value })} className="pl-10 bg-slate-800/50 border-slate-700" />

Address

setCompany({ ...company, address: { ...company.address, street: e.target.value } })} className="bg-slate-800/50 border-slate-700" />
setCompany({ ...company, address: { ...company.address, city: e.target.value } })} className="bg-slate-800/50 border-slate-700" />
setCompany({ ...company, address: { ...company.address, state: e.target.value } })} className="bg-slate-800/50 border-slate-700" />
setCompany({ ...company, address: { ...company.address, zip: e.target.value } })} className="bg-slate-800/50 border-slate-700" />
setCompany({ ...company, address: { ...company.address, country: e.target.value } })} className="bg-slate-800/50 border-slate-700" />
{/* Team Tab */} Team Members Manage who has access to your client portal {/* Invite New Member */}
setNewMemberEmail(e.target.value)} className="pl-10 bg-slate-800/50 border-slate-700" />
{/* Team List */}
{teamMembers.length === 0 ? (

No team members yet

) : ( teamMembers.map((member) => (
{member.name?.charAt(0) || member.email.charAt(0).toUpperCase()}

{member.name || member.email}

{member.email}

{member.role} {!member.accepted && ( Pending )}
)) )}
{/* Notifications Tab */} Notification Preferences Choose what updates you want to receive

Invoice Notifications

Receive emails when invoices are issued or paid

setNotifications({ ...notifications, email_invoices: checked })} />

Milestone Updates

Get notified when project milestones are completed

setNotifications({ ...notifications, email_milestones: checked })} />

Weekly Reports

Receive weekly project status reports

setNotifications({ ...notifications, email_reports: checked })} />

Team Updates

Notifications about team member changes

setNotifications({ ...notifications, email_team_updates: checked })} />

Urgent SMS Alerts

Receive SMS for critical updates

setNotifications({ ...notifications, sms_urgent: checked })} />
{/* Billing Tab */} Billing Information Manage payment methods and billing details
setCompany({ ...company, billing_email: e.target.value })} className="pl-10 bg-slate-800/50 border-slate-700" placeholder="billing@company.com" />

Payment Methods

•••• •••• •••• 4242

Expires 12/26

Default
{/* Security Tab */} Security Settings Manage your account security

Change Password

Update your account password

Two-Factor Authentication

Add an extra layer of security

Danger Zone

Permanently delete your account and all associated data

); }