Surface actual error message when user creation fails

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Krao Hasanee
2026-03-30 09:14:53 -04:00
parent 8034f15fb5
commit 5519c1f54b
+76 -4
View File
@@ -12,7 +12,10 @@ export default function Companies() {
const [loading, setLoading] = useState(true);
const [showNew, setShowNew] = useState(false);
const [newForm, setNewForm] = useState({ name: '', phone: '', address: '' });
const [showNewUser, setShowNewUser] = useState(false);
const [userForm, setUserForm] = useState({ name: '', email: '', password: '', company_id: '' });
const [saving, setSaving] = useState(false);
const [userError, setUserError] = useState('');
useEffect(() => {
load();
@@ -49,6 +52,29 @@ export default function Companies() {
}
};
const handleCreateUser = async (e) => {
e.preventDefault();
setUserError('');
setSaving(true);
const { data, error } = await supabase.functions.invoke('create-user', {
body: {
name: userForm.name.trim(),
email: userForm.email.trim(),
password: userForm.password,
company_id: userForm.company_id || null,
},
});
setSaving(false);
const errMsg = data?.error || error?.message || (error ? JSON.stringify(error) : null);
if (errMsg) {
setUserError(errMsg);
return;
}
setShowNewUser(false);
setUserForm({ name: '', email: '', password: '', company_id: '' });
load();
};
if (loading) return <Layout><p style={{ padding: 24, color: 'var(--text-muted)' }}>Loading...</p></Layout>;
const unassigned = profiles.filter(p => !p.company_id);
@@ -59,7 +85,7 @@ export default function Companies() {
<div>
<div className="page-title">Companies</div>
<div className="page-subtitle">
{companies.length} company{companies.length !== 1 ? 'ies' : ''}
{companies.length} {companies.length !== 1 ? 'companies' : 'company'}
{unassigned.length > 0 && (
<span style={{ marginLeft: 10, color: 'var(--danger)', fontWeight: 600 }}>
· {unassigned.length} unassigned user{unassigned.length !== 1 ? 's' : ''}
@@ -67,11 +93,57 @@ export default function Companies() {
)}
</div>
</div>
<button className="btn btn-primary" onClick={() => setShowNew(s => !s)}>
{showNew ? 'Cancel' : '+ New Company'}
</button>
<div style={{ display: 'flex', gap: 8 }}>
<button className="btn btn-outline" onClick={() => { setShowNewUser(s => !s); setShowNew(false); setUserError(''); }}>
{showNewUser ? 'Cancel' : '+ New User'}
</button>
<button className="btn btn-primary" onClick={() => { setShowNew(s => !s); setShowNewUser(false); }}>
{showNew ? 'Cancel' : '+ New Company'}
</button>
</div>
</div>
{showNewUser && (
<div className="card" style={{ marginBottom: 24, maxWidth: 480 }}>
<div className="card-title">New User</div>
<form onSubmit={handleCreateUser}>
<div className="grid-2">
<div className="form-group">
<label>Full Name *</label>
<input type="text" placeholder="Jane Smith" value={userForm.name}
onChange={e => setUserForm(f => ({ ...f, name: e.target.value }))} required autoFocus />
</div>
<div className="form-group">
<label>Email *</label>
<input type="email" placeholder="jane@acme.com" value={userForm.email}
onChange={e => setUserForm(f => ({ ...f, email: e.target.value }))} required />
</div>
</div>
<div className="grid-2">
<div className="form-group">
<label>Password *</label>
<input type="password" placeholder="Temporary password" value={userForm.password}
onChange={e => setUserForm(f => ({ ...f, password: e.target.value }))} required minLength={6} />
</div>
<div className="form-group">
<label>Assign to Company</label>
<select value={userForm.company_id} onChange={e => setUserForm(f => ({ ...f, company_id: e.target.value }))}>
<option value="">No company yet</option>
{companies.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
</select>
</div>
</div>
{userError && <p style={{ fontSize: 13, color: 'var(--danger)', marginBottom: 12 }}>{userError}</p>}
<div className="action-buttons">
<button type="submit" className="btn btn-primary" disabled={saving}>
{saving ? 'Creating...' : 'Create User'}
</button>
<button type="button" className="btn btn-outline" onClick={() => setShowNewUser(false)}>Cancel</button>
</div>
</form>
</div>
)}
{showNew && (
<div className="card" style={{ marginBottom: 24, maxWidth: 480 }}>
<div className="card-title">New Company</div>