'use client' import { useState, useMemo, useRef, useEffect, useCallback } from 'react' import { useRouter } from 'next/navigation' import PageLayout from '../../../components/PageLayout' import useAuthStore from '../../../store/authStore' import { useUserStatus } from '../../../hooks/useUserStatus' import { useToast } from '../../../components/toast/toastComponent' import { ChevronDownIcon } from '@heroicons/react/20/solid' // NEW interface CompanyProfileData { companyName: string vatNumber: string street: string postalCode: string city: string country: string accountHolder: string iban: string bic: string secondPhone: string emergencyName: string emergencyPhone: string } // Common countries list const COUNTRIES = [ 'Germany', 'Austria', 'Switzerland', 'Italy', 'France', 'Spain', 'Portugal', 'Netherlands', 'Belgium', 'Poland', 'Czech Republic', 'Hungary', 'Croatia', 'Slovenia', 'Slovakia', 'United Kingdom', 'Ireland', 'Sweden', 'Norway', 'Denmark', 'Finland', 'Russia', 'Turkey', 'Greece', 'Romania', 'Bulgaria', 'Serbia', 'Albania', 'Bosnia and Herzegovina', 'United States', 'Canada', 'Brazil', 'Argentina', 'Mexico', 'China', 'Japan', 'India', 'Pakistan', 'Australia', 'South Africa', 'Other' ] const init: CompanyProfileData = { companyName: '', vatNumber: '', street: '', postalCode: '', city: '', country: '', accountHolder: '', iban: '', bic: '', secondPhone: '', emergencyName: '', emergencyPhone: '' } function ModernSelect({ label, placeholder = 'Select…', value, onChange, options, }: { label: string placeholder?: string value: string onChange: (next: string) => void options: { value: string; label: string }[] }) { const [open, setOpen] = useState(false) const [query, setQuery] = useState('') const btnRef = useRef(null) const [pos, setPos] = useState({ left: 16, top: 0, width: 320 }) const selected = useMemo(() => options.find(o => o.value === value) || null, [options, value]) const filtered = useMemo(() => { const q = query.trim().toLowerCase() if (!q) return options return options.filter(o => o.label.toLowerCase().includes(q)) }, [options, query]) useEffect(() => { if (!open) return const update = () => { const el = btnRef.current if (!el) return const r = el.getBoundingClientRect() const padding = 16 const width = Math.min(r.width, window.innerWidth - padding * 2) const left = Math.max(padding, Math.min(r.left, window.innerWidth - width - padding)) const top = r.bottom + 8 setPos({ left, top, width }) } update() window.addEventListener('resize', update) window.addEventListener('scroll', update, true) return () => { window.removeEventListener('resize', update) window.removeEventListener('scroll', update, true) } }, [open]) useEffect(() => { if (!open) return const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') setOpen(false) } window.addEventListener('keydown', onKey) return () => window.removeEventListener('keydown', onKey) }, [open]) return (
{open && ( <>
setOpen(false)} aria-hidden />
setQuery(e.target.value)} placeholder="Search…" className="w-full rounded-lg border border-gray-200 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[#8D6B1D] focus:border-transparent" autoFocus />
{filtered.length === 0 ? (
No results
) : ( filtered.map(o => { const active = o.value === value return ( ) }) )}
)}
) } export default function CompanyAdditionalInformationPage() { const router = useRouter() const user = useAuthStore(s => s.user) // NEW const isAuthReady = useAuthStore(s => (s as any).isAuthReady) // NEW const { accessToken } = useAuthStore() const { userStatus, loading: statusLoading, refreshStatus } = useUserStatus() const { showToast } = useToast() const [form, setForm] = useState(init) const [loading, setLoading] = useState(false) const [success, setSuccess] = useState(false) const [error, setError] = useState('') // NEW: smooth redirect const [redirectTo, setRedirectTo] = useState(null) const redirectOnceRef = useRef(false) const smoothReplace = useCallback((to: string) => { if (redirectOnceRef.current) return redirectOnceRef.current = true setRedirectTo(to) window.setTimeout(() => router.replace(to), 200) }, [router]) // NEW: hard block if step already done OR all steps done useEffect(() => { if (statusLoading || !userStatus) return const allDone = !!userStatus.email_verified && !!userStatus.documents_uploaded && !!userStatus.profile_completed && !!userStatus.contract_signed if (allDone) { smoothReplace('/dashboard') // CHANGED } else if (userStatus.profile_completed) { smoothReplace('/quickaction-dashboard') // CHANGED } }, [statusLoading, userStatus, smoothReplace]) // NEW: must be logged in useEffect(() => { if (!isAuthReady) return if (!user || !accessToken) smoothReplace('/login') }, [isAuthReady, user, accessToken, smoothReplace]) const handleChange = (e: React.ChangeEvent) => { const { name, value } = e.target setForm(p => ({ ...p, [name]: value })) setError('') } const validate = () => { const required: (keyof CompanyProfileData)[] = [ 'companyName','vatNumber','street','postalCode','city','country','accountHolder','iban' ] for (const k of required) { if (!form[k].trim()) { const msg = 'Bitte alle Pflichtfelder ausfüllen.' setError(msg) showToast({ variant: 'error', title: 'Missing information', message: msg, }) return false } } if (!/^([A-Z]{2}\d{2}[A-Z0-9]{10,30})$/i.test(form.iban.replace(/\s+/g,''))) { const msg = 'Ungültige IBAN.' setError(msg) showToast({ variant: 'error', title: 'Invalid IBAN', message: msg, }) return false } setError('') return true } const submit = async (e: React.FormEvent) => { e.preventDefault() if (loading || success) return if (!validate()) return if (!accessToken) { const msg = 'Not authenticated. Please log in again.' setError(msg) showToast({ variant: 'error', title: 'Authentication error', message: msg, }) return } setLoading(true) try { // Prepare data for backend with correct field names const profileData = { address: form.street, // Backend expects 'address', not nested object zip_code: form.postalCode, // Backend expects 'zip_code' city: form.city, country: form.country, registrationNumber: form.vatNumber, // Map VAT number to registration number businessType: 'company', // Default business type branch: null, // Not collected in form, set to null numberOfEmployees: null, // Not collected in form, set to null accountHolderName: form.accountHolder, // Backend expects 'accountHolderName' iban: form.iban.replace(/\s+/g, '') // Remove spaces from IBAN } const response = await fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}/api/profile/company/complete`, { method: 'POST', headers: { 'Authorization': `Bearer ${accessToken}`, 'Content-Type': 'application/json' }, body: JSON.stringify(profileData) }) if (!response.ok) { const errorData = await response.json().catch(() => ({ message: 'Save failed' })) throw new Error(errorData.message || 'Save failed') } setSuccess(true) showToast({ variant: 'success', title: 'Profile saved', message: 'Your company profile has been saved successfully.', }) // Refresh user status to update profile completion state await refreshStatus() // Redirect to next step after short delay setTimeout(() => { // Check if we came from tutorial const urlParams = new URLSearchParams(window.location.search) const fromTutorial = urlParams.get('tutorial') === 'true' if (fromTutorial) { router.push('/quickaction-dashboard?tutorial=true') } else { router.push('/quickaction-dashboard/register-sign-contract/company') } }, 1500) } catch (error: any) { console.error('Company profile save error:', error) const msg = error.message || 'Speichern fehlgeschlagen.' setError(msg) showToast({ variant: 'error', title: 'Save failed', message: msg, }) } finally { setLoading(false) } } const setField = (name: keyof CompanyProfileData, value: string) => { setForm(p => ({ ...p, [name]: value })) setError('') } return ( {/* NEW: smooth redirect overlay */} {redirectTo && (
Redirecting…
Please wait
)}
{/* Animated background (same as dashboard) */}
{/* Soft gradient blobs */}
{/* Subtle radial highlight */}

Complete Company Profile

{/* Company Details */}

Company Details

setField('country', v)} options={COUNTRIES.map(c => ({ value: c, label: c }))} />

{/* Bank Details */}

Bank Details


{/* Additional Information */}

Additional Information

{error && (
{error}
)} {success && (
Data saved. Redirecting shortly…
)}
) }