stadtwerke/innungsapp/apps/admin/app/dashboard/mitglieder/neu/page.tsx

188 lines
7.3 KiB
TypeScript

'use client'
import { useState } from 'react'
import { useRouter } from 'next/navigation'
import { trpc } from '@/lib/trpc-client'
import Link from 'next/link'
import { SPARTEN } from '@innungsapp/shared'
export default function MitgliedNeuPage() {
const router = useRouter()
const [sendInvite, setSendInvite] = useState(true)
const [form, setForm] = useState({
name: '',
betrieb: '',
sparte: 'Elektrotechnik',
ort: '',
telefon: '',
email: '',
status: 'aktiv' as const,
istAusbildungsbetrieb: false,
seit: new Date().getFullYear(),
})
const createMutation = trpc.members.create.useMutation({
onSuccess: () => router.push('/dashboard/mitglieder'),
})
const inviteMutation = trpc.members.invite.useMutation({
onSuccess: () => router.push('/dashboard/mitglieder'),
})
const isPending = createMutation.isPending || inviteMutation.isPending
const error = createMutation.error ?? inviteMutation.error
function handleSubmit(e: React.FormEvent) {
e.preventDefault()
if (sendInvite) {
inviteMutation.mutate(form)
} else {
createMutation.mutate(form)
}
}
return (
<div className="max-w-2xl space-y-6">
<div className="flex items-center gap-4">
<Link href="/dashboard/mitglieder" className="text-gray-400 hover:text-gray-600">
Zurück
</Link>
<h1 className="text-2xl font-bold text-gray-900">Mitglied anlegen</h1>
</div>
<form onSubmit={handleSubmit} className="bg-white rounded-xl border shadow-sm p-6 space-y-4">
<div className="grid grid-cols-2 gap-4">
<div className="col-span-2">
<label className="block text-sm font-medium text-gray-700 mb-1">Name *</label>
<input
required
value={form.name}
onChange={(e) => setForm({ ...form, name: e.target.value })}
className="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-brand-500"
/>
</div>
<div className="col-span-2">
<label className="block text-sm font-medium text-gray-700 mb-1">Betrieb *</label>
<input
required
value={form.betrieb}
onChange={(e) => setForm({ ...form, betrieb: e.target.value })}
className="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-brand-500"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">Sparte *</label>
<select
value={form.sparte}
onChange={(e) => setForm({ ...form, sparte: e.target.value })}
className="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-brand-500"
>
{SPARTEN.map((s) => <option key={s}>{s}</option>)}
</select>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">Ort *</label>
<input
required
value={form.ort}
onChange={(e) => setForm({ ...form, ort: e.target.value })}
className="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-brand-500"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">E-Mail *</label>
<input
required
type="email"
value={form.email}
onChange={(e) => setForm({ ...form, email: e.target.value })}
className="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-brand-500"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">Telefon</label>
<input
type="tel"
value={form.telefon}
onChange={(e) => setForm({ ...form, telefon: e.target.value })}
className="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-brand-500"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">Mitglied seit</label>
<input
type="number"
value={form.seit}
onChange={(e) => setForm({ ...form, seit: Number(e.target.value) })}
min="1900"
max="2100"
className="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-brand-500"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">Status</label>
<select
value={form.status}
onChange={(e) => setForm({ ...form, status: e.target.value as typeof form.status })}
className="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-brand-500"
>
<option value="aktiv">Aktiv</option>
<option value="ruhend">Ruhend</option>
<option value="ausgetreten">Ausgetreten</option>
</select>
</div>
<div className="col-span-2">
<label className="flex items-center gap-2 cursor-pointer">
<input
type="checkbox"
checked={form.istAusbildungsbetrieb}
onChange={(e) => setForm({ ...form, istAusbildungsbetrieb: e.target.checked })}
className="rounded border-gray-300 text-brand-500 focus:ring-brand-500"
/>
<span className="text-sm text-gray-700">Ausbildungsbetrieb</span>
</label>
</div>
</div>
<div className="border-t pt-4">
<label className="flex items-center gap-2 cursor-pointer">
<input
type="checkbox"
checked={sendInvite}
onChange={(e) => setSendInvite(e.target.checked)}
className="rounded border-gray-300 text-brand-500 focus:ring-brand-500"
/>
<span className="text-sm text-gray-700 font-medium">
Einladungs-E-Mail senden
</span>
</label>
<p className="text-xs text-gray-500 mt-1 ml-6">
Das Mitglied erhält eine E-Mail mit einem Login-Link.
</p>
</div>
{error && (
<p className="text-sm text-red-600 bg-red-50 px-4 py-2 rounded-lg">
{error.message}
</p>
)}
<div className="flex gap-3 pt-2">
<button
type="submit"
disabled={isPending}
className="bg-brand-500 text-white px-6 py-2 rounded-lg text-sm font-medium hover:bg-brand-600 disabled:opacity-60 transition-colors"
>
{isPending ? 'Wird gespeichert...' : sendInvite ? 'Speichern & Einladung senden' : 'Speichern'}
</button>
<Link
href="/dashboard/mitglieder"
className="px-6 py-2 rounded-lg text-sm font-medium text-gray-700 hover:bg-gray-100 transition-colors"
>
Abbrechen
</Link>
</div>
</form>
</div>
)
}