Spaces:
Sleeping
Sleeping
Download frontend/src/api/client.js from habib-analyst/email-agent-api: direct link, hf CLI and curl.
- Browser
- Download file 4.27 kB
-
https://huggingface.co/spaces/habib-analyst/email-agent-api/resolve/main/frontend/src/api/client.js
- Command line
-
hf download hf://spaces/habib-analyst/email-agent-api/frontend/src/api/client.js
-
curl -L -o client.js https://huggingface.co/spaces/habib-analyst/email-agent-api/resolve/main/frontend/src/api/client.js
4.27 kB
| import axios from "axios"; | |
| const api = axios.create({ | |
| baseURL: import.meta.env.VITE_API_URL || "https://habib-analyst-email-agent-api.hf.space/api", | |
| headers: { "Content-Type": "application/json" }, | |
| timeout: 180000, | |
| }); | |
| // βββ Token Management ββββββββββββββββββββββββββββββββββββββββββββββ | |
| let _token = null; | |
| export function setAuthToken(token) { | |
| _token = token; | |
| if (token) { | |
| sessionStorage.setItem("session_token", token); | |
| } else { | |
| sessionStorage.removeItem("session_token"); | |
| } | |
| } | |
| export function getAuthToken() { | |
| if (!_token) { | |
| _token = sessionStorage.getItem("session_token"); | |
| } | |
| return _token; | |
| } | |
| export function clearAuthToken() { | |
| _token = null; | |
| sessionStorage.removeItem("session_token"); | |
| } | |
| // βββ Attach JWT to every request βββββββββββββββββββββββββββββββββββ | |
| api.interceptors.request.use((config) => { | |
| const token = getAuthToken(); | |
| if (token) { | |
| config.headers.Authorization = `Bearer ${token}`; | |
| } | |
| return config; | |
| }); | |
| // βββ Handle 401 responses globally βββββββββββββββββββββββββββββββββ | |
| api.interceptors.response.use( | |
| (response) => response, | |
| (error) => { | |
| if (error.response?.status === 401) { | |
| // Don't redirect if we're already on auth routes | |
| const url = error.config?.url || ""; | |
| if (!url.includes("/auth/") && !url.includes("/admin/login")) { | |
| clearAuthToken(); | |
| // Dispatch a custom event so AuthContext can react | |
| window.dispatchEvent(new CustomEvent("auth:expired")); | |
| } | |
| } | |
| return Promise.reject(error); | |
| } | |
| ); | |
| export const authAPI = { | |
| getStatus: () => api.get("/auth/status"), | |
| startAuth: () => api.get("/auth/gmail"), | |
| disconnect: () => api.post("/auth/disconnect"), | |
| }; | |
| export const adminAPI = { | |
| login: (email, password) => api.post("/admin/login", { email, password }), | |
| getStats: () => api.get("/admin/stats"), | |
| getUsers: () => api.get("/admin/users"), | |
| userAction: (email, action) => api.post("/admin/users/action", { email, action }), | |
| }; | |
| export const quotaAPI = { | |
| getStatus: () => api.get("/quota/status"), | |
| checkDuplicate: (recipientEmail) => api.get(`/quota/check-duplicate/${recipientEmail}`), | |
| }; | |
| export const emailAPI = { | |
| loadTemplate: () => api.post("/email/load-template"), | |
| applyTemplate: (recipientInput) => | |
| api.post("/email/apply-template", { professor_input: recipientInput }), | |
| verify: (toEmail, subject, htmlBody) => | |
| api.post("/email/verify", { to_email: toEmail, subject, html_body: htmlBody }), | |
| send: (toEmail, subject, htmlBody) => | |
| api.post("/email/send", { to_email: toEmail, subject, html_body: htmlBody }), | |
| getAttachments: () => api.get("/email/attachments"), | |
| uploadAttachment: (file) => { | |
| const form = new FormData(); | |
| form.append("file", file); | |
| return api.post("/email/attachments/upload", form, { | |
| headers: { "Content-Type": "multipart/form-data" }, | |
| }); | |
| }, | |
| deleteAttachment: (filename) => api.delete(`/email/attachments/${filename}`), | |
| contactSales: (data) => api.post("/email/contact-sales", data), | |
| }; | |
| export const batchAPI = { | |
| uploadCSV: (file) => { | |
| const form = new FormData(); | |
| form.append("file", file); | |
| return api.post("/batch/upload-csv", form, { | |
| headers: { "Content-Type": "multipart/form-data" }, | |
| }); | |
| }, | |
| extractEmails: (text) => | |
| api.post("/batch/extract-emails", { text }), | |
| scrapeFaculty: (url) => | |
| api.post("/batch/scrape-faculty", { url }, { timeout: 120000 }), | |
| start: (recipientList, mode = "manual", delayMin = 15, delayMax = 45) => | |
| api.post("/batch/start", { | |
| professor_list: recipientList, | |
| mode, | |
| delay_min: delayMin, | |
| delay_max: delayMax, | |
| }), | |
| getQueue: () => api.get("/batch/queue"), | |
| generate: (index) => api.post(`/batch/generate/${index}`), | |
| send: (index) => api.post(`/batch/send/${index}`), | |
| skip: (index) => api.post(`/batch/skip/${index}`), | |
| autoRun: () => api.post("/batch/auto-run", {}, { timeout: 3600000 }), | |
| stop: () => api.post("/batch/stop"), | |
| clear: () => api.post("/batch/clear"), | |
| }; | |
| export default api; | |