profit-planet-frontend/src/app/quickaction-dashboard/register-upload-id/personal/hooks/usePersonalUploadId.ts

166 lines
4.6 KiB
TypeScript

'use client'
import { useState, useRef, useCallback, useEffect } from 'react'
import useAuthStore from '../../../../store/authStore'
import { useUserStatus } from '../../../../hooks/useUserStatus'
export function usePersonalUploadId() {
// Auth and status
const token = useAuthStore(s => s.accessToken)
const { refreshStatus } = useUserStatus()
// Form state
const [idNumber, setIdNumber] = useState('')
const [idType, setIdType] = useState('')
const [expiry, setExpiry] = useState('')
const [hasBack, setHasBack] = useState(true)
// Files + previews
const [frontFile, setFrontFile] = useState<File | null>(null)
const [backFile, setBackFile] = useState<File | null>(null)
const [frontPreview, setFrontPreview] = useState<string | null>(null)
const [backPreview, setBackPreview] = useState<string | null>(null)
// UI state
const [submitting, setSubmitting] = useState(false)
const [error, setError] = useState('')
const [success, setSuccess] = useState(false)
// Refs
const frontInputRef = useRef<HTMLInputElement | null>(null)
const backInputRef = useRef<HTMLInputElement | null>(null)
// Shared 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 = (f: File, side: 'front' | 'back') => {
if (f.size > 10 * 1024 * 1024) {
setError('File size exceeds 10 MB.')
return
}
setError('')
side === 'front' ? setFrontFile(f) : setBackFile(f)
}
const onDrop = (e: React.DragEvent, side: 'front' | 'back') => {
e.preventDefault()
const f = e.dataTransfer.files?.[0]
if (f) handleFile(f, side)
}
const clearFile = (side: 'front' | 'back') => {
side === 'front' ? setFrontFile(null) : setBackFile(null)
}
const dropEvents = {
onDragOver: (e: React.DragEvent) => e.preventDefault(),
onDragEnter: (e: React.DragEvent) => e.preventDefault(),
}
const openPicker = useCallback((side: 'front' | 'back') => {
(side === 'front' ? frontInputRef.current : backInputRef.current)?.click()
}, [])
// Previews
useEffect(() => {
if (!frontFile) { setFrontPreview(null); return }
const url = URL.createObjectURL(frontFile)
setFrontPreview(url)
return () => URL.revokeObjectURL(url)
}, [frontFile])
useEffect(() => {
if (!backFile) { setBackPreview(null); return }
const url = URL.createObjectURL(backFile)
setBackPreview(url)
return () => URL.revokeObjectURL(url)
}, [backFile])
// Validation
const validate = () => {
if (!idNumber.trim() || !idType || !expiry) {
setError('Please fill out all required fields.')
return false
}
if (!frontFile) {
setError('Please upload the front side.')
return false
}
if (hasBack && !backFile) {
setError('Please upload the back side or disable the switch.')
return false
}
setError('')
return true
}
// Submit
const submit = async (e: React.FormEvent) => {
e.preventDefault()
if (!validate()) return
if (!token) {
setError('Not authenticated. Please log in again.')
return
}
setSubmitting(true)
setError('')
try {
const formData = new FormData()
if (frontFile) formData.append('front', frontFile)
if (hasBack && backFile) formData.append('back', backFile)
formData.append('idType', idType)
formData.append('idNumber', idNumber)
formData.append('expiryDate', expiry)
const response = await fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}/api/upload/personal-id`, {
method: 'POST',
headers: { 'Authorization': `Bearer ${token}` },
body: formData
})
const data = await response.json().catch(() => ({}))
if (response.ok && data.success) {
setSuccess(true)
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 {
window.location.href = '/quickaction-dashboard'
}
}, 2000)
} else {
setError(data.message || 'Upload failed. Please try again.')
}
} catch (err) {
console.error('Upload error:', err)
setError('Network error. Please try again.')
} finally {
setSubmitting(false)
}
}
return {
// values
idNumber, idType, expiry, hasBack,
frontFile, backFile,
frontPreview, backPreview,
submitting, error, success,
frontInputRef, backInputRef,
inputBase,
// setters
setIdNumber, setIdType, setExpiry, setHasBack,
// handlers
handleFile, onDrop, clearFile, dropEvents, openPicker, submit,
}
}