feature: add sign contract for personal and company
This commit is contained in:
parent
affa6912a9
commit
10d3d341bc
@ -0,0 +1,257 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useState, useEffect } from 'react'
|
||||||
|
import PageLayout from '../../../components/PageLayout'
|
||||||
|
|
||||||
|
export default function CompanySignContractPage() {
|
||||||
|
const [companyName, setCompanyName] = useState('')
|
||||||
|
const [repName, setRepName] = useState('')
|
||||||
|
const [repTitle, setRepTitle] = useState('')
|
||||||
|
const [location, setLocation] = useState('')
|
||||||
|
const [date, setDate] = useState('')
|
||||||
|
const [note, setNote] = useState('')
|
||||||
|
const [agreeContract, setAgreeContract] = useState(false)
|
||||||
|
const [agreeData, setAgreeData] = useState(false)
|
||||||
|
const [confirmSignature, setConfirmSignature] = useState(false)
|
||||||
|
const [submitting, setSubmitting] = useState(false)
|
||||||
|
const [success, setSuccess] = useState(false)
|
||||||
|
const [error, setError] = useState('')
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setDate(new Date().toISOString().slice(0,10))
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const valid = () =>
|
||||||
|
companyName.trim().length > 2 &&
|
||||||
|
repName.trim().length > 4 &&
|
||||||
|
repTitle.trim().length > 1 &&
|
||||||
|
location.trim().length > 1 &&
|
||||||
|
agreeContract &&
|
||||||
|
agreeData &&
|
||||||
|
confirmSignature
|
||||||
|
|
||||||
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
|
e.preventDefault()
|
||||||
|
if (!valid()) {
|
||||||
|
setError('Bitte alle Pflichtfelder & Bestätigungen ausfüllen.')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setError('')
|
||||||
|
setSubmitting(true)
|
||||||
|
try {
|
||||||
|
// TODO: POST /contracts/company/sign { companyName, repName, repTitle, location, date, note }
|
||||||
|
await new Promise(r => setTimeout(r, 1400))
|
||||||
|
setSuccess(true)
|
||||||
|
} catch {
|
||||||
|
setError('Signatur fehlgeschlagen. Bitte erneut versuchen.')
|
||||||
|
} finally {
|
||||||
|
setSubmitting(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageLayout>
|
||||||
|
<div className="relative flex flex-col flex-1 w-full px-5 sm:px-8 lg:px-12 py-12">
|
||||||
|
{/* Background */}
|
||||||
|
<div className="fixed inset-0 -z-10">
|
||||||
|
<div className="absolute inset-0 -z-20 bg-gradient-to-b from-gray-900/95 via-gray-900/80 to-gray-900" />
|
||||||
|
<svg aria-hidden="true" className="absolute inset-0 -z-10 h-full w-full stroke-white/10">
|
||||||
|
<defs>
|
||||||
|
<pattern id="company-contract-pattern" x="50%" y={-1} width={200} height={200} patternUnits="userSpaceOnUse">
|
||||||
|
<path d="M.5 200V.5H200" fill="none" stroke="rgba(255,255,255,0.05)" />
|
||||||
|
</pattern>
|
||||||
|
</defs>
|
||||||
|
<rect fill="url(#company-contract-pattern)" width="100%" height="100%" strokeWidth={0} />
|
||||||
|
</svg>
|
||||||
|
<div aria-hidden="true" className="absolute top-0 right-0 left-1/2 -ml-24 blur-3xl transform-gpu overflow-hidden lg:ml-24 xl:ml-48">
|
||||||
|
<div
|
||||||
|
className="aspect-[801/1036] w-[50.0625rem] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-50"
|
||||||
|
style={{ clipPath:'polygon(63.1% 29.5%,100% 17.1%,76.6% 3%,48.4% 0%,44.6% 4.7%,54.5% 25.3%,59.8% 49%,55.2% 57.8%,44.4% 57.2%,27.8% 47.9%,35.1% 81.5%,0% 97.7%,39.2% 100%,35.2% 81.4%,97.2% 52.8%,63.1% 29.5%)'}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
className="relative max-w-5xl w-full mx-auto bg-white rounded-2xl shadow-xl ring-1 ring-black/10"
|
||||||
|
>
|
||||||
|
<div className="px-6 py-8 sm:px-10 lg:px-14">
|
||||||
|
<h1 className="text-center text-2xl sm:text-3xl font-semibold text-[#0F172A] mb-2">
|
||||||
|
Sign Company Partnership Contract
|
||||||
|
</h1>
|
||||||
|
<p className="text-center text-sm text-gray-600 mb-8">
|
||||||
|
Prüfe die Vertragsdetails und unterschreibe im Namen des Unternehmens.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Meta + Preview */}
|
||||||
|
<section className="grid gap-8 lg:grid-cols-2 mb-10">
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="rounded-lg border border-gray-200 p-5 bg-gray-50">
|
||||||
|
<h2 className="text-sm font-semibold text-gray-800 mb-3">Contract Information</h2>
|
||||||
|
<ul className="space-y-2 text-xs sm:text-sm text-gray-600">
|
||||||
|
<li><span className="font-medium text-gray-700">Contract ID:</span> COMP-2024-017</li>
|
||||||
|
<li><span className="font-medium text-gray-700">Version:</span> 2.4 (gültig ab 01.11.2024)</li>
|
||||||
|
<li><span className="font-medium text-gray-700">Jurisdiction:</span> EU / Germany</li>
|
||||||
|
<li><span className="font-medium text-gray-700">Language:</span> DE (binding)</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="rounded-lg border border-amber-200 bg-amber-50 p-5">
|
||||||
|
<h3 className="text-sm font-semibold text-amber-900 mb-2">Achtung</h3>
|
||||||
|
<p className="text-xs sm:text-sm text-amber-800 leading-relaxed">
|
||||||
|
Du bestätigst rechtsverbindlich, dass du bevollmächtigt bist im Namen des Unternehmens zu unterschreiben.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="rounded-lg border border-gray-200 h-64 sm:h-72 bg-white flex items-center justify-center relative overflow-hidden">
|
||||||
|
<p className="text-xs text-gray-500 text-center px-6">
|
||||||
|
(Vertragsvorschau / PDF Platzhalter)
|
||||||
|
<br/>Company Contract PDF would render here.
|
||||||
|
</p>
|
||||||
|
<div className="absolute inset-x-0 bottom-0 p-3 bg-gradient-to-t from-white via-white/90 to-transparent text-[11px] text-gray-500 text-center">
|
||||||
|
Scroll preview (disabled in mock)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<hr className="my-10 border-gray-200" />
|
||||||
|
|
||||||
|
{/* Company Signature Fields */}
|
||||||
|
<section>
|
||||||
|
<h2 className="text-sm font-semibold text-[#0F2460] mb-5">Company & Representative</h2>
|
||||||
|
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
|
||||||
|
<div className="sm:col-span-2 lg:col-span-2">
|
||||||
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
|
Unternehmensname *
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
value={companyName}
|
||||||
|
onChange={e => { setCompanyName(e.target.value); setError('') }}
|
||||||
|
placeholder="Firmenname offiziell"
|
||||||
|
className="w-full rounded-lg border border-gray-300 px-4 py-2.5 text-sm focus:ring-2 focus:ring-indigo-500 focus:border-transparent"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
|
Datum *
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="date"
|
||||||
|
value={date}
|
||||||
|
onChange={e => setDate(e.target.value)}
|
||||||
|
className="w-full rounded-lg border border-gray-300 px-4 py-2.5 text-sm focus:ring-2 focus:ring-indigo-500 focus:border-transparent"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
|
Ort *
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
value={location}
|
||||||
|
onChange={e => { setLocation(e.target.value); setError('') }}
|
||||||
|
placeholder="z.B. München"
|
||||||
|
className="w-full rounded-lg border border-gray-300 px-4 py-2.5 text-sm focus:ring-2 focus:ring-indigo-500 focus:border-transparent"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="sm:col-span-2 lg:col-span-1">
|
||||||
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
|
Vertreter Name *
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
value={repName}
|
||||||
|
onChange={e => { setRepName(e.target.value); setError('') }}
|
||||||
|
placeholder="Vor- und Nachname"
|
||||||
|
className="w-full rounded-lg border border-gray-300 px-4 py-2.5 text-sm focus:ring-2 focus:ring-indigo-500 focus:border-transparent"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="sm:col-span-2 lg:col-span-2">
|
||||||
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
|
Vertreter Position / Titel *
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
value={repTitle}
|
||||||
|
onChange={e => { setRepTitle(e.target.value); setError('') }}
|
||||||
|
placeholder="z.B. Geschäftsführer, Authorized Signatory"
|
||||||
|
className="w-full rounded-lg border border-gray-300 px-4 py-2.5 text-sm focus:ring-2 focus:ring-indigo-500 focus:border-transparent"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="sm:col-span-2 lg:col-span-3">
|
||||||
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
|
Notiz (optional)
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
value={note}
|
||||||
|
onChange={e => setNote(e.target.value)}
|
||||||
|
placeholder="Interne Referenz / Zusatz"
|
||||||
|
className="w-full rounded-lg border border-gray-300 px-4 py-2.5 text-sm focus:ring-2 focus:ring-indigo-500 focus:border-transparent"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<hr className="my-10 border-gray-200" />
|
||||||
|
|
||||||
|
{/* Confirmations */}
|
||||||
|
<section className="space-y-5">
|
||||||
|
<h2 className="text-sm font-semibold text-[#0F2460]">Bestätigungen</h2>
|
||||||
|
<label className="flex items-start gap-3 text-sm text-gray-700">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={agreeContract}
|
||||||
|
onChange={e => setAgreeContract(e.target.checked)}
|
||||||
|
className="mt-1 h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
|
||||||
|
/>
|
||||||
|
<span>Ich bestätige, den vollständigen Vertrag im Namen des Unternehmens gelesen und akzeptiert zu haben.</span>
|
||||||
|
</label>
|
||||||
|
<label className="flex items-start gap-3 text-sm text-gray-700">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={agreeData}
|
||||||
|
onChange={e => setAgreeData(e.target.checked)}
|
||||||
|
className="mt-1 h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
|
||||||
|
/>
|
||||||
|
<span>Ich stimme der Verarbeitung der Unternehmens- & personenbezogenen Daten gemäß Datenschutzerklärung zu.</span>
|
||||||
|
</label>
|
||||||
|
<label className="flex items-start gap-3 text-sm text-gray-700">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={confirmSignature}
|
||||||
|
onChange={e => setConfirmSignature(e.target.checked)}
|
||||||
|
className="mt-1 h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
|
||||||
|
/>
|
||||||
|
<span>Ich bin bevollmächtigt, rechtsverbindlich für dieses Unternehmen zu unterschreiben.</span>
|
||||||
|
</label>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{error && (
|
||||||
|
<div className="mt-8 rounded-md border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-600">
|
||||||
|
{error}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{success && (
|
||||||
|
<div className="mt-8 rounded-md border border-green-300 bg-green-50 px-4 py-3 text-sm text-green-700">
|
||||||
|
Vertrag erfolgreich unterzeichnet.
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="mt-10 flex justify-end">
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={submitting || success}
|
||||||
|
className="inline-flex items-center justify-center rounded-md bg-indigo-600 px-8 py-3 text-sm font-semibold text-white shadow hover:bg-indigo-500 disabled:bg-gray-400 disabled:cursor-not-allowed transition"
|
||||||
|
>
|
||||||
|
{submitting ? 'Signiere…' : success ? 'Signiert' : 'Jetzt signieren'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</PageLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -0,0 +1,232 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useState, useEffect } from 'react'
|
||||||
|
import PageLayout from '../../../components/PageLayout'
|
||||||
|
|
||||||
|
export default function PersonalSignContractPage() {
|
||||||
|
const [fullName, setFullName] = useState('')
|
||||||
|
const [location, setLocation] = useState('')
|
||||||
|
const [date, setDate] = useState('')
|
||||||
|
const [note, setNote] = useState('')
|
||||||
|
const [agreeContract, setAgreeContract] = useState(false)
|
||||||
|
const [agreeData, setAgreeData] = useState(false)
|
||||||
|
const [confirmSignature, setConfirmSignature] = useState(false)
|
||||||
|
const [submitting, setSubmitting] = useState(false)
|
||||||
|
const [success, setSuccess] = useState(false)
|
||||||
|
const [error, setError] = useState('')
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setDate(new Date().toISOString().slice(0, 10))
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const valid = () =>
|
||||||
|
fullName.trim().length > 4 &&
|
||||||
|
location.trim().length > 1 &&
|
||||||
|
agreeContract &&
|
||||||
|
agreeData &&
|
||||||
|
confirmSignature
|
||||||
|
|
||||||
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
|
e.preventDefault()
|
||||||
|
if (!valid()) {
|
||||||
|
setError('Bitte alle Pflichtfelder & Bestätigungen ausfüllen.')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setError('')
|
||||||
|
setSubmitting(true)
|
||||||
|
try {
|
||||||
|
// TODO: POST /contracts/personal/sign { fullName, location, date, note }
|
||||||
|
await new Promise(r => setTimeout(r, 1200))
|
||||||
|
setSuccess(true)
|
||||||
|
} catch {
|
||||||
|
setError('Signatur fehlgeschlagen. Bitte erneut versuchen.')
|
||||||
|
} finally {
|
||||||
|
setSubmitting(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageLayout>
|
||||||
|
<div className="relative flex flex-col flex-1 w-full px-5 sm:px-8 lg:px-12 py-12">
|
||||||
|
{/* Background */}
|
||||||
|
<div className="fixed inset-0 -z-10">
|
||||||
|
<div className="absolute inset-0 -z-20 bg-gradient-to-b from-gray-900/95 via-gray-900/80 to-gray-900" />
|
||||||
|
<svg aria-hidden="true" className="absolute inset-0 -z-10 h-full w-full stroke-white/10">
|
||||||
|
<defs>
|
||||||
|
<pattern id="personal-contract-pattern" x="50%" y={-1} width={200} height={200} patternUnits="userSpaceOnUse">
|
||||||
|
<path d="M.5 200V.5H200" fill="none" stroke="rgba(255,255,255,0.05)" />
|
||||||
|
</pattern>
|
||||||
|
</defs>
|
||||||
|
<rect fill="url(#personal-contract-pattern)" width="100%" height="100%" strokeWidth={0} />
|
||||||
|
</svg>
|
||||||
|
<div aria-hidden="true" className="absolute top-0 right-0 left-1/2 -ml-24 blur-3xl transform-gpu overflow-hidden lg:ml-24 xl:ml-48">
|
||||||
|
<div
|
||||||
|
className="aspect-[801/1036] w-[50.0625rem] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-50"
|
||||||
|
style={{ clipPath:'polygon(63.1% 29.5%,100% 17.1%,76.6% 3%,48.4% 0%,44.6% 4.7%,54.5% 25.3%,59.8% 49%,55.2% 57.8%,44.4% 57.2%,27.8% 47.9%,35.1% 81.5%,0% 97.7%,39.2% 100%,35.2% 81.4%,97.2% 52.8%,63.1% 29.5%)'}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
className="relative max-w-5xl w-full mx-auto bg-white rounded-2xl shadow-xl ring-1 ring-black/10"
|
||||||
|
>
|
||||||
|
<div className="px-6 py-8 sm:px-10 lg:px-14">
|
||||||
|
<h1 className="text-center text-2xl sm:text-3xl font-semibold text-[#0F172A] mb-2">
|
||||||
|
Sign Personal Participation Contract
|
||||||
|
</h1>
|
||||||
|
<p className="text-center text-sm text-gray-600 mb-8">
|
||||||
|
Bitte überprüfe die Vertragsdetails und unterschreibe elektronisch.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Contract Meta + Preview */}
|
||||||
|
<section className="grid gap-8 lg:grid-cols-2 mb-10">
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="rounded-lg border border-gray-200 p-5 bg-gray-50">
|
||||||
|
<h2 className="text-sm font-semibold text-gray-800 mb-3">Contract Information</h2>
|
||||||
|
<ul className="space-y-2 text-xs sm:text-sm text-gray-600">
|
||||||
|
<li><span className="font-medium text-gray-700">Contract ID:</span> PERS-2024-001</li>
|
||||||
|
<li><span className="font-medium text-gray-700">Version:</span> 1.2 (gültig ab 01.11.2024)</li>
|
||||||
|
<li><span className="font-medium text-gray-700">Jurisdiction:</span> EU / Germany</li>
|
||||||
|
<li><span className="font-medium text-gray-700">Language:</span> DE (verbindlich)</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="rounded-lg border border-indigo-100 bg-indigo-50/60 p-5">
|
||||||
|
<h3 className="text-sm font-semibold text-indigo-900 mb-2">Hinweis</h3>
|
||||||
|
<p className="text-xs sm:text-sm text-indigo-800 leading-relaxed">
|
||||||
|
Deine elektronische Signatur ist rechtsverbindlich. Stelle sicher, dass alle Angaben korrekt sind.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="rounded-lg border border-gray-200 h-64 sm:h-72 bg-white relative flex items-center justify-center overflow-hidden">
|
||||||
|
<p className="text-xs text-gray-500 text-center px-6">
|
||||||
|
(Vertragsvorschau / PDF Platzhalter)
|
||||||
|
<br/>Der vollständige Vertrag wird hier als PDF gerendert.
|
||||||
|
</p>
|
||||||
|
<div className="absolute inset-x-0 bottom-0 p-3 bg-gradient-to-t from-white via-white/90 to-transparent text-[11px] text-gray-500 text-center">
|
||||||
|
Scroll preview (disabled in mock)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<hr className="my-10 border-gray-200" />
|
||||||
|
|
||||||
|
{/* Signature Fields */}
|
||||||
|
<section>
|
||||||
|
<h2 className="text-sm font-semibold text-[#0F2460] mb-5">Signature Details</h2>
|
||||||
|
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
|
||||||
|
<div className="sm:col-span-2 lg:col-span-2">
|
||||||
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
|
Vollständiger Name (Signatur) *
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
value={fullName}
|
||||||
|
onChange={e => { setFullName(e.target.value); setError('') }}
|
||||||
|
placeholder="Vor- und Nachname"
|
||||||
|
className="w-full rounded-lg border border-gray-300 px-4 py-2.5 text-sm focus:ring-2 focus:ring-indigo-500 focus:border-transparent"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<p className="mt-1 text-xs text-gray-500">
|
||||||
|
Muss deinem amtlichen Ausweis entsprechen.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
|
Datum *
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="date"
|
||||||
|
value={date}
|
||||||
|
onChange={e => setDate(e.target.value)}
|
||||||
|
className="w-full rounded-lg border border-gray-300 px-4 py-2.5 text-sm focus:ring-2 focus:ring-indigo-500 focus:border-transparent"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
|
Ort *
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
value={location}
|
||||||
|
onChange={e => { setLocation(e.target.value); setError('') }}
|
||||||
|
placeholder="z.B. Berlin"
|
||||||
|
className="w-full rounded-lg border border-gray-300 px-4 py-2.5 text-sm focus:ring-2 focus:ring-indigo-500 focus:border-transparent"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="sm:col-span-2 lg:col-span-3">
|
||||||
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
|
Notiz (optional)
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
value={note}
|
||||||
|
onChange={e => setNote(e.target.value)}
|
||||||
|
placeholder="Optionale zusätzliche Bemerkung"
|
||||||
|
className="w-full rounded-lg border border-gray-300 px-4 py-2.5 text-sm focus:ring-2 focus:ring-indigo-500 focus:border-transparent"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<hr className="my-10 border-gray-200" />
|
||||||
|
|
||||||
|
{/* Confirmations */}
|
||||||
|
<section className="space-y-5">
|
||||||
|
<h2 className="text-sm font-semibold text-[#0F2460]">Bestätigungen</h2>
|
||||||
|
<label className="flex items-start gap-3 text-sm text-gray-700">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={agreeContract}
|
||||||
|
onChange={e => setAgreeContract(e.target.checked)}
|
||||||
|
className="mt-1 h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
|
||||||
|
/>
|
||||||
|
<span>Ich bestätige, dass ich den Vertrag vollständig gelesen und verstanden habe.</span>
|
||||||
|
</label>
|
||||||
|
<label className="flex items-start gap-3 text-sm text-gray-700">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={agreeData}
|
||||||
|
onChange={e => setAgreeData(e.target.checked)}
|
||||||
|
className="mt-1 h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
|
||||||
|
/>
|
||||||
|
<span>Ich stimme der Verarbeitung meiner personenbezogenen Daten gemäß Datenschutzerklärung zu.</span>
|
||||||
|
</label>
|
||||||
|
<label className="flex items-start gap-3 text-sm text-gray-700">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={confirmSignature}
|
||||||
|
onChange={e => setConfirmSignature(e.target.checked)}
|
||||||
|
className="mt-1 h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
|
||||||
|
/>
|
||||||
|
<span>Ich bestätige, dass diese elektronische Unterschrift rechtsverbindlich ist und einer handschriftlichen Signatur entspricht.</span>
|
||||||
|
</label>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{error && (
|
||||||
|
<div className="mt-8 rounded-md border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-600">
|
||||||
|
{error}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{success && (
|
||||||
|
<div className="mt-8 rounded-md border border-green-300 bg-green-50 px-4 py-3 text-sm text-green-700">
|
||||||
|
Vertrag erfolgreich unterzeichnet.
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="mt-10 flex justify-end">
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={submitting || success}
|
||||||
|
className="inline-flex items-center justify-center rounded-md bg-indigo-600 px-8 py-3 text-sm font-semibold text-white shadow hover:bg-indigo-500 disabled:bg-gray-400 disabled:cursor-not-allowed transition"
|
||||||
|
>
|
||||||
|
{submitting ? 'Signiere…' : success ? 'Signiert' : 'Jetzt signieren'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</PageLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user