File size: 4,046 Bytes
7f6dd09 d061a75 7f6dd09 26159c8 7f6dd09 702b8ab 7f6dd09 d061a75 7f6dd09 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | import axios from "axios";
const configuredBaseUrl = import.meta.env.VITE_API_URL?.trim();
const BASE_URL = configuredBaseUrl || "";
const api = axios.create({ baseURL: BASE_URL, timeout: 30000 });
api.interceptors.response.use(
(response) => response,
(error) => {
const message =
error.response?.data?.error || error.message || "Request failed";
return Promise.reject(new Error(message));
},
);
export async function login(email, password) {
const res = await api.post("/api/auth/login", { email, password });
return res.data;
}
export async function signup(email, password) {
const res = await api.post("/api/auth/signup", { email, password });
return res.data;
}
export async function logout() {
const res = await api.post("/api/auth/logout");
return res.data;
}
export async function createJob(companyName, userEmail) {
const res = await api.post("/api/jobs", {
company_name: companyName,
user_email: userEmail,
});
return res.data;
}
export async function uploadFiles(jobId, formData) {
const res = await api.post("/api/upload/" + jobId, formData, {
headers: { "Content-Type": "multipart/form-data" },
timeout: 120000,
});
return res.data;
}
export async function getJobResult(jobId) {
const res = await api.get("/api/analysis/" + jobId + "/result");
return res.data;
}
export async function getJobStatus(jobId) {
const res = await api.get("/api/jobs/" + jobId + "/status");
return res.data;
}
export async function submitOfficerNotes(jobId, notes, officerId) {
const res = await api.post("/api/officer/" + jobId + "/notes", {
notes,
officer_id: officerId || "anonymous",
});
return res.data;
}
export async function getCAM(jobId) {
const res = await api.get("/api/cam/" + jobId);
return res.data;
}
export async function regenerateCAM(jobId) {
const res = await api.post("/api/cam/" + jobId + "/regenerate");
return res.data;
}
export async function downloadCAM(jobId, format) {
const res = await api.get(`/api/cam/${jobId}/download/${format}`, {
responseType: "blob",
timeout: 60000,
});
const mime =
format === "pdf"
? "application/pdf"
: "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
const blob = new Blob([res.data], { type: mime });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = `${jobId}_Credit_Memo.${format}`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
export async function getCAMPdfBlobUrl(jobId) {
const res = await api.get(`/api/cam/${jobId}/download/pdf?preview=true`, {
responseType: "blob",
timeout: 60000,
});
const blob = new Blob([res.data], { type: "application/pdf" });
return URL.createObjectURL(blob);
}
export async function listJobs() {
const res = await api.get("/api/jobs");
return res.data;
}
export function createSSEConnection(jobId, onEvent) {
const url = BASE_URL
? BASE_URL + "/api/analysis/" + jobId + "/stream"
: "/api/analysis/" + jobId + "/stream";
const source = new EventSource(url);
let connected = false;
let done = false;
source.onopen = () => {
connected = true;
};
source.onmessage = (e) => {
try {
const parsed = JSON.parse(e.data);
onEvent(parsed);
// If server sent complete or error, we're done — close cleanly
if (parsed.type === "complete" || parsed.type === "error") {
done = true;
source.close();
}
} catch (err) {
console.error("SSE parse error", err);
}
};
source.onerror = () => {
source.close();
// Don't fire error if we already received a terminal event
if (done) return;
onEvent({
type: "error",
stage: "SSE",
message: connected
? "Connection to pipeline lost. Please try again."
: "Unable to connect to analysis pipeline. Check that the backend is running.",
percent: 0,
});
};
return source;
}
|