2025-08-19 22:35:01 +08:00
|
|
|
import { useState, useEffect } from "react";
|
2025-08-15 16:16:41 +08:00
|
|
|
import { useNavigate } from "react-router-dom";
|
2025-08-19 22:35:01 +08:00
|
|
|
import { jobAPI, interviewAPI, studentAPI } from "@/services/api";
|
|
|
|
|
import { mapJobList, mapInterviewList } from "@/utils/dataMapper";
|
2025-08-15 16:16:41 +08:00
|
|
|
import JobList from "./components/JobList";
|
|
|
|
|
|
|
|
|
|
import "./index.css";
|
|
|
|
|
|
|
|
|
|
const CompanyJobsPage = () => {
|
2025-08-19 22:35:01 +08:00
|
|
|
const [jobs, setJobs] = useState([]);
|
|
|
|
|
const [interviews, setInterviews] = useState([]);
|
|
|
|
|
const [loading, setLoading] = useState(true);
|
2025-08-15 16:16:41 +08:00
|
|
|
const [isExpand, setIsExpand] = useState(false); // 是否展开
|
|
|
|
|
|
|
|
|
|
const navigate = useNavigate();
|
|
|
|
|
|
2025-08-19 22:35:01 +08:00
|
|
|
useEffect(() => {
|
|
|
|
|
fetchData();
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
const fetchData = async () => {
|
|
|
|
|
try {
|
|
|
|
|
setLoading(true);
|
2025-08-20 10:40:22 +08:00
|
|
|
|
2025-08-19 22:35:01 +08:00
|
|
|
// Get current user's student ID from API
|
|
|
|
|
let studentId = null;
|
|
|
|
|
try {
|
|
|
|
|
const currentStudent = await studentAPI.getCurrentStudent();
|
|
|
|
|
studentId = currentStudent?.id;
|
|
|
|
|
} catch (err) {
|
2025-08-20 10:40:22 +08:00
|
|
|
console.log("Could not get current student:", err);
|
2025-08-19 22:35:01 +08:00
|
|
|
}
|
2025-08-20 10:40:22 +08:00
|
|
|
|
2025-08-19 22:35:01 +08:00
|
|
|
// Fetch jobs (and interviews if we have a student ID)
|
2025-08-20 10:40:22 +08:00
|
|
|
const jobsData = await jobAPI.getList({
|
|
|
|
|
page: 1,
|
|
|
|
|
pageSize: 10,
|
|
|
|
|
isActive: true,
|
2025-08-19 22:35:01 +08:00
|
|
|
});
|
2025-08-20 10:40:22 +08:00
|
|
|
|
2025-08-19 22:35:01 +08:00
|
|
|
let interviewsData = { data: [] };
|
|
|
|
|
if (studentId) {
|
|
|
|
|
try {
|
2025-08-20 10:40:22 +08:00
|
|
|
interviewsData = await interviewAPI.getList({
|
2025-08-19 22:35:01 +08:00
|
|
|
studentId: studentId,
|
2025-08-20 10:40:22 +08:00
|
|
|
status: "SCHEDULED",
|
2025-08-19 22:35:01 +08:00
|
|
|
});
|
|
|
|
|
} catch (err) {
|
2025-08-20 10:40:22 +08:00
|
|
|
console.log("No interviews found or API error");
|
2025-08-19 22:35:01 +08:00
|
|
|
}
|
|
|
|
|
}
|
2025-08-20 10:40:22 +08:00
|
|
|
|
2025-08-19 22:35:01 +08:00
|
|
|
// Map data to frontend format
|
|
|
|
|
const mappedJobs = mapJobList(jobsData.data || jobsData);
|
2025-08-20 10:40:22 +08:00
|
|
|
const mappedInterviews = mapInterviewList(
|
|
|
|
|
interviewsData.data || interviewsData
|
|
|
|
|
);
|
|
|
|
|
|
2025-08-19 22:35:01 +08:00
|
|
|
setJobs(mappedJobs);
|
|
|
|
|
setInterviews(mappedInterviews);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("Failed to fetch data:", error);
|
|
|
|
|
// Fallback to empty data
|
|
|
|
|
setJobs([]);
|
|
|
|
|
setInterviews([]);
|
|
|
|
|
} finally {
|
|
|
|
|
setLoading(false);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2025-08-15 16:16:41 +08:00
|
|
|
const handleJobWrapperClick = () => {
|
|
|
|
|
navigate("/company-jobs-list");
|
|
|
|
|
};
|
|
|
|
|
|
2025-08-19 22:35:01 +08:00
|
|
|
if (loading) {
|
|
|
|
|
return (
|
|
|
|
|
<div className="company-jobs-page-wrapper">
|
2025-08-20 10:40:22 +08:00
|
|
|
<div
|
|
|
|
|
className="company-jobs-page"
|
|
|
|
|
style={{ justifyContent: "center", alignItems: "center" }}
|
|
|
|
|
>
|
2025-08-19 22:35:01 +08:00
|
|
|
<p>加载中...</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-15 16:16:41 +08:00
|
|
|
return (
|
|
|
|
|
<div className="company-jobs-page-wrapper">
|
|
|
|
|
<div className="company-jobs-page">
|
|
|
|
|
<div className="company-jobs-page-left" onClick={handleJobWrapperClick}>
|
|
|
|
|
<p className="company-jobs-page-title">企业内推岗位库</p>
|
|
|
|
|
<div className="company-jobs-page-left-list-wrapper">
|
2025-08-20 10:40:22 +08:00
|
|
|
<JobList data={jobs} backgroundColor="#F7F8FA" />
|
2025-08-15 16:16:41 +08:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="company-jobs-page-interview-wrapper">
|
|
|
|
|
<div
|
|
|
|
|
className={`${
|
|
|
|
|
isExpand
|
|
|
|
|
? "company-jobs-page-interview"
|
|
|
|
|
: "company-jobs-page-interview company-jobs-page-interview-expand"
|
|
|
|
|
}`}
|
|
|
|
|
>
|
|
|
|
|
<p className="company-jobs-page-title">内推岗位面试</p>
|
|
|
|
|
<ul className="company-jobs-page-interview-list">
|
2025-08-20 10:40:22 +08:00
|
|
|
{interviews.length > 0 ? (
|
|
|
|
|
interviews.map((item) => (
|
|
|
|
|
<li
|
|
|
|
|
className="company-jobs-page-interview-item"
|
|
|
|
|
key={item.id}
|
|
|
|
|
>
|
|
|
|
|
<div className="company-jobs-page-interview-item-info">
|
|
|
|
|
<p className="company-jobs-page-interview-item-info-position">
|
|
|
|
|
{item.position}
|
|
|
|
|
</p>
|
|
|
|
|
{item.job?.tags?.length > 0 ? (
|
|
|
|
|
<ul className="company-jobs-page-interview-item-info-tags">
|
|
|
|
|
{item.job.tags.map((tag) => (
|
|
|
|
|
<li
|
|
|
|
|
className="company-jobs-page-interview-item-info-tag"
|
|
|
|
|
key={tag}
|
|
|
|
|
>
|
|
|
|
|
{tag}
|
|
|
|
|
</li>
|
|
|
|
|
))}
|
|
|
|
|
</ul>
|
|
|
|
|
) : null}
|
|
|
|
|
<span className="company-jobs-page-interview-item-info-salary">
|
|
|
|
|
{item.job?.salary || "面议"}
|
|
|
|
|
</span>
|
2025-08-15 16:16:41 +08:00
|
|
|
</div>
|
2025-08-20 10:40:22 +08:00
|
|
|
<div className="company-jobs-page-interview-item-btn-wrapper">
|
|
|
|
|
<span>{item.interviewTime}</span>
|
|
|
|
|
<div
|
|
|
|
|
className={`company-jobs-page-interview-item-btn ${
|
|
|
|
|
item.status !== "COMPLETED" &&
|
|
|
|
|
"company-jobs-page-interview-item-btn-active"
|
|
|
|
|
}`}
|
|
|
|
|
>
|
|
|
|
|
{item.statusText}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</li>
|
|
|
|
|
))
|
|
|
|
|
) : (
|
2025-08-19 22:35:01 +08:00
|
|
|
<li className="company-jobs-page-interview-item">
|
2025-08-20 10:40:22 +08:00
|
|
|
<p
|
|
|
|
|
style={{
|
|
|
|
|
color: "#999",
|
|
|
|
|
textAlign: "center",
|
|
|
|
|
width: "100%",
|
|
|
|
|
}}
|
|
|
|
|
>
|
2025-08-19 22:35:01 +08:00
|
|
|
暂无面试安排
|
|
|
|
|
</p>
|
|
|
|
|
</li>
|
|
|
|
|
)}
|
2025-08-15 16:16:41 +08:00
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
className={
|
|
|
|
|
isExpand
|
|
|
|
|
? "company-jobs-page-process-wrapper-expand"
|
|
|
|
|
: "company-jobs-page-process-wrapper-close"
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
<div
|
|
|
|
|
className="company-jobs-page-process-wrapper-title"
|
|
|
|
|
onClick={() => setIsExpand(!isExpand)}
|
|
|
|
|
>
|
|
|
|
|
岗位陪跑流程
|
|
|
|
|
</div>
|
|
|
|
|
<div className="company-jobs-page-process-content">
|
|
|
|
|
<div className="company-jobs-page-process-item-icon icon1">
|
|
|
|
|
<p>内推岗位简历投递</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="company-jobs-page-process-item-round-dot icon2" />
|
|
|
|
|
<div className="company-jobs-page-process-item-icon icon3">
|
|
|
|
|
<p>岗位简历接收</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="company-jobs-page-process-item-icon icon4">
|
|
|
|
|
<p>面试时间地点确定</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="company-jobs-page-process-item-icon icon5">
|
|
|
|
|
<p>参与企业面试</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="company-jobs-page-process-item-round-dot icon6" />
|
|
|
|
|
<div className="company-jobs-page-process-item-icon icon7">
|
|
|
|
|
<p>企业offer发送</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default CompanyJobsPage;
|