Files
auditly/services/api.ts
Ra 1a9e92d7bd Implement comprehensive report system with detailed viewing and AI enhancements
- Add detailed report viewing with full-screen ReportDetail component for both company and employee reports
- Fix company wiki to display onboarding Q&A in card format matching Figma designs
- Exclude company owners from employee submission counts (owners contribute to wiki, not employee data)
- Fix employee report generation to include company context (wiki + company report + employee answers)
- Fix company report generation to use filtered employee submissions only
- Add proper error handling for submission data format variations
- Update Firebase functions to use gpt-4o model instead of deprecated gpt-4.1
- Fix UI syntax errors and improve report display functionality
- Add comprehensive logging for debugging report generation flow

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-18 19:08:29 -07:00

88 lines
2.9 KiB
TypeScript

import { API_URL } from '../constants';
// Get auth token from localStorage (persistent across sessions)
const getAuthToken = (): string | null => {
return localStorage.getItem('auditly_auth_token');
};
// Make authenticated API call
export const makeAuthenticatedRequest = async (
endpoint: string,
options: RequestInit = {},
orgId?: string
): Promise<Response> => {
const token = getAuthToken();
if (!token) {
throw new Error('No authentication token found. Please log in again.');
}
const headers = new Headers(options.headers);
headers.set('Authorization', `Bearer ${token}`);
headers.set('Content-Type', 'application/json');
// Add orgId to request body if provided and it's a POST/PUT request
let body = options.body;
if (orgId && (options.method === 'POST' || options.method === 'PUT')) {
if (typeof body === 'string') {
try {
const parsedBody = JSON.parse(body);
parsedBody.orgId = orgId;
body = JSON.stringify(parsedBody);
} catch (e) {
// If body isn't JSON, create a new object
body = JSON.stringify({ orgId, data: body });
}
} else if (body instanceof FormData) {
body.append('orgId', orgId);
} else if (body && typeof body === 'object') {
body = JSON.stringify({ orgId, ...body });
} else {
body = JSON.stringify({ orgId });
}
}
const url = endpoint.startsWith('http') ? endpoint : `${API_URL}${endpoint}`;
// Add timeout to prevent hanging forever
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 second timeout
try {
const response = await fetch(url, {
...options,
headers,
body,
signal: controller.signal,
});
clearTimeout(timeoutId);
return response;
} catch (error) {
clearTimeout(timeoutId);
if (error.name === 'AbortError') {
throw new Error('Request timeout: The server took too long to respond');
}
throw error;
}
};
// Convenience methods for different HTTP verbs
export const apiGet = (endpoint: string, orgId?: string) =>
makeAuthenticatedRequest(endpoint, { method: 'GET' }, orgId);
export const apiPost = (endpoint: string, data: any = {}, orgId?: string) => {
console.log('apiPost called with:', { endpoint, data, orgId, hasToken: !!getAuthToken() });
return makeAuthenticatedRequest(endpoint, {
method: 'POST',
body: JSON.stringify(data)
}, orgId);
};
export const apiPut = (endpoint: string, data: any = {}, orgId?: string) =>
makeAuthenticatedRequest(endpoint, {
method: 'PUT',
body: JSON.stringify(data)
}, orgId);
export const apiDelete = (endpoint: string, orgId?: string) =>
makeAuthenticatedRequest(endpoint, { method: 'DELETE' }, orgId);