110 lines
3.4 KiB
TypeScript
110 lines
3.4 KiB
TypeScript
import { useState, useEffect } from 'react';
|
|
import { useNavigate } from 'react-router';
|
|
import { Button, Card, FormField, Input, useToast } from '@cameleer/design-system';
|
|
import { useCreateTenant } from '../../api/vendor-hooks';
|
|
import { toSlug } from '../../utils/slug';
|
|
|
|
const TIERS = ['LOW', 'MID', 'HIGH', 'BUSINESS'];
|
|
|
|
export function CreateTenantPage() {
|
|
const navigate = useNavigate();
|
|
const { toast } = useToast();
|
|
const createTenant = useCreateTenant();
|
|
|
|
const [name, setName] = useState('');
|
|
const [slug, setSlug] = useState('');
|
|
const [slugTouched, setSlugTouched] = useState(false);
|
|
const [tier, setTier] = useState('LOW');
|
|
|
|
useEffect(() => {
|
|
if (!slugTouched) {
|
|
setSlug(toSlug(name));
|
|
}
|
|
}, [name, slugTouched]);
|
|
|
|
async function handleSubmit(e: React.FormEvent) {
|
|
e.preventDefault();
|
|
try {
|
|
const result = await createTenant.mutateAsync({ name, slug, tier });
|
|
toast({ title: 'Tenant created', variant: 'success' });
|
|
navigate(`/vendor/tenants/${result.id}`);
|
|
} catch (err) {
|
|
toast({ title: 'Failed to create tenant', description: String(err), variant: 'error' });
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div style={{ padding: '24px', maxWidth: 560 }}>
|
|
<div style={{ marginBottom: 20 }}>
|
|
<h1 style={{ margin: 0, fontSize: '1.25rem', fontWeight: 600 }}>Create Tenant</h1>
|
|
</div>
|
|
|
|
<Card title="Tenant details">
|
|
<form onSubmit={handleSubmit} style={{ display: 'flex', flexDirection: 'column', gap: 16, padding: '8px 0' }}>
|
|
<FormField label="Name" htmlFor="tenant-name" required>
|
|
<Input
|
|
id="tenant-name"
|
|
value={name}
|
|
onChange={(e) => setName(e.target.value)}
|
|
placeholder="Acme Corp"
|
|
required
|
|
/>
|
|
</FormField>
|
|
|
|
<FormField label="Slug" htmlFor="tenant-slug" required hint="URL-safe identifier, auto-generated from name">
|
|
<Input
|
|
id="tenant-slug"
|
|
value={slug}
|
|
onChange={(e) => {
|
|
setSlug(e.target.value);
|
|
setSlugTouched(true);
|
|
}}
|
|
placeholder="acme-corp"
|
|
required
|
|
/>
|
|
</FormField>
|
|
|
|
<FormField label="Tier" htmlFor="tenant-tier" required>
|
|
<select
|
|
id="tenant-tier"
|
|
value={tier}
|
|
onChange={(e) => setTier(e.target.value)}
|
|
style={{
|
|
width: '100%',
|
|
padding: '8px 12px',
|
|
border: '1px solid var(--border)',
|
|
borderRadius: 6,
|
|
background: 'var(--bg-surface)',
|
|
color: 'var(--text-primary)',
|
|
fontSize: '0.875rem',
|
|
}}
|
|
>
|
|
{TIERS.map((t) => (
|
|
<option key={t} value={t}>{t}</option>
|
|
))}
|
|
</select>
|
|
</FormField>
|
|
|
|
<div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end', paddingTop: 8 }}>
|
|
<Button
|
|
type="button"
|
|
variant="ghost"
|
|
onClick={() => navigate('/vendor/tenants')}
|
|
>
|
|
Cancel
|
|
</Button>
|
|
<Button
|
|
type="submit"
|
|
variant="primary"
|
|
loading={createTenant.isPending}
|
|
disabled={!name || !slug}
|
|
>
|
|
Create Tenant
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
</Card>
|
|
</div>
|
|
);
|
|
}
|