Spaces:
Sleeping
Sleeping
| import axios from 'axios'; | |
| import { API_BASE_URL } from '@/config'; | |
| import apiClient from '@/lib/api/axios-instance'; | |
| import { createHeaders } from '@/lib/api'; | |
| export interface Task { | |
| id: number; | |
| type: string; | |
| priority?: string; | |
| severity?: string; | |
| description: string; | |
| sprintName: string | null; | |
| estimates: string; | |
| esUnit: number | null; | |
| stateDate: string; | |
| endDate: string | null; | |
| assignedTo: number | null; | |
| remainingHr: number | null; | |
| status: string; | |
| issuesId: number | null; | |
| title: string; | |
| createdAt?: string; | |
| createdBy?: number | null; | |
| createdByName?: string; | |
| updatedAt?: string | null; | |
| updatedBy?: number | null; | |
| updatedByName?: string | null; | |
| taskCode?: string; | |
| version?: string; | |
| url?: string; | |
| stepsToReproduce?: string; | |
| inputs?: string; | |
| environment?: string; | |
| expectedBehavior?: string; | |
| actualBehavior?: string; | |
| resolution?: string; | |
| rootCause?: string; | |
| projectId?: number; | |
| projectName?: string; | |
| issueName?: string; | |
| deliverableName?: string; | |
| relatedUrl?: string; | |
| } | |
| export interface TaskCreateRequest { | |
| id?: number; | |
| type: string; | |
| priority?: string; | |
| severity?: string; | |
| description: string; | |
| sprintName: string | null; | |
| estimates: string; | |
| esUnit: number | null; | |
| stateDate: string; | |
| endDate: string | null; | |
| assignedTo: number | null; | |
| remainingHr: number | null; | |
| status: string; | |
| issuesId: number | null; | |
| title: string; | |
| taskCode?: string; | |
| version?: string; | |
| url?: string; | |
| stepsToReproduce?: string; | |
| inputs?: string; | |
| environment?: string; | |
| expectedBehavior?: string; | |
| actualBehavior?: string; | |
| resolution?: string; | |
| rootCause?: string; | |
| } | |
| export interface TaskUpdateRequest extends TaskCreateRequest { | |
| id: number; | |
| } | |
| // Helper to create a safe task object with default values for null/undefined fields | |
| const createSafeTask = (data: any): Task => { | |
| return { | |
| id: data.id || 0, | |
| title: data.title || '', | |
| description: data.description || '', | |
| type: data.type || 'Medium', | |
| status: data.status || 'New', | |
| sprintName: data.sprintName, | |
| estimates: data.estimates || '', | |
| esUnit: data.esUnit, | |
| stateDate: data.stateDate || new Date().toISOString().split('T')[0], | |
| endDate: data.endDate, | |
| assignedTo: data.assignedTo, | |
| remainingHr: data.remainingHr, | |
| issuesId: data.issuesId, | |
| createdAt: data.createdAt || new Date().toISOString(), // Default to current time if not provided | |
| createdBy: data.createdBy, | |
| createdByName: data.createdByName, | |
| updatedAt: data.updatedAt, | |
| updatedBy: data.updatedBy, | |
| updatedByName: data.updatedByName, | |
| taskCode: data.taskCode || '', | |
| version: data.version || '', | |
| url: data.url || '', | |
| stepsToReproduce: data.stepsToReproduce || '', | |
| inputs: data.inputs || '', | |
| environment: data.environment || '', | |
| expectedBehavior: data.expectedBehavior || '', | |
| actualBehavior: data.actualBehavior || '', | |
| resolution: data.resolution || '', | |
| rootCause: data.rootCause || '', | |
| priority: data.priority, | |
| severity: data.severity, | |
| projectId: data.projectId, | |
| projectName: data.projectName, | |
| issueName: data.issueName, | |
| deliverableName: data.deliverableName, | |
| relatedUrl: data.relatedUrl | |
| }; | |
| }; | |
| class TasksApi { | |
| private baseUrl = `/api/Tasks`; | |
| async getAll(): Promise<Task[]> { | |
| try { | |
| console.log('TasksApi: Fetching all tasks from', this.baseUrl); | |
| const response = await apiClient.get(this.baseUrl); | |
| console.log('TasksApi: Response status', response.status); | |
| if (!response.data) { | |
| console.warn('TasksApi: No data in response'); | |
| return []; | |
| } | |
| if (!Array.isArray(response.data)) { | |
| console.warn('TasksApi: Response is not an array', response.data); | |
| return []; | |
| } | |
| // Map each item to ensure it has all required fields | |
| return response.data.map(item => createSafeTask(item)); | |
| } catch (error) { | |
| console.error('Error fetching tasks:', error); | |
| // Return empty array instead of throwing to prevent UI crashes | |
| return []; | |
| } | |
| } | |
| async getByType(type: string): Promise<Task[]> { | |
| try { | |
| console.log(`TasksApi: Fetching tasks of type ${type}`); | |
| console.log(`TasksApi: Requesting from URL: ${this.baseUrl}/GetTaskByType?type=${type}`); | |
| const response = await apiClient.get(`${this.baseUrl}/GetTaskByType?type=${type}`); | |
| console.log('TasksApi: Response status:', response.status); | |
| console.log('TasksApi: Response headers:', response.headers); | |
| if (!response.data) { | |
| console.warn('TasksApi: No data in response'); | |
| return []; | |
| } | |
| // Log the raw response data | |
| console.log('TasksApi: Raw response data type:', typeof response.data); | |
| console.log('TasksApi: Raw response data sample:', | |
| Array.isArray(response.data) | |
| ? response.data.slice(0, 1) | |
| : response.data | |
| ); | |
| if (!Array.isArray(response.data)) { | |
| console.warn('TasksApi: Response is not an array', response.data); | |
| // Try to handle if the response is enclosed in another object | |
| if (response.data && typeof response.data === 'object' && response.data.items && Array.isArray(response.data.items)) { | |
| console.log('TasksApi: Found array in response.data.items'); | |
| response.data = response.data.items; | |
| } else { | |
| console.warn('TasksApi: Unable to extract array from response'); | |
| return []; | |
| } | |
| } | |
| console.log(`TasksApi: Found ${response.data.length} ${type} tasks`); | |
| // Map each item to ensure it has all required fields | |
| const mappedTasks = response.data.map(item => createSafeTask(item)); | |
| console.log(`TasksApi: Returning ${mappedTasks.length} mapped ${type} tasks`); | |
| if (mappedTasks.length > 0) { | |
| console.log('TasksApi: First mapped task sample:', mappedTasks[0]); | |
| } | |
| return mappedTasks; | |
| } catch (error) { | |
| console.error(`Error fetching tasks of type ${type}:`, error); | |
| // Return empty array instead of throwing to prevent UI crashes | |
| return []; | |
| } | |
| } | |
| async getById(id: number): Promise<Task | null> { | |
| try { | |
| const response = await apiClient.get(`${this.baseUrl}/${id}`); | |
| if (response.data) { | |
| return createSafeTask(response.data); | |
| } | |
| return null; | |
| } catch (error) { | |
| console.error(`Error fetching task ${id}:`, error); | |
| return null; | |
| } | |
| } | |
| async create(task: TaskCreateRequest): Promise<Task> { | |
| try { | |
| // Remove id if it's 0, undefined, or null | |
| const taskData = { ...task }; | |
| if (taskData.id === 0 || taskData.id === undefined || taskData.id === null) { | |
| delete taskData.id; | |
| } | |
| // Don't fill empty fields with default values | |
| // Instead, let null values pass through to the API | |
| // Only format dates that actually have values | |
| if (taskData.stateDate && typeof taskData.stateDate === 'string') { | |
| // Check if the date already has a time part | |
| if (!taskData.stateDate.includes('T')) { | |
| taskData.stateDate = taskData.stateDate + 'T12:00:00.000Z'; | |
| } | |
| } | |
| if (taskData.endDate && typeof taskData.endDate === 'string') { | |
| // Check if the date already has a time part | |
| if (!taskData.endDate.includes('T')) { | |
| taskData.endDate = taskData.endDate + 'T12:00:00.000Z'; | |
| } | |
| } | |
| console.log('TasksApi: Creating task with data', taskData); | |
| const response = await apiClient.post(this.baseUrl, taskData); | |
| console.log('TasksApi: Create response status', response.status); | |
| return createSafeTask(response.data); | |
| } catch (error) { | |
| console.error('Error creating task:', error); | |
| throw error; | |
| } | |
| } | |
| async update(id: number, task: TaskUpdateRequest): Promise<Task> { | |
| try { | |
| // Don't fill empty fields with default values | |
| // Instead, let null values pass through to the API | |
| const taskData = { ...task }; | |
| // Only format dates that actually have values | |
| if (taskData.stateDate && typeof taskData.stateDate === 'string') { | |
| // Check if the date already has a time part | |
| if (!taskData.stateDate.includes('T')) { | |
| taskData.stateDate = taskData.stateDate + 'T12:00:00.000Z'; | |
| } | |
| } | |
| if (taskData.endDate && typeof taskData.endDate === 'string') { | |
| // Check if the date already has a time part | |
| if (!taskData.endDate.includes('T')) { | |
| taskData.endDate = taskData.endDate + 'T12:00:00.000Z'; | |
| } | |
| } | |
| console.log(`TasksApi: Updating task ${id} with data`, taskData); | |
| const response = await apiClient.put(`${this.baseUrl}/${id}`, taskData); | |
| console.log(`TasksApi: Update response status for task ${id}`, response.status); | |
| return createSafeTask(response.data); | |
| } catch (error) { | |
| console.error(`Error updating task ${id}:`, error); | |
| throw error; | |
| } | |
| } | |
| async delete(id: number): Promise<void> { | |
| try { | |
| console.log(`TasksApi: Deleting task ${id}`); | |
| await apiClient.delete(`${this.baseUrl}/${id}`); | |
| console.log(`TasksApi: Task ${id} deleted successfully`); | |
| } catch (error) { | |
| console.error(`Error deleting task ${id}:`, error); | |
| throw error; | |
| } | |
| } | |
| } | |
| export const tasksApi = new TasksApi(); |