Mr-Haseeb786
Clean deployment build
88da18c
Raw
History Blame Contribute Delete
6.49 kB
import axios, { AxiosError } from "axios";
import type { Job, SearchFilters, GeneratedCV } from "@/types";
const API_BASE = import.meta.env.VITE_API_URL || "";
const api = axios.create({
baseURL: API_BASE,
headers: {
"Content-Type": "application/json",
},
});
// Request interceptor to add auth headers if needed
api.interceptors.request.use((config) => {
return config;
});
// Response interceptor for error handling
api.interceptors.response.use(
(response) => response,
(error: AxiosError) => {
console.error("API Error:", error.response?.data || error.message);
return Promise.reject(error);
}
);
export const jobsAPI = {
// Load runtime app config/settings
async getConfig(): Promise<{
tailoring_mode: "local" | "api";
llm_provider: "ollama" | "groq" | "grok" | "openai";
enable_professional_summary: boolean;
include_cover_letters: boolean;
}> {
const response = await api.get("/api/config");
return response.data;
},
// Save user profile for the Auto-Apply Extension
async saveUserProfile(profileData: {
first_name: string;
last_name: string;
email: string;
phone: string;
linkedin: string;
github: string;
}): Promise<{ success: boolean; message?: string }> {
const response = await api.post("/api/user-profile", profileData);
return response.data;
},
// Run deep semantic analysis for a specific job
evaluateJobFit: async (
jobId: string
): Promise<{
success: boolean;
match_score?: number;
matched_skills?: string[];
missing_skills?: string[];
error?: string;
}> => {
const response = await api.post("/api/evaluate-fit", { job_id: jobId });
return response.data;
},
// Save runtime app settings
async saveSettings(payload: {
tailoring_mode: "local" | "api";
llm_provider: "ollama" | "groq" | "grok" | "openai";
enable_professional_summary: boolean;
include_cover_letters: boolean;
}): Promise<{ success: boolean; settings: unknown }> {
const response = await api.post("/api/settings", payload);
return response.data;
},
// Search for jobs
async searchJobs(
filters: SearchFilters
): Promise<{ jobs: Job[]; excel_file: string }> {
const response = await api.post("/api/search", {
keyword: filters.keyword,
location: filters.location,
max_jobs: filters.maxJobs,
max_days_old: filters.maxDaysOld || 30,
});
return {
jobs: response.data.jobs || [],
excel_file: response.data.excel_file || "",
};
},
// Fast Search using Apify
async searchJobsApify(
filters: SearchFilters
): Promise<{ jobs: Job[]; json_file: string }> {
const response = await api.post("/api/apify-search", {
keyword: filters.keyword,
location: filters.location,
max_jobs: filters.maxJobs,
max_days_old: filters.maxDaysOld || 30,
});
return {
jobs: response.data.jobs || [],
json_file: response.data.json_file || "",
};
},
// Upload CV template
async uploadCV(file: File): Promise<{ success: boolean; message: string }> {
const formData = new FormData();
formData.append("file", file);
const response = await api.post("/api/upload-cv", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
});
return response.data;
},
// Get jobs list
async getJobsList(): Promise<Job[]> {
const response = await api.get("/api/jobs");
return response.data.jobs || [];
},
// Generate CV for single job
async generateCV(jobId: string): Promise<{
success: boolean;
filename: string;
url: string;
job?: Job; // <--- Temporary
cover_letter_filename?: string;
cover_letter_url?: string;
}> {
const response = await api.post(`/api/generate-cv/${jobId}`);
const coverLetterFilename =
response.data.cover_letter_filename || undefined;
return {
success: response.data.success,
filename: response.data.filename,
url: `/api/download/${encodeURIComponent(response.data.filename)}`,
job: response.data.job, // <--- Temporary
cover_letter_filename: coverLetterFilename,
cover_letter_url: coverLetterFilename
? `/api/download/${encodeURIComponent(coverLetterFilename)}`
: undefined,
};
},
// Generate CVs for all selected jobs
async generateAllCVs(jobIds?: string[]): Promise<{
success: boolean;
successful: GeneratedCV[];
failed: Array<{ jobId: string; error: string }>;
zip_filename: string;
}> {
// Updated the IDs of each job to represent actual IDs and avoid duplicated scrapes and Stop converting UUID strings into Numbers!
const jobIndices = jobIds || [];
const response = await api.post("/api/generate-all-cvs", {
job_indices: jobIndices,
});
const successful: GeneratedCV[] = (response.data.successful || []).map(
(cv: any) => ({
jobId: String(cv.job_index),
jobTitle: cv.job_title || "",
company: cv.company || "",
filename: cv.filename,
url: `/api/download/${encodeURIComponent(cv.filename)}`,
coverLetterFilename: cv.cover_letter_filename || undefined,
coverLetterUrl: cv.cover_letter_filename
? `/api/download/${encodeURIComponent(cv.cover_letter_filename)}`
: undefined,
generatedAt: new Date().toISOString(),
status: "success",
})
);
const failed = (response.data.failed || []).map((item: any) => ({
jobId: String(item.job_index),
error: item.error || "Unknown error",
}));
return {
success: response.data.success,
successful,
failed,
zip_filename: response.data.zip_filename,
};
},
// Download file
async downloadFile(filename: string): Promise<Blob> {
const encodedFilename = encodeURIComponent(filename);
const response = await api.get(`/api/download/${encodedFilename}`, {
responseType: "blob",
});
return response.data;
},
// Get batch progress (for real-time updates)
async getBatchProgress(): Promise<{
completed: number;
total: number;
current_job?: string;
failed: number;
}> {
return {
completed: 0,
total: 0,
failed: 0,
current_job: undefined,
};
},
// Health check
async healthCheck(): Promise<{ status: string }> {
const response = await api.get("/api/health");
return response.data;
},
};
export default api;