You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
96 lines
2.7 KiB
96 lines
2.7 KiB
/**
|
|
* 发布岗位 hook:拉取表单、更新字段、预估质量、发布岗位。
|
|
*/
|
|
import { useCallback, useEffect, useState } from 'react';
|
|
import { estimateJobQuality, fetchJobPublishForm, publishJob } from '../api';
|
|
import type { JobPublishFormData, JobQualityEstimate } from '../types';
|
|
import { useAsyncData } from './useAsyncData';
|
|
|
|
export function useJobPublish() {
|
|
const fetcher = useCallback(() => fetchJobPublishForm(), []);
|
|
const { data, loading, error, refresh } = useAsyncData<JobPublishFormData>(fetcher);
|
|
|
|
const [form, setForm] = useState<JobPublishFormData | null>(null);
|
|
const [estimate, setEstimate] = useState<JobQualityEstimate | null>(null);
|
|
const [estimating, setEstimating] = useState(false);
|
|
const [publishing, setPublishing] = useState(false);
|
|
|
|
useEffect(() => {
|
|
if (data && !form) {
|
|
setForm(data);
|
|
}
|
|
}, [data, form]);
|
|
|
|
const updateField = useCallback(<K extends keyof JobPublishFormData>(
|
|
field: K,
|
|
value: JobPublishFormData[K],
|
|
) => {
|
|
setForm((prev) => (prev ? { ...prev, [field]: value } : prev));
|
|
}, []);
|
|
|
|
const updateStringField = useCallback((field: keyof JobPublishFormData, value: string) => {
|
|
setForm((prev) => (prev ? { ...prev, [field]: value } : prev));
|
|
}, []);
|
|
|
|
const updateNumberField = useCallback((field: keyof JobPublishFormData, value: string) => {
|
|
setForm((prev) => (prev ? { ...prev, [field]: Number(value) || 0 } : prev));
|
|
}, []);
|
|
|
|
const toggleBenefit = useCallback((benefit: string) => {
|
|
setForm((prev) => {
|
|
if (!prev) return prev;
|
|
const benefits = prev.benefits.includes(benefit)
|
|
? prev.benefits.filter((b) => b !== benefit)
|
|
: [...prev.benefits, benefit];
|
|
return { ...prev, benefits };
|
|
});
|
|
}, []);
|
|
|
|
const toggleSkill = useCallback((skill: string) => {
|
|
setForm((prev) => {
|
|
if (!prev) return prev;
|
|
const skills = prev.skills.includes(skill)
|
|
? prev.skills.filter((s) => s !== skill)
|
|
: [...prev.skills, skill];
|
|
return { ...prev, skills };
|
|
});
|
|
}, []);
|
|
|
|
const runEstimate = useCallback(async () => {
|
|
if (!form) return;
|
|
setEstimating(true);
|
|
try {
|
|
const result = await estimateJobQuality(form);
|
|
setEstimate(result);
|
|
} finally {
|
|
setEstimating(false);
|
|
}
|
|
}, [form]);
|
|
|
|
const publish = useCallback(async () => {
|
|
if (!form) return null;
|
|
setPublishing(true);
|
|
try {
|
|
return await publishJob(form);
|
|
} finally {
|
|
setPublishing(false);
|
|
}
|
|
}, [form]);
|
|
|
|
return {
|
|
form,
|
|
loading,
|
|
error,
|
|
refresh,
|
|
updateField,
|
|
updateStringField,
|
|
updateNumberField,
|
|
toggleBenefit,
|
|
toggleSkill,
|
|
estimate,
|
|
estimating,
|
|
runEstimate,
|
|
publishing,
|
|
publish,
|
|
};
|
|
}
|
|
|