// api.jsx - JSON bridge between the revamp UI and Laravel business logic const RevampApi = (() => { let csrf = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || null; const headers = (extra = {}) => ({ Accept: 'application/json', 'X-Requested-With': 'XMLHttpRequest', ...(csrf ? { 'X-CSRF-TOKEN': csrf } : {}), ...extra, }); const setCsrf = (token) => { if (token) csrf = token; }; const parseJson = async (response) => { const text = await response.text(); if (!text) return {}; try { return JSON.parse(text); } catch (error) { return { message: text }; } }; const request = async (path, options = {}) => { const hasBody = options.body !== undefined; const response = await fetch(path, { credentials: 'same-origin', ...options, headers: headers({ ...(hasBody ? { 'Content-Type': 'application/json' } : {}), ...(options.headers || {}), }), body: hasBody && typeof options.body !== 'string' ? JSON.stringify(options.body) : options.body, }); const payload = await parseJson(response); setCsrf(payload.csrf); if (!response.ok) { const error = new Error(payload.message || 'Die Anfrage ist fehlgeschlagen.'); error.status = response.status; error.payload = payload; throw error; } return payload; }; const api = (path) => `/revamp-api${path}`; return { session: () => request(api('/session')), bootstrap: () => request(api('/bootstrap')), login: (email, password, remember = true) => request(api('/login'), { method: 'POST', body: { email, password, remember }, }), register: (name, email, password) => request(api('/register'), { method: 'POST', body: { name, email, password }, }), logout: () => request(api('/logout'), { method: 'POST' }), locations: (query) => request(api(`/locations?q=${encodeURIComponent(query)}`)), createSearch: (data) => request(api('/searches'), { method: 'POST', body: data, }), updateSearch: (taskId, data) => request(api(`/searches/${taskId}`), { method: 'PATCH', body: data, }), toggleSearch: (taskId) => request(api(`/searches/${taskId}/toggle`), { method: 'PATCH' }), refreshSearch: (taskId) => request(api(`/searches/${taskId}/refresh`), { method: 'POST' }), deleteSearch: (taskId) => request(api(`/searches/${taskId}`), { method: 'DELETE' }), evaluateSearch: (taskId) => request(api(`/searches/${taskId}/evaluate`), { method: 'POST' }), exportSearchUrl: (taskId) => api(`/searches/${taskId}/export`), evaluateAd: (taskId, adId) => request(api(`/searches/${taskId}/ads/${adId}/evaluate`), { method: 'POST' }), scrapeAdDetails: (taskId, adId) => request(api(`/searches/${taskId}/ads/${adId}/scrape-details`), { method: 'POST' }), contactAd: (taskId, adId) => request(api(`/searches/${taskId}/ads/${adId}/contact`), { method: 'POST' }), inquiryPreview: (taskId, adId) => request(api(`/searches/${taskId}/ads/${adId}/inquiry-preview`)), toggleSharing: (taskId, adId) => request(api(`/searches/${taskId}/ads/${adId}/sharing`), { method: 'POST' }), setAdAction: (adId, actionType) => request(api('/ads/action'), { method: 'POST', body: { ad_id: adId, action_type: actionType }, }), removeAdAction: (adId) => request(api('/ads/action'), { method: 'DELETE', body: { ad_id: adId }, }), updateProfile: (data) => request(api('/profile'), { method: 'PATCH', body: data, }), updatePassword: (data) => request(api('/profile/password'), { method: 'PATCH', body: data, }), deleteProfile: (password) => request(api('/profile'), { method: 'DELETE', body: { password }, }), toggleExpertMode: () => request(api('/profile/expert-mode'), { method: 'POST' }), activateDebugMode: (code) => request(api('/profile/debug-mode'), { method: 'POST', body: { code }, }), investor: () => request(api('/investor')), investorCompare: (ids = []) => request(api(`/investor/compare?ids=${encodeURIComponent(ids.join(','))}`)), portfolioAnalytics: () => request(api('/portfolio/analytics')), portfolioExportUrl: () => api('/portfolio/export'), notificationSubscriptions: () => request(api('/notifications/subscriptions')), storePushSubscription: (subscription) => request(api('/notifications/store'), { method: 'POST', body: subscription, }), revokePushSubscription: (endpoint) => request(api('/notifications/revoke'), { method: 'POST', body: { endpoint }, }), revokeAllPushSubscriptions: () => request(api('/notifications/revoke-all'), { method: 'POST' }), sendTestNotification: () => request(api('/notifications/test'), { method: 'POST' }), adminJobs: () => request(api('/admin/jobs')), retryFailedJob: (id) => request(api(`/admin/jobs/failed/${id}/retry`), { method: 'POST' }), deleteFailedJob: (id) => request(api(`/admin/jobs/failed/${id}`), { method: 'DELETE' }), clearFailedJobs: () => request(api('/admin/jobs/failed'), { method: 'DELETE' }), setCsrf, }; })(); Object.assign(window, { RevampApi });