feat(admin): fixed job listing
This commit is contained in:
@@ -66,10 +66,30 @@ function NewJobForm({ companies }: { companies: { id: number; name: string }[] }
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
async function handleSubmit(formData: FormData) {
|
async function handleSubmit(data: JobFormData) {
|
||||||
setError(null)
|
setError(null)
|
||||||
setSuccess(false)
|
setSuccess(false)
|
||||||
startTransition(async () => {
|
startTransition(async () => {
|
||||||
|
// Convert React Hook Form data to FormData for the server action
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('companyId', String(data.companyId))
|
||||||
|
formData.append('title', data.title)
|
||||||
|
formData.append('link', data.link)
|
||||||
|
formData.append('description', data.description)
|
||||||
|
formData.append('location', data.location)
|
||||||
|
formData.append('imageURL', data.imageURL || '')
|
||||||
|
formData.append('salary', data.salary)
|
||||||
|
// Convert Date to ISO string for the server
|
||||||
|
const deadline = data.applicationDeadline instanceof Date
|
||||||
|
? data.applicationDeadline.toISOString().slice(0, 10)
|
||||||
|
: new Date(data.applicationDeadline).toISOString().slice(0, 10)
|
||||||
|
formData.append('applicationDeadline', deadline)
|
||||||
|
formData.append('minCGPA', String(data.minCGPA))
|
||||||
|
formData.append('minSSC', String(data.minSSC))
|
||||||
|
formData.append('minHSC', String(data.minHSC))
|
||||||
|
formData.append('allowDeadKT', String(data.allowDeadKT))
|
||||||
|
formData.append('allowLiveKT', String(data.allowLiveKT))
|
||||||
|
|
||||||
const result = await createJob(formData)
|
const result = await createJob(formData)
|
||||||
if (result?.success) {
|
if (result?.success) {
|
||||||
setSuccess(true)
|
setSuccess(true)
|
||||||
@@ -128,7 +148,7 @@ function NewJobForm({ companies }: { companies: { id: number; name: string }[] }
|
|||||||
<Card className="shadow-xl border-0 bg-white/80 backdrop-blur-sm">
|
<Card className="shadow-xl border-0 bg-white/80 backdrop-blur-sm">
|
||||||
<CardContent className="p-8">
|
<CardContent className="p-8">
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form action={handleSubmit} className="space-y-8">
|
<form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-8">
|
||||||
{/* Success/Error Messages */}
|
{/* Success/Error Messages */}
|
||||||
{success && (
|
{success && (
|
||||||
<Alert className="border-green-200 bg-green-50">
|
<Alert className="border-green-200 bg-green-50">
|
||||||
@@ -319,25 +339,24 @@ function NewJobForm({ companies }: { companies: { id: number; name: string }[] }
|
|||||||
control={form.control}
|
control={form.control}
|
||||||
name="applicationDeadline"
|
name="applicationDeadline"
|
||||||
render={({ field }) => {
|
render={({ field }) => {
|
||||||
const getDisplayDate = (value: string) => {
|
const getDisplayDate = (value: Date | string) => {
|
||||||
if (!value) return ""
|
if (!value) return ""
|
||||||
try {
|
try {
|
||||||
return format(new Date(value), "PPP")
|
const date = value instanceof Date ? value : new Date(value)
|
||||||
|
return format(date, "PPP")
|
||||||
} catch {
|
} catch {
|
||||||
return value
|
return ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectedDate = field.value ? new Date(field.value) : undefined
|
const selectedDate = field.value ? (field.value instanceof Date ? field.value : new Date(field.value)) : undefined
|
||||||
|
|
||||||
const handleSelect = (date: Date | undefined) => {
|
const handleSelect = (date: Date | undefined) => {
|
||||||
setTimeout(() => {
|
if (date) {
|
||||||
if (date) {
|
field.onChange(date)
|
||||||
field.onChange(date.toISOString().slice(0, 10))
|
} else {
|
||||||
} else {
|
field.onChange(new Date())
|
||||||
field.onChange("")
|
}
|
||||||
}
|
|
||||||
}, 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -354,9 +373,7 @@ function NewJobForm({ companies }: { companies: { id: number; name: string }[] }
|
|||||||
)}
|
)}
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
{getDisplayDate(typeof field.value === "string" ? field.value : "") || (
|
{field.value ? getDisplayDate(field.value) : <span>Pick a date</span>}
|
||||||
<span>Pick a date</span>
|
|
||||||
)}
|
|
||||||
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
|
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
|
||||||
</Button>
|
</Button>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@@ -367,7 +384,6 @@ function NewJobForm({ companies }: { companies: { id: number; name: string }[] }
|
|||||||
selected={selectedDate}
|
selected={selectedDate}
|
||||||
onSelect={handleSelect}
|
onSelect={handleSelect}
|
||||||
captionLayout="dropdown"
|
captionLayout="dropdown"
|
||||||
key={typeof field.value === "string" ? field.value : "empty"}
|
|
||||||
/>
|
/>
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
</Popover>
|
</Popover>
|
||||||
@@ -445,7 +461,15 @@ function NewJobForm({ companies }: { companies: { id: number; name: string }[] }
|
|||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel className="text-sm font-medium text-gray-700">Minimum CGPA</FormLabel>
|
<FormLabel className="text-sm font-medium text-gray-700">Minimum CGPA</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input type="number" step="0.01" placeholder="0.00" {...field} className="h-11" />
|
<Input
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
placeholder="0.00"
|
||||||
|
{...field}
|
||||||
|
value={field.value?.toString() || ''}
|
||||||
|
onChange={(e) => field.onChange(e.target.value ? parseFloat(e.target.value) : 0)}
|
||||||
|
className="h-11"
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
@@ -459,7 +483,15 @@ function NewJobForm({ companies }: { companies: { id: number; name: string }[] }
|
|||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel className="text-sm font-medium text-gray-700">Minimum SSC %</FormLabel>
|
<FormLabel className="text-sm font-medium text-gray-700">Minimum SSC %</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input type="number" step="0.01" placeholder="0.00" {...field} className="h-11" />
|
<Input
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
placeholder="0.00"
|
||||||
|
{...field}
|
||||||
|
value={field.value?.toString() || ''}
|
||||||
|
onChange={(e) => field.onChange(e.target.value ? parseFloat(e.target.value) : 0)}
|
||||||
|
className="h-11"
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
@@ -473,7 +505,15 @@ function NewJobForm({ companies }: { companies: { id: number; name: string }[] }
|
|||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel className="text-sm font-medium text-gray-700">Minimum HSC %</FormLabel>
|
<FormLabel className="text-sm font-medium text-gray-700">Minimum HSC %</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input type="number" step="0.01" placeholder="0.00" {...field} className="h-11" />
|
<Input
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
placeholder="0.00"
|
||||||
|
{...field}
|
||||||
|
value={field.value?.toString() || ''}
|
||||||
|
onChange={(e) => field.onChange(e.target.value ? parseFloat(e.target.value) : 0)}
|
||||||
|
className="h-11"
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ export const jobSchema = z.object({
|
|||||||
link: z.string().url('Invalid URL'),
|
link: z.string().url('Invalid URL'),
|
||||||
description: z.string().min(1, 'Description is required'),
|
description: z.string().min(1, 'Description is required'),
|
||||||
location: z.string().min(1, 'Location is required'),
|
location: z.string().min(1, 'Location is required'),
|
||||||
imageURL: z.string().url('Invalid URL'),
|
imageURL: z.string().url('Invalid URL').or(z.literal('')).optional(),
|
||||||
salary: z.string().min(1, 'Salary is required'),
|
salary: z.string().min(1, 'Salary is required'),
|
||||||
applicationDeadline: z.date(),
|
applicationDeadline: z.date(),
|
||||||
minCGPA: z.number().min(0),
|
minCGPA: z.coerce.number().min(0, 'Minimum CGPA must be 0 or greater'),
|
||||||
minSSC: z.number().min(0),
|
minSSC: z.coerce.number().min(0, 'Minimum SSC must be 0 or greater'),
|
||||||
minHSC: z.number().min(0),
|
minHSC: z.coerce.number().min(0, 'Minimum HSC must be 0 or greater'),
|
||||||
allowDeadKT: z.boolean(),
|
allowDeadKT: z.boolean(),
|
||||||
allowLiveKT: z.boolean(),
|
allowLiveKT: z.boolean(),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -684,7 +684,7 @@ export default function ProfilePage() {
|
|||||||
<SelectValue placeholder="Select branch" />
|
<SelectValue placeholder="Select branch" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value="Computer Science">Computer Science</SelectItem>
|
<SelectItem value="Computer Engineering">Computer Engineering</SelectItem>
|
||||||
<SelectItem value="Information Technology">Information Technology</SelectItem>
|
<SelectItem value="Information Technology">Information Technology</SelectItem>
|
||||||
<SelectItem value="Electronics & Communication">Electronics & Communication</SelectItem>
|
<SelectItem value="Electronics & Communication">Electronics & Communication</SelectItem>
|
||||||
<SelectItem value="Mechanical Engineering">Mechanical Engineering</SelectItem>
|
<SelectItem value="Mechanical Engineering">Mechanical Engineering</SelectItem>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export default function AcademicDetailsStep({ form }: { form: any }) {
|
|||||||
];
|
];
|
||||||
|
|
||||||
const branchOptions = [
|
const branchOptions = [
|
||||||
{ value: 'cse', label: 'Computer Science' },
|
{ value: 'cse', label: 'Computer Engineering' },
|
||||||
{ value: 'it', label: 'Information Technology' },
|
{ value: 'it', label: 'Information Technology' },
|
||||||
{ value: 'ece', label: 'Electronics & Communication' },
|
{ value: 'ece', label: 'Electronics & Communication' },
|
||||||
{ value: 'mechanical', label: 'Mechanical' },
|
{ value: 'mechanical', label: 'Mechanical' },
|
||||||
|
|||||||
Reference in New Issue
Block a user