feat: update success messages for document uploads and contract signing to include redirect notice + remove cow
This commit is contained in:
parent
1f91f09777
commit
6bf1ca006e
@ -211,11 +211,11 @@ export default function TutorialModal({
|
|||||||
|
|
||||||
{/* Visual Section - Right Half */}
|
{/* Visual Section - Right Half */}
|
||||||
<div className="relative lg:flex-1 mt-4 lg:mt-0 h-32 lg:h-full lg:min-h-[150px] flex items-end justify-end">
|
<div className="relative lg:flex-1 mt-4 lg:mt-0 h-32 lg:h-full lg:min-h-[150px] flex items-end justify-end">
|
||||||
<img
|
{/* <img
|
||||||
src="/images/misc/cow.png"
|
src="/images/misc/cow.png"
|
||||||
alt="Profit Planet Mascot"
|
alt="Profit Planet Mascot"
|
||||||
className="max-h-full max-w-full object-contain opacity-90 pl-30"
|
className="max-h-full max-w-full object-contain opacity-90 pl-30"
|
||||||
/>
|
/> */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Dialog.Panel>
|
</Dialog.Panel>
|
||||||
@ -324,7 +324,7 @@ export const createTutorialSteps = (
|
|||||||
{
|
{
|
||||||
id: 6,
|
id: 6,
|
||||||
title: "You're all set! 🎉 Welcome to the family",
|
title: "You're all set! 🎉 Welcome to the family",
|
||||||
description: "Congratulations! You've completed all the steps perfectly. Our friendly team will now review your information - we'll have you approved and ready to go very soon!",
|
description: "Congratulations! Our team will now review your information and have you approved very soon!",
|
||||||
details: [
|
details: [
|
||||||
"Our team will carefully review everything you've submitted",
|
"Our team will carefully review everything you've submitted",
|
||||||
"This usually takes just 1-2 business days",
|
"This usually takes just 1-2 business days",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import PageLayout from '../../../components/PageLayout'
|
import PageLayout from '../../../components/PageLayout'
|
||||||
import useAuthStore from '../../../store/authStore'
|
import useAuthStore from '../../../store/authStore'
|
||||||
@ -64,6 +64,50 @@ export default function PersonalAdditionalInformationPage() {
|
|||||||
const [success, setSuccess] = useState(false)
|
const [success, setSuccess] = useState(false)
|
||||||
const [error, setError] = useState('')
|
const [error, setError] = useState('')
|
||||||
|
|
||||||
|
// Prefill form if profile already exists
|
||||||
|
useEffect(() => {
|
||||||
|
let abort = false
|
||||||
|
async function loadProfile() {
|
||||||
|
if (!accessToken) return
|
||||||
|
try {
|
||||||
|
const res = await fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}/api/me`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { Authorization: `Bearer ${accessToken}` }
|
||||||
|
})
|
||||||
|
if (!res.ok) return
|
||||||
|
const data = await res.json().catch(() => null)
|
||||||
|
const profile = data?.profile
|
||||||
|
const user = data?.user
|
||||||
|
if (!profile || abort) return
|
||||||
|
const toDateInput = (d?: string) => {
|
||||||
|
if (!d) return ''
|
||||||
|
const dt = new Date(d)
|
||||||
|
if (Number.isNaN(dt.getTime())) return ''
|
||||||
|
return dt.toISOString().split('T')[0]
|
||||||
|
}
|
||||||
|
setForm(prev => ({
|
||||||
|
...prev,
|
||||||
|
dob: toDateInput(profile.date_of_birth || profile.dateOfBirth),
|
||||||
|
nationality: profile.nationality || prev.nationality,
|
||||||
|
street: profile.address || prev.street,
|
||||||
|
postalCode: profile.zip_code || profile.zipCode || prev.postalCode,
|
||||||
|
city: profile.city || prev.city,
|
||||||
|
country: profile.country || prev.country,
|
||||||
|
accountHolder: profile.account_holder_name || profile.accountHolderName || prev.accountHolder,
|
||||||
|
// Prefer IBAN from users table (data.user.iban), fallback to profile if any
|
||||||
|
iban: (user?.iban ?? profile.iban ?? prev.iban) as string,
|
||||||
|
secondPhone: profile.phone_secondary || profile.phoneSecondary || prev.secondPhone,
|
||||||
|
emergencyName: profile.emergency_contact_name || profile.emergencyContactName || prev.emergencyName,
|
||||||
|
emergencyPhone: profile.emergency_contact_phone || profile.emergencyContactPhone || prev.emergencyPhone,
|
||||||
|
}))
|
||||||
|
} catch (_) {
|
||||||
|
// ignore prefill errors; user can still fill manually
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loadProfile()
|
||||||
|
return () => { abort = true }
|
||||||
|
}, [accessToken])
|
||||||
|
|
||||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {
|
||||||
const { name, value } = e.target
|
const { name, value } = e.target
|
||||||
setForm(p => ({ ...p, [name]: value }))
|
setForm(p => ({ ...p, [name]: value }))
|
||||||
@ -101,20 +145,20 @@ export default function PersonalAdditionalInformationPage() {
|
|||||||
]
|
]
|
||||||
for (const k of requiredKeys) {
|
for (const k of requiredKeys) {
|
||||||
if (!form[k].trim()) {
|
if (!form[k].trim()) {
|
||||||
setError('Bitte alle Pflichtfelder ausfüllen.')
|
setError('Please fill in all required fields.')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Date of birth validation
|
// Date of birth validation
|
||||||
if (!validateDateOfBirth(form.dob)) {
|
if (!validateDateOfBirth(form.dob)) {
|
||||||
setError('Ungültiges Geburtsdatum. Sie müssen mindestens 18 Jahre alt sein.')
|
setError('Invalid date of birth. You must be at least 18 years old.')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// very loose IBAN check
|
// very loose IBAN check
|
||||||
if (!/^([A-Z]{2}\d{2}[A-Z0-9]{10,30})$/i.test(form.iban.replace(/\s+/g,''))) {
|
if (!/^([A-Z]{2}\d{2}[A-Z0-9]{10,30})$/i.test(form.iban.replace(/\s+/g,''))) {
|
||||||
setError('Ungültige IBAN.')
|
setError('Invalid IBAN.')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
setError('')
|
setError('')
|
||||||
@ -183,7 +227,7 @@ export default function PersonalAdditionalInformationPage() {
|
|||||||
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('Personal profile save error:', error)
|
console.error('Personal profile save error:', error)
|
||||||
setError(error.message || 'Speichern fehlgeschlagen. Bitte erneut versuchen.')
|
setError(error.message || 'Save failed. Please try again.')
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
@ -413,7 +457,7 @@ export default function PersonalAdditionalInformationPage() {
|
|||||||
)}
|
)}
|
||||||
{success && (
|
{success && (
|
||||||
<div className="mt-6 rounded-md border border-green-300 bg-green-50 px-4 py-3 text-xs text-green-700">
|
<div className="mt-6 rounded-md border border-green-300 bg-green-50 px-4 py-3 text-xs text-green-700">
|
||||||
Daten gespeichert.
|
Data saved. Redirecting shortly…
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@ -423,7 +467,7 @@ export default function PersonalAdditionalInformationPage() {
|
|||||||
disabled={loading || success}
|
disabled={loading || success}
|
||||||
className="inline-flex items-center rounded-md bg-indigo-600 px-6 py-2.5 text-sm font-semibold text-white shadow hover:bg-indigo-500 disabled:bg-gray-400 disabled:cursor-not-allowed"
|
className="inline-flex items-center rounded-md bg-indigo-600 px-6 py-2.5 text-sm font-semibold text-white shadow hover:bg-indigo-500 disabled:bg-gray-400 disabled:cursor-not-allowed"
|
||||||
>
|
>
|
||||||
{loading ? 'Speichern…' : success ? 'Gespeichert' : 'Save & Continue'}
|
{loading ? 'Saving…' : success ? 'Saved' : 'Save & Continue'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -78,15 +78,15 @@ export default function CompanySignContractPage() {
|
|||||||
if (!valid()) {
|
if (!valid()) {
|
||||||
// Detailed error message to help debug
|
// Detailed error message to help debug
|
||||||
const issues = []
|
const issues = []
|
||||||
if (companyName.trim().length < 3) issues.push('Firmenname (mindestens 3 Zeichen)')
|
if (companyName.trim().length < 3) issues.push('Company name (min 3 characters)')
|
||||||
if (repName.trim().length < 3) issues.push('Vertreter Name (mindestens 3 Zeichen)')
|
if (repName.trim().length < 3) issues.push('Representative name (min 3 characters)')
|
||||||
if (repTitle.trim().length < 2) issues.push('Vertretertitel (mindestens 2 Zeichen)')
|
if (repTitle.trim().length < 2) issues.push('Representative title (min 2 characters)')
|
||||||
if (location.trim().length < 2) issues.push('Ort (mindestens 2 Zeichen)')
|
if (location.trim().length < 2) issues.push('Location (min 2 characters)')
|
||||||
if (!agreeContract) issues.push('Vertrag gelesen und verstanden')
|
if (!agreeContract) issues.push('Contract read and understood')
|
||||||
if (!agreeData) issues.push('Datenschutzerklärung zugestimmt')
|
if (!agreeData) issues.push('Privacy policy accepted')
|
||||||
if (!confirmSignature) issues.push('Elektronische Signatur bestätigt')
|
if (!confirmSignature) issues.push('Electronic signature confirmed')
|
||||||
|
|
||||||
setError(`Bitte vervollständigen: ${issues.join(', ')}`)
|
setError(`Please complete: ${issues.join(', ')}`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,7 +156,7 @@ export default function CompanySignContractPage() {
|
|||||||
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('Contract signing error:', error)
|
console.error('Contract signing error:', error)
|
||||||
setError(error.message || 'Signatur fehlgeschlagen. Bitte erneut versuchen.')
|
setError(error.message || 'Signature failed. Please try again.')
|
||||||
} finally {
|
} finally {
|
||||||
setSubmitting(false)
|
setSubmitting(false)
|
||||||
}
|
}
|
||||||
@ -193,7 +193,7 @@ export default function CompanySignContractPage() {
|
|||||||
Sign Company Partnership Contract
|
Sign Company Partnership Contract
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-center text-sm text-gray-600 mb-8">
|
<p className="text-center text-sm text-gray-600 mb-8">
|
||||||
Prüfe die Vertragsdetails und unterschreibe im Namen des Unternehmens.
|
Please review the contract details and sign on behalf of the company.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{/* Meta + Preview */}
|
{/* Meta + Preview */}
|
||||||
@ -203,22 +203,22 @@ export default function CompanySignContractPage() {
|
|||||||
<h2 className="text-sm font-semibold text-gray-800 mb-3">Contract Information</h2>
|
<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">
|
<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">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">Version:</span> 2.4 (valid from 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">Jurisdiction:</span> EU / Germany</li>
|
||||||
<li><span className="font-medium text-gray-700">Language:</span> DE (binding)</li>
|
<li><span className="font-medium text-gray-700">Language:</span> DE (binding)</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div className="rounded-lg border border-amber-200 bg-amber-50 p-5">
|
<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>
|
<h3 className="text-sm font-semibold text-amber-900 mb-2">Attention</h3>
|
||||||
<p className="text-xs sm:text-sm text-amber-800 leading-relaxed">
|
<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.
|
You confirm that you are authorized to sign on behalf of the company.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="rounded-lg border border-gray-200 bg-white relative overflow-hidden">
|
<div className="rounded-lg border border-gray-200 bg-white relative overflow-hidden">
|
||||||
<div className="flex items-center justify-between p-3 border-b border-gray-200 bg-gray-50">
|
<div className="flex items-center justify-between p-3 border-b border-gray-200 bg-gray-50">
|
||||||
<h3 className="text-sm font-semibold text-gray-900">Vertragsvorschau (Unternehmen)</h3>
|
<h3 className="text-sm font-semibold text-gray-900">Company Contract Preview</h3>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@ -260,18 +260,18 @@ export default function CompanySignContractPage() {
|
|||||||
disabled={previewLoading}
|
disabled={previewLoading}
|
||||||
className="inline-flex items-center rounded-md bg-indigo-600 hover:bg-indigo-500 text-white px-2.5 py-1.5 text-xs disabled:opacity-60"
|
className="inline-flex items-center rounded-md bg-indigo-600 hover:bg-indigo-500 text-white px-2.5 py-1.5 text-xs disabled:opacity-60"
|
||||||
>
|
>
|
||||||
{previewLoading ? 'Lade…' : 'Refresh'}
|
{previewLoading ? 'Loading…' : 'Refresh'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{previewLoading ? (
|
{previewLoading ? (
|
||||||
<div className="h-72 flex items-center justify-center text-xs text-gray-500">Lade Vorschau…</div>
|
<div className="h-72 flex items-center justify-center text-xs text-gray-500">Loading preview…</div>
|
||||||
) : previewError ? (
|
) : previewError ? (
|
||||||
<div className="h-72 flex items-center justify-center text-xs text-red-600 px-4 text-center">{previewError}</div>
|
<div className="h-72 flex items-center justify-center text-xs text-red-600 px-4 text-center">{previewError}</div>
|
||||||
) : previewHtml ? (
|
) : previewHtml ? (
|
||||||
<iframe title="Company Contract Preview" className="w-full h-72" srcDoc={previewHtml} />
|
<iframe title="Company Contract Preview" className="w-full h-72" srcDoc={previewHtml} />
|
||||||
) : (
|
) : (
|
||||||
<div className="h-72 flex items-center justify-center text-xs text-gray-500">Keine Vorschau verfügbar.</div>
|
<div className="h-72 flex items-center justify-center text-xs text-gray-500">No preview available.</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -285,7 +285,7 @@ export default function CompanySignContractPage() {
|
|||||||
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
|
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
|
||||||
<div className="sm:col-span-2 lg:col-span-2">
|
<div className="sm:col-span-2 lg:col-span-2">
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
Unternehmensname *
|
Company Name *
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
value={companyName}
|
value={companyName}
|
||||||
@ -297,7 +297,7 @@ export default function CompanySignContractPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
Datum *
|
Date *
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
@ -308,8 +308,8 @@ export default function CompanySignContractPage() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text_sm font-medium text-gray-700 mb-1">
|
||||||
Ort *
|
Location *
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
value={location}
|
value={location}
|
||||||
@ -320,8 +320,8 @@ export default function CompanySignContractPage() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="sm:col-span-2 lg:col-span-1">
|
<div className="sm:col-span-2 lg:col-span-1">
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text_sm font-medium text-gray-700 mb-1">
|
||||||
Vertreter Name *
|
Representative Name *
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
value={repName}
|
value={repName}
|
||||||
@ -333,7 +333,7 @@ export default function CompanySignContractPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="sm:col-span-2 lg:col-span-2">
|
<div className="sm:col-span-2 lg:col-span-2">
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
Vertreter Position / Titel *
|
Representative Position / Title *
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
value={repTitle}
|
value={repTitle}
|
||||||
@ -345,7 +345,7 @@ export default function CompanySignContractPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="sm:col-span-2 lg:col-span-3">
|
<div className="sm:col-span-2 lg:col-span-3">
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
Notiz (optional)
|
Note (optional)
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
value={note}
|
value={note}
|
||||||
@ -361,7 +361,7 @@ export default function CompanySignContractPage() {
|
|||||||
|
|
||||||
{/* Confirmations */}
|
{/* Confirmations */}
|
||||||
<section className="space-y-5">
|
<section className="space-y-5">
|
||||||
<h2 className="text-sm font-semibold text-[#0F2460]">Bestätigungen</h2>
|
<h2 className="text-sm font-semibold text-[#0F2460]">Confirmations</h2>
|
||||||
<label className="flex items-start gap-3 text-sm text-gray-700">
|
<label className="flex items-start gap-3 text-sm text-gray-700">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@ -369,7 +369,7 @@ export default function CompanySignContractPage() {
|
|||||||
onChange={e => setAgreeContract(e.target.checked)}
|
onChange={e => setAgreeContract(e.target.checked)}
|
||||||
className="mt-1 h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
|
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>
|
<span>I confirm I have read and accepted the full contract on behalf of the company.</span>
|
||||||
</label>
|
</label>
|
||||||
<label className="flex items-start gap-3 text-sm text-gray-700">
|
<label className="flex items-start gap-3 text-sm text-gray-700">
|
||||||
<input
|
<input
|
||||||
@ -378,7 +378,7 @@ export default function CompanySignContractPage() {
|
|||||||
onChange={e => setAgreeData(e.target.checked)}
|
onChange={e => setAgreeData(e.target.checked)}
|
||||||
className="mt-1 h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
|
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>
|
<span>I consent to processing of company and personal data in accordance with the privacy policy.</span>
|
||||||
</label>
|
</label>
|
||||||
<label className="flex items-start gap-3 text-sm text-gray-700">
|
<label className="flex items-start gap-3 text-sm text-gray-700">
|
||||||
<input
|
<input
|
||||||
@ -387,7 +387,7 @@ export default function CompanySignContractPage() {
|
|||||||
onChange={e => setConfirmSignature(e.target.checked)}
|
onChange={e => setConfirmSignature(e.target.checked)}
|
||||||
className="mt-1 h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
|
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>
|
<span>I am authorized to sign legally binding documents for this company.</span>
|
||||||
</label>
|
</label>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@ -398,7 +398,7 @@ export default function CompanySignContractPage() {
|
|||||||
)}
|
)}
|
||||||
{success && (
|
{success && (
|
||||||
<div className="mt-8 rounded-md border border-green-300 bg-green-50 px-4 py-3 text-sm text-green-700">
|
<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.
|
Contract signed successfully. Redirecting shortly…
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@ -408,7 +408,7 @@ export default function CompanySignContractPage() {
|
|||||||
disabled={submitting || success}
|
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"
|
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'}
|
{submitting ? 'Signing…' : success ? 'Signed' : 'Sign Now'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -73,13 +73,13 @@ export default function PersonalSignContractPage() {
|
|||||||
if (!valid()) {
|
if (!valid()) {
|
||||||
// Detailed error message to help debug
|
// Detailed error message to help debug
|
||||||
const issues = []
|
const issues = []
|
||||||
if (fullName.trim().length < 3) issues.push('Vollständiger Name (mindestens 3 Zeichen)')
|
if (fullName.trim().length < 3) issues.push('Full name (min 3 characters)')
|
||||||
if (location.trim().length < 2) issues.push('Ort (mindestens 2 Zeichen)')
|
if (location.trim().length < 2) issues.push('Location (min 2 characters)')
|
||||||
if (!agreeContract) issues.push('Vertrag gelesen und verstanden')
|
if (!agreeContract) issues.push('Contract read and understood')
|
||||||
if (!agreeData) issues.push('Datenschutzerklärung zugestimmt')
|
if (!agreeData) issues.push('Privacy policy accepted')
|
||||||
if (!confirmSignature) issues.push('Elektronische Signatur bestätigt')
|
if (!confirmSignature) issues.push('Electronic signature confirmed')
|
||||||
|
|
||||||
setError(`Bitte vervollständigen: ${issues.join(', ')}`)
|
setError(`Please complete: ${issues.join(', ')}`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ export default function PersonalSignContractPage() {
|
|||||||
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('Contract signing error:', error)
|
console.error('Contract signing error:', error)
|
||||||
setError(error.message || 'Signatur fehlgeschlagen. Bitte erneut versuchen.')
|
setError(error.message || 'Signature failed. Please try again.')
|
||||||
} finally {
|
} finally {
|
||||||
setSubmitting(false)
|
setSubmitting(false)
|
||||||
}
|
}
|
||||||
@ -184,7 +184,7 @@ export default function PersonalSignContractPage() {
|
|||||||
Sign Personal Participation Contract
|
Sign Personal Participation Contract
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-center text-sm text-gray-600 mb-8">
|
<p className="text-center text-sm text-gray-600 mb-8">
|
||||||
Bitte überprüfe die Vertragsdetails und unterschreibe elektronisch.
|
Please review the contract details and sign electronically.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{/* Contract Meta + Preview */}
|
{/* Contract Meta + Preview */}
|
||||||
@ -194,22 +194,22 @@ export default function PersonalSignContractPage() {
|
|||||||
<h2 className="text-sm font-semibold text-gray-800 mb-3">Contract Information</h2>
|
<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">
|
<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">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">Version:</span> 1.2 (valid from 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">Jurisdiction:</span> EU / Germany</li>
|
||||||
<li><span className="font-medium text-gray-700">Language:</span> DE (verbindlich)</li>
|
<li><span className="font-medium text-gray-700">Language:</span> EN (binding)</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div className="rounded-lg border border-indigo-100 bg-indigo-50/60 p-5">
|
<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>
|
<h3 className="text-sm font-semibold text-indigo-900 mb-2">Note</h3>
|
||||||
<p className="text-xs sm:text-sm text-indigo-800 leading-relaxed">
|
<p className="text-xs sm:text-sm text-indigo-800 leading-relaxed">
|
||||||
Deine elektronische Signatur ist rechtsverbindlich. Stelle sicher, dass alle Angaben korrekt sind.
|
Your electronic signature is legally binding. Please ensure all details are correct.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="rounded-lg border border-gray-200 bg-white relative overflow-hidden">
|
<div className="rounded-lg border border-gray-200 bg-white relative overflow-hidden">
|
||||||
<div className="flex items-center justify-between p-3 border-b border-gray-200 bg-gray-50">
|
<div className="flex items-center justify-between p-3 border-b border-gray-200 bg-gray-50">
|
||||||
<h3 className="text-sm font-semibold text-gray-900">Vertragsvorschau</h3>
|
<h3 className="text-sm font-semibold text-gray-900">Contract Preview</h3>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@ -227,13 +227,13 @@ export default function PersonalSignContractPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{previewLoading ? (
|
{previewLoading ? (
|
||||||
<div className="h-72 flex items-center justify-center text-xs text-gray-500">Lade Vorschau…</div>
|
<div className="h-72 flex items-center justify-center text-xs text-gray-500">Loading preview…</div>
|
||||||
) : previewError ? (
|
) : previewError ? (
|
||||||
<div className="h-72 flex items-center justify-center text-xs text-red-600 px-4 text-center">{previewError}</div>
|
<div className="h-72 flex items-center justify-center text-xs text-red-600 px-4 text-center">{previewError}</div>
|
||||||
) : previewHtml ? (
|
) : previewHtml ? (
|
||||||
<iframe title="Contract Preview" className="w-full h-72" srcDoc={previewHtml} />
|
<iframe title="Contract Preview" className="w-full h-72" srcDoc={previewHtml} />
|
||||||
) : (
|
) : (
|
||||||
<div className="h-72 flex items-center justify-center text-xs text-gray-500">Keine Vorschau verfügbar.</div>
|
<div className="h-72 flex items-center justify-center text-xs text-gray-500">No preview available.</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -247,7 +247,7 @@ export default function PersonalSignContractPage() {
|
|||||||
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
|
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
|
||||||
<div className="sm:col-span-2 lg:col-span-2">
|
<div className="sm:col-span-2 lg:col-span-2">
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
Vollständiger Name (Signatur) *
|
Full Name (Signature) *
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
value={fullName}
|
value={fullName}
|
||||||
@ -257,12 +257,12 @@ export default function PersonalSignContractPage() {
|
|||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<p className="mt-1 text-xs text-gray-500">
|
<p className="mt-1 text-xs text-gray-500">
|
||||||
Muss deinem amtlichen Ausweis entsprechen.
|
Must match your official ID.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
Datum *
|
Date *
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
@ -274,7 +274,7 @@ export default function PersonalSignContractPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
Ort *
|
Location *
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
value={location}
|
value={location}
|
||||||
@ -286,7 +286,7 @@ export default function PersonalSignContractPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="sm:col-span-2 lg:col-span-3">
|
<div className="sm:col-span-2 lg:col-span-3">
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
Notiz (optional)
|
Note (optional)
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
value={note}
|
value={note}
|
||||||
@ -302,7 +302,7 @@ export default function PersonalSignContractPage() {
|
|||||||
|
|
||||||
{/* Confirmations */}
|
{/* Confirmations */}
|
||||||
<section className="space-y-5">
|
<section className="space-y-5">
|
||||||
<h2 className="text-sm font-semibold text-[#0F2460]">Bestätigungen</h2>
|
<h2 className="text-sm font-semibold text-[#0F2460]">Confirmations</h2>
|
||||||
<label className="flex items-start gap-3 text-sm text-gray-700">
|
<label className="flex items-start gap-3 text-sm text-gray-700">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@ -310,7 +310,7 @@ export default function PersonalSignContractPage() {
|
|||||||
onChange={e => setAgreeContract(e.target.checked)}
|
onChange={e => setAgreeContract(e.target.checked)}
|
||||||
className="mt-1 h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
|
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>
|
<span>I confirm that I have read and understood the contract in full.</span>
|
||||||
</label>
|
</label>
|
||||||
<label className="flex items-start gap-3 text-sm text-gray-700">
|
<label className="flex items-start gap-3 text-sm text-gray-700">
|
||||||
<input
|
<input
|
||||||
@ -319,7 +319,7 @@ export default function PersonalSignContractPage() {
|
|||||||
onChange={e => setAgreeData(e.target.checked)}
|
onChange={e => setAgreeData(e.target.checked)}
|
||||||
className="mt-1 h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
|
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>
|
<span>I consent to the processing of my personal data in accordance with the privacy policy.</span>
|
||||||
</label>
|
</label>
|
||||||
<label className="flex items-start gap-3 text-sm text-gray-700">
|
<label className="flex items-start gap-3 text-sm text-gray-700">
|
||||||
<input
|
<input
|
||||||
@ -328,7 +328,7 @@ export default function PersonalSignContractPage() {
|
|||||||
onChange={e => setConfirmSignature(e.target.checked)}
|
onChange={e => setConfirmSignature(e.target.checked)}
|
||||||
className="mt-1 h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
|
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>
|
<span>I confirm this electronic signature is legally binding and equivalent to a handwritten signature.</span>
|
||||||
</label>
|
</label>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@ -339,7 +339,7 @@ export default function PersonalSignContractPage() {
|
|||||||
)}
|
)}
|
||||||
{success && (
|
{success && (
|
||||||
<div className="mt-8 rounded-md border border-green-300 bg-green-50 px-4 py-3 text-sm text-green-700">
|
<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.
|
Contract signed successfully. Redirecting shortly…
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@ -349,7 +349,7 @@ export default function PersonalSignContractPage() {
|
|||||||
disabled={submitting || success}
|
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"
|
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'}
|
{submitting ? 'Signing…' : success ? 'Signed' : 'Sign Now'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -274,7 +274,7 @@ export default function CompanyIdUploadPage() {
|
|||||||
)}
|
)}
|
||||||
{success && (
|
{success && (
|
||||||
<div className="mt-6 rounded-md border border-green-300 bg-green-50 px-4 py-3 text-sm text-green-700">
|
<div className="mt-6 rounded-md border border-green-300 bg-green-50 px-4 py-3 text-sm text-green-700">
|
||||||
Documents uploaded successfully.
|
Documents uploaded successfully. Redirecting shortly…
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@ -285,7 +285,7 @@ export default function PersonalIdUploadPage() {
|
|||||||
)}
|
)}
|
||||||
{success && (
|
{success && (
|
||||||
<div className="mt-6 rounded-md border border-green-300 bg-green-50 px-4 py-3 text-sm text-green-700">
|
<div className="mt-6 rounded-md border border-green-300 bg-green-50 px-4 py-3 text-sm text-green-700">
|
||||||
Upload saved successfully.
|
Upload saved successfully. Redirecting shortly…
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user