Files
shop-front/src/app/jobs/components/Resume.tsx
T
hamid zarghami 9ffb33f335 jobs and resume
2025-10-06 10:15:10 +03:30

254 lines
10 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import DefaulModal from '@/components/DefaulModal'
import { Button } from '@/components/ui/button'
import { useState, type FC, useEffect } from 'react'
import { useForm } from 'react-hook-form'
import { ResumeType } from '../types/Types'
import { useGetJobs } from '../hooks/useJobsData'
import { useMutation } from '@tanstack/react-query'
import * as api from '../service/JobsService'
import { toast } from '@/components/Toast'
import Input from '@/components/Input'
import DatePickerComponent from '@/components/DatePicker'
import Select from '@/components/Select'
import { DocumentUpload, CloseCircle } from 'iconsax-react'
import { extractErrorMessage } from '@/helpers/errorUtils'
interface ResumeProps {
jobId?: string
}
const Resume: FC<ResumeProps> = ({ jobId }) => {
const [open, setOpen] = useState<boolean>(false)
const [selectedFile, setSelectedFile] = useState<File | null>(null)
const [filePreview, setFilePreview] = useState<string>('')
const { data: jobsData } = useGetJobs()
const { register, handleSubmit, formState: { errors }, setValue, watch, reset } = useForm<ResumeType>()
const jobs = jobsData?.results?.jobs || []
const jobOptions = jobs.map(job => ({
label: job.title,
value: job._id
}))
const watchedJob = watch('job')
useEffect(() => {
if (jobId) {
setValue('job', jobId)
}
}, [jobId, setValue])
const uploadFileMutation = useMutation({
mutationFn: api.uploadSingleFile,
onSuccess: (data) => {
setValue('resumeUrl', data?.results?.url?.url)
toast('فایل با موفقیت آپلود شد', 'success')
},
onError: () => {
toast('خطا در آپلود فایل', 'error')
setSelectedFile(null)
setFilePreview('')
}
})
const sendResumeMutation = useMutation({
mutationFn: api.sendResume,
onSuccess: () => {
toast('رزومه شما با موفقیت ارسال شد', 'success')
setOpen(false)
reset()
setSelectedFile(null)
setFilePreview('')
},
onError: (error) => {
toast(extractErrorMessage(error), 'error')
}
})
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0]
if (file) {
// بررسی نوع فایل
if (!file.type.includes('pdf') && !file.type.includes('word') && !file.type.includes('document')) {
toast('لطفا فایل PDF یا Word انتخاب کنید', 'error')
return
}
// بررسی اندازه فایل (حداکثر 5MB)
if (file.size > 5 * 1024 * 1024) {
toast('حجم فایل نباید بیشتر از ۵ مگابایت باشد', 'error')
return
}
setSelectedFile(file)
setFilePreview(file.name)
// آپلود فایل
uploadFileMutation.mutate(file)
}
}
const removeFile = () => {
setSelectedFile(null)
setFilePreview('')
setValue('resumeUrl', '')
}
const onSubmit = (data: ResumeType) => {
if (!selectedFile) {
toast('لطفا فایل رزومه را انتخاب کنید', 'error')
return
}
if (!data.resumeUrl) {
toast('لطفا منتظر تکمیل آپلود فایل باشید', 'error')
return
}
sendResumeMutation.mutate(data)
}
return (
<div>
<Button onClick={() => setOpen(!open)} size={'sm'}>
ارسال رزومه
</Button>
<DefaulModal
open={open}
close={() => setOpen(false)}
title_header='ارسال رزومه'
isHeader
>
<form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
{/* انتخاب شغل */}
<Select
placeholder="انتخاب شغل"
items={jobOptions}
value={watchedJob}
name="job"
onChange={(e) => setValue('job', e.target.value)}
error_text={errors.job?.message}
disabled={!!jobId}
/>
{/* نام کامل */}
<Input
label="نام کامل"
placeholder="نام کامل خود را وارد کنید"
{...register('fullName', { required: 'نام کامل الزامی است' })}
error_text={errors.fullName?.message}
/>
{/* نام پدر */}
<Input
label="نام پدر"
placeholder="نام پدر خود را وارد کنید"
{...register('fatherName', { required: 'نام پدر الزامی است' })}
error_text={errors.fatherName?.message}
/>
{/* محل تولد */}
<Input
label="محل تولد"
placeholder="محل تولد خود را وارد کنید"
{...register('placeOfBirth', { required: 'محل تولد الزامی است' })}
error_text={errors.placeOfBirth?.message}
/>
{/* تاریخ تولد */}
<DatePickerComponent
label="تاریخ تولد"
placeholder="تاریخ تولد را انتخاب کنید"
onChange={(date) => setValue('birthday', date)}
error_text={errors.birthday?.message}
/>
{/* آپلود فایل رزومه */}
<div className="w-full">
<label className="text-sm text-black block mb-2">
فایل رزومه (PDF یا Word)
</label>
{!selectedFile ? (
<div className="relative">
<input
type="file"
accept=".pdf,.doc,.docx"
onChange={handleFileChange}
className="absolute inset-0 w-full h-full opacity-0 cursor-pointer"
id="resume-file"
disabled={uploadFileMutation.isPending}
/>
<label
htmlFor="resume-file"
className="flex items-center justify-center w-full h-32 border-2 border-dashed border-gray-300 rounded-xl cursor-pointer hover:border-gray-400 transition-colors"
>
<div className="text-center">
<DocumentUpload color='gray' size={32} className="mx-auto text-gray-400 mb-2" />
<p className="text-sm text-gray-600">
فایل رزومه خود را اینجا رها کنید یا کلیک کنید
</p>
<p className="text-xs text-gray-400 mt-1">
PDF یا Word (حداکثر ۵ مگابایت)
</p>
</div>
</label>
</div>
) : (
<div className="flex items-center justify-between p-3 bg-gray-50 rounded-xl border">
<div className="flex items-center gap-2">
<DocumentUpload color='gray' size={20} className="text-gray-600" />
<span className="text-sm text-gray-700 truncate">
{filePreview}
</span>
{uploadFileMutation.isPending && (
<span className="text-xs text-blue-600">در حال آپلود...</span>
)}
</div>
<button
type="button"
onClick={removeFile}
disabled={uploadFileMutation.isPending}
className="text-red-500 hover:text-red-700 disabled:opacity-50"
>
<CloseCircle color='red' size={20} />
</button>
</div>
)}
{errors.resumeUrl && (
<div className="text-xs text-red-500 mt-1">
{errors.resumeUrl.message}
</div>
)}
</div>
{/* دکمه‌های اقدام */}
<div className="flex gap-3 pt-4">
<Button
type="button"
variant="outline"
onClick={() => setOpen(false)}
className="flex-1"
>
انصراف
</Button>
<Button
type="submit"
disabled={sendResumeMutation.isPending || uploadFileMutation.isPending || !watch('resumeUrl')}
className="flex-1"
>
{sendResumeMutation.isPending ? 'در حال ارسال...' :
uploadFileMutation.isPending ? 'در حال آپلود فایل...' : 'ارسال رزومه'}
</Button>
</div>
</form>
</DefaulModal>
</div>
)
}
export default Resume