tududi/frontend/utils/taskEventService.ts
Chris 03f38f05dc
Setup intelligence (#84)
* Add next suggestions and remove console logs

* Add pomodoro timer

* Add pomodoro switch in settings

* Fix pomodoro setting

* Add timezones to settings

* Fix an issue with password reset

* Cleanup

* Sort tags alphabetically

* Clean up today's view

* Add an indicator for repeatedly added to today

* Refactor tags

* Add due date today item

* Move recurrence to the subtitle area

* Fix today layout

* Add a badge to Inbox items

* Move inbox badge to sidebar

* Add quotes and progress bar

* Add translations for quotes

* Fix test issues

* Add helper script for docker local

* Set up overdue tasks

* Add  linux/arm/v7 build to deploy script

* Add  linux/arm/v7 build to deploy script pt2

* Fix an issue with helmet and SSL

* Add volume db persistence

* Fix cog icon issues
2025-06-27 14:02:18 +03:00

187 lines
No EOL
4.6 KiB
TypeScript

import {
TaskEvent,
TaskCompletionTime,
ProductivityMetrics,
CompletionAnalyticsResponse,
TaskActivitySummary
} from '../entities/TaskEvent';
const API_BASE = '/api';
/**
* Get task timeline (all events for a specific task)
*/
export const getTaskTimeline = async (taskId: number): Promise<TaskEvent[]> => {
const response = await fetch(`${API_BASE}/task/${taskId}/timeline`, {
credentials: 'include'
});
if (!response.ok) {
throw new Error(`Failed to fetch task timeline: ${response.statusText}`);
}
return response.json();
};
/**
* Get task completion time analytics
*/
export const getTaskCompletionTime = async (taskId: number): Promise<TaskCompletionTime | null> => {
const response = await fetch(`${API_BASE}/task/${taskId}/completion-time`, {
credentials: 'include'
});
if (response.status === 404) {
return null;
}
if (!response.ok) {
throw new Error(`Failed to fetch task completion time: ${response.statusText}`);
}
return response.json();
};
/**
* Get user productivity metrics
*/
export const getUserProductivityMetrics = async (
startDate?: string,
endDate?: string
): Promise<ProductivityMetrics> => {
const params = new URLSearchParams();
if (startDate) params.append('startDate', startDate);
if (endDate) params.append('endDate', endDate);
const response = await fetch(`${API_BASE}/user/productivity-metrics?${params}`, {
credentials: 'include'
});
if (!response.ok) {
throw new Error(`Failed to fetch productivity metrics: ${response.statusText}`);
}
return response.json();
};
/**
* Get user activity summary
*/
export const getUserActivitySummary = async (
startDate: string,
endDate: string
): Promise<TaskActivitySummary[]> => {
const params = new URLSearchParams({
startDate,
endDate
});
const response = await fetch(`${API_BASE}/user/activity-summary?${params}`, {
credentials: 'include'
});
if (!response.ok) {
throw new Error(`Failed to fetch activity summary: ${response.statusText}`);
}
return response.json();
};
/**
* Get completion analytics for multiple tasks
*/
export const getCompletionAnalytics = async (
options: {
limit?: number;
offset?: number;
projectId?: number;
} = {}
): Promise<CompletionAnalyticsResponse> => {
const params = new URLSearchParams();
if (options.limit) params.append('limit', options.limit.toString());
if (options.offset) params.append('offset', options.offset.toString());
if (options.projectId) params.append('projectId', options.projectId.toString());
const response = await fetch(`${API_BASE}/tasks/completion-analytics?${params}`, {
credentials: 'include'
});
if (!response.ok) {
throw new Error(`Failed to fetch completion analytics: ${response.statusText}`);
}
return response.json();
};
/**
* Format duration for display
*/
export const formatDuration = (hours: number): string => {
if (hours < 1) {
const minutes = Math.round(hours * 60);
return `${minutes}m`;
} else if (hours < 24) {
const h = Math.floor(hours);
const m = Math.round((hours - h) * 60);
return m > 0 ? `${h}h ${m}m` : `${h}h`;
} else {
const days = Math.floor(hours / 24);
const h = Math.floor(hours % 24);
return h > 0 ? `${days}d ${h}h` : `${days}d`;
}
};
/**
* Get human-readable event type
*/
export const getEventTypeLabel = (eventType: string): string => {
const labels: Record<string, string> = {
'created': 'Created',
'status_changed': 'Status Changed',
'priority_changed': 'Priority Changed',
'due_date_changed': 'Due Date Changed',
'project_changed': 'Project Changed',
'name_changed': 'Name Changed',
'description_changed': 'Description Changed',
'note_changed': 'Note Changed',
'completed': 'Completed',
'archived': 'Archived',
'deleted': 'Deleted',
'restored': 'Restored',
'today_changed': 'Today Flag Changed',
'tags_changed': 'Tags Changed',
'recurrence_changed': 'Recurrence Changed'
};
return labels[eventType] || eventType;
};
/**
* Get human-readable status value
*/
export const getStatusLabel = (status: number): string => {
const statusLabels: Record<number, string> = {
0: 'Not Started',
1: 'In Progress',
2: 'Done',
3: 'Archived',
4: 'Waiting'
};
return statusLabels[status] || `Status ${status}`;
};
/**
* Get human-readable priority value
*/
export const getPriorityLabel = (priority: number): string => {
const priorityLabels: Record<number, string> = {
0: 'Low',
1: 'Medium',
2: 'High'
};
return priorityLabels[priority] || `Priority ${priority}`;
};