143 lines
5.9 KiB
TypeScript
143 lines
5.9 KiB
TypeScript
'use client'
|
||
|
||
import { trpc } from '@/lib/trpc-client'
|
||
import { useState } from 'react'
|
||
|
||
export default function EinstellungenPage() {
|
||
const { data: org, isLoading } = trpc.organizations.me.useQuery()
|
||
const updateMutation = trpc.organizations.update.useMutation()
|
||
const avvMutation = trpc.organizations.acceptAvv.useMutation()
|
||
|
||
const [name, setName] = useState('')
|
||
const [contactEmail, setContactEmail] = useState('')
|
||
|
||
if (isLoading) return <div className="text-gray-500">Wird geladen...</div>
|
||
if (!org) return null
|
||
|
||
return (
|
||
<div className="max-w-2xl space-y-8">
|
||
<h1 className="text-2xl font-bold text-gray-900">Einstellungen</h1>
|
||
|
||
{/* Org Settings */}
|
||
<div className="bg-white rounded-lg border p-6 space-y-4">
|
||
<h2 className="font-semibold text-gray-900">Innung</h2>
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 mb-1">Name der Innung</label>
|
||
<input
|
||
defaultValue={org.name}
|
||
onChange={(e) => setName(e.target.value)}
|
||
className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-brand-500 focus:border-transparent"
|
||
/>
|
||
</div>
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 mb-1">Kontakt-E-Mail</label>
|
||
<input
|
||
type="email"
|
||
defaultValue={org.contactEmail ?? ''}
|
||
onChange={(e) => setContactEmail(e.target.value)}
|
||
className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-brand-500 focus:border-transparent"
|
||
/>
|
||
</div>
|
||
<button
|
||
onClick={() => updateMutation.mutate({ name: name || undefined, contactEmail: contactEmail || undefined })}
|
||
disabled={updateMutation.isPending}
|
||
className="bg-brand-500 text-white px-4 py-2 rounded-lg text-sm font-medium hover:bg-brand-600 disabled:opacity-60 transition-colors"
|
||
>
|
||
{updateMutation.isPending ? 'Wird gespeichert...' : 'Speichern'}
|
||
</button>
|
||
{updateMutation.isSuccess && (
|
||
<p className="text-sm text-green-600">Einstellungen gespeichert ✓</p>
|
||
)}
|
||
</div>
|
||
|
||
{/* AVV */}
|
||
<div className="bg-white rounded-lg border p-6 space-y-4">
|
||
<h2 className="font-semibold text-gray-900">Auftragsverarbeitungsvertrag (AVV)</h2>
|
||
<p className="text-sm text-gray-600">
|
||
Der AVV regelt die Verarbeitung personenbezogener Daten im Auftrag Ihrer Innung
|
||
durch InnungsApp GmbH gemäß Art. 28 DSGVO.
|
||
</p>
|
||
<a
|
||
href="/avv.pdf"
|
||
download
|
||
className="inline-flex items-center gap-2 text-sm text-brand-600 hover:underline"
|
||
>
|
||
📄 AVV als PDF herunterladen
|
||
</a>
|
||
{org.avvAccepted ? (
|
||
<div className="bg-green-50 border border-green-200 rounded-lg p-4">
|
||
<p className="text-sm text-green-700 font-medium">
|
||
✓ AVV akzeptiert am {org.avvAcceptedAt?.toLocaleDateString('de-DE')}
|
||
</p>
|
||
</div>
|
||
) : (
|
||
<div className="bg-yellow-50 border border-yellow-200 rounded-lg p-4 space-y-3">
|
||
<p className="text-sm text-yellow-800 font-medium">
|
||
⚠️ Der AVV muss vor dem Go-Live akzeptiert werden.
|
||
</p>
|
||
<label className="flex items-start gap-2 cursor-pointer">
|
||
<input
|
||
type="checkbox"
|
||
id="avv-check"
|
||
className="mt-0.5 rounded border-gray-300"
|
||
/>
|
||
<span className="text-sm text-gray-700">
|
||
Ich bestätige, dass ich den AVV gelesen habe und im Namen der Innung akzeptiere.
|
||
</span>
|
||
</label>
|
||
<button
|
||
onClick={() => {
|
||
const cb = document.getElementById('avv-check') as HTMLInputElement
|
||
if (!cb.checked) { alert('Bitte bestätigen Sie den AVV.'); return }
|
||
avvMutation.mutate()
|
||
}}
|
||
disabled={avvMutation.isPending}
|
||
className="bg-brand-500 text-white px-4 py-2 rounded-lg text-sm font-medium hover:bg-brand-600 disabled:opacity-60 transition-colors"
|
||
>
|
||
AVV verbindlich akzeptieren
|
||
</button>
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
{/* Registrierungslink */}
|
||
<div className="bg-white rounded-lg border p-6 space-y-4">
|
||
<h2 className="font-semibold text-gray-900">Registrierungslink</h2>
|
||
<p className="text-sm text-gray-600">
|
||
Teilen Sie diesen Link mit neuen Mitgliedern. Sie können sich damit selbst registrieren
|
||
und erhalten einen Aktivierungslink per E-Mail.
|
||
</p>
|
||
<div className="flex gap-2">
|
||
<input
|
||
readOnly
|
||
value={`${typeof window !== 'undefined' ? window.location.origin : ''}/registrierung/${org.slug}`}
|
||
className="flex-1 px-3 py-2 border border-gray-200 rounded-lg text-sm bg-gray-50 text-gray-700 focus:outline-none"
|
||
/>
|
||
<button
|
||
type="button"
|
||
onClick={() =>
|
||
navigator.clipboard.writeText(
|
||
`${window.location.origin}/registrierung/${org.slug}`
|
||
)
|
||
}
|
||
className="px-4 py-2 border border-gray-300 rounded-lg text-sm font-medium text-gray-700 hover:bg-gray-50 transition-colors whitespace-nowrap"
|
||
>
|
||
Kopieren
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Plan Info */}
|
||
<div className="bg-white rounded-lg border p-6">
|
||
<h2 className="font-semibold text-gray-900 mb-2">Plan</h2>
|
||
<span className="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-brand-100 text-brand-700 capitalize">
|
||
{org.plan}
|
||
</span>
|
||
<p className="text-sm text-gray-500 mt-2">
|
||
Für Upgrades oder Fragen zum Plan: kontakt@innungsapp.de
|
||
</p>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|