profit-planet-frontend/src/app/quickaction-dashboard/register-upload-id/company/hooks/useCompanyUploadId.ts
2026-01-13 13:58:28 +01:00

191 lines
5.4 KiB
TypeScript

'use client'
import { useState, useRef, useEffect, useCallback } from 'react'
import useAuthStore from '../../../../store/authStore'
import { useUserStatus } from '../../../../hooks/useUserStatus'
import { useToast } from '../../../../components/toast/toastComponent'
export function useCompanyUploadId() {
// Auth + status
const { accessToken } = useAuthStore()
const { refreshStatus } = useUserStatus()
const { showToast } = useToast()
// Form state
const [idNumber, setIdNumber] = useState('')
const [idType, setIdType] = useState('')
const [expiryDate, setExpiryDate] = useState('')
const [hasBack, setHasBack] = useState(true)
// Files + previews
const [frontFile, setFrontFile] = useState<File | null>(null)
const [extraFile, setExtraFile] = useState<File | null>(null)
const [frontPreview, setFrontPreview] = useState<string | null>(null)
const [extraPreview, setExtraPreview] = useState<string | null>(null)
// UI state
const [submitting, setSubmitting] = useState(false)
const [error, setError] = useState('')
const [success, setSuccess] = useState(false)
// Refs
const frontRef = useRef<HTMLInputElement | null>(null)
const extraRef = useRef<HTMLInputElement | null>(null)
// Unified input style
const inputBase =
'w-full h-11 rounded-lg border border-gray-300 px-4 text-sm text-gray-900 placeholder:text-gray-900 placeholder:opacity-100 focus:ring-2 focus:ring-indigo-500 focus:border-transparent bg-white'
// File handlers
const handleFile = (file: File, which: 'front' | 'extra') => {
if (file.size > 10 * 1024 * 1024) {
const msg = 'File size exceeds 10 MB.'
setError(msg)
showToast({
variant: 'error',
title: 'File too large',
message: msg,
})
return
}
setError('')
which === 'front' ? setFrontFile(file) : setExtraFile(file)
}
const onDrop = (e: React.DragEvent, which: 'front' | 'extra') => {
e.preventDefault()
const f = e.dataTransfer.files?.[0]
if (f) handleFile(f, which)
}
const clearFile = (which: 'front' | 'extra') => {
which === 'front' ? setFrontFile(null) : setExtraFile(null)
}
const dropHandlers = {
onDragOver: (e: React.DragEvent) => e.preventDefault(),
onDragEnter: (e: React.DragEvent) => e.preventDefault(),
}
const openPicker = useCallback((which: 'front' | 'extra') => {
(which === 'front' ? frontRef.current : extraRef.current)?.click()
}, [])
// Previews (images only)
useEffect(() => {
if (!frontFile || !frontFile.type?.startsWith('image/')) { setFrontPreview(null); return }
const url = URL.createObjectURL(frontFile)
setFrontPreview(url)
return () => URL.revokeObjectURL(url)
}, [frontFile])
useEffect(() => {
if (!extraFile || !extraFile.type?.startsWith('image/')) { setExtraPreview(null); return }
const url = URL.createObjectURL(extraFile)
setExtraPreview(url)
return () => URL.revokeObjectURL(url)
}, [extraFile])
// Validation
const validate = () => {
if (!idNumber.trim() || !idType || !expiryDate || !frontFile) {
const msg = 'Please complete all required fields (marked with *).'
setError(msg)
showToast({
variant: 'error',
title: 'Missing information',
message: msg,
})
return false
}
setError('')
return true
}
// Submit
const submit = async (e: React.FormEvent) => {
e.preventDefault()
if (!validate()) return
if (!accessToken) {
const msg = 'Not authenticated. Please log in again.'
setError(msg)
showToast({
variant: 'error',
title: 'Authentication error',
message: msg,
})
return
}
setSubmitting(true)
setError('')
try {
const formData = new FormData()
if (frontFile) formData.append('front', frontFile)
if (hasBack && extraFile) formData.append('back', extraFile)
formData.append('idType', idType)
formData.append('idNumber', idNumber.trim())
formData.append('expiryDate', expiryDate)
const response = await fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}/api/upload/company-id`, {
method: 'POST',
headers: { 'Authorization': `Bearer ${accessToken}` },
body: formData,
})
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Upload failed' }))
const msg = errorData.message || 'Upload failed'
throw new Error(msg)
}
setSuccess(true)
showToast({
variant: 'success',
title: 'Documents uploaded',
message: 'Your company ID documents have been uploaded successfully.',
})
await refreshStatus()
setTimeout(() => {
// Check if we came from tutorial
const urlParams = new URLSearchParams(window.location.search)
const fromTutorial = urlParams.get('tutorial') === 'true'
if (fromTutorial) {
window.location.href = '/quickaction-dashboard?tutorial=true'
} else {
// keep same redirect as page used before
window.location.href = '/quickaction-dashboard/register-additional-information'
}
}, 1500)
} catch (err: any) {
console.error('Company ID upload error:', err)
const msg = err?.message || 'Upload failed.'
setError(msg)
showToast({
variant: 'error',
title: 'Upload failed',
message: msg,
})
} finally {
setSubmitting(false)
}
}
return {
// values
idNumber, idType, expiryDate, hasBack,
frontFile, extraFile,
frontPreview, extraPreview,
submitting, error, success,
frontRef, extraRef,
inputBase,
// setters
setIdNumber, setIdType, setExpiryDate, setHasBack, setExtraFile,
// handlers
handleFile, onDrop, clearFile, dropHandlers, openPicker, submit,
}
}