feat: Enhance ticketing system with categories, templates, SLA tracking, and fix frontend integration

- Add ticket categories (billing, technical, feature_request, etc.) with type-specific options
- Add TicketTemplate and CannedResponse models for quick ticket creation
- Implement SLA tracking with due_at and first_response_at fields
- Add is_platform_admin and is_customer helper functions to fix permission checks
- Register models in Django admin with filters and fieldsets
- Enhance signals with error handling for WebSocket notifications
- Fix frontend API URLs for templates and canned responses
- Update PlatformSupport page to use real ticketing API
- Add comprehensive i18n translations for all ticket fields

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
poduck
2025-11-28 05:32:36 -05:00
parent 512d95ca2d
commit 200a6b3dd4
22 changed files with 1782 additions and 425 deletions

View File

@@ -1,8 +1,23 @@
import { apiClient } from './client';
import { Ticket, TicketComment } from '../types'; // Assuming types.ts will define these
import apiClient from './client';
import { Ticket, TicketComment, TicketTemplate, CannedResponse, TicketStatus, TicketPriority, TicketCategory, TicketType } from '../types';
export const getTickets = async (): Promise<Ticket[]> => {
const response = await apiClient.get('/api/tickets/');
export interface TicketFilters {
status?: TicketStatus;
priority?: TicketPriority;
category?: TicketCategory;
ticketType?: TicketType;
assignee?: string;
}
export const getTickets = async (filters?: TicketFilters): Promise<Ticket[]> => {
const params = new URLSearchParams();
if (filters?.status) params.append('status', filters.status);
if (filters?.priority) params.append('priority', filters.priority);
if (filters?.category) params.append('category', filters.category);
if (filters?.ticketType) params.append('ticket_type', filters.ticketType);
if (filters?.assignee) params.append('assignee', filters.assignee);
const response = await apiClient.get(`/api/tickets/${params.toString() ? `?${params.toString()}` : ''}`);
return response.data;
};
@@ -34,3 +49,20 @@ export const createTicketComment = async (ticketId: string, data: Partial<Ticket
const response = await apiClient.post(`/api/tickets/${ticketId}/comments/`, data);
return response.data;
};
// Ticket Templates
export const getTicketTemplates = async (): Promise<TicketTemplate[]> => {
const response = await apiClient.get('/api/tickets/templates/');
return response.data;
};
export const getTicketTemplate = async (id: string): Promise<TicketTemplate> => {
const response = await apiClient.get(`/api/tickets/templates/${id}/`);
return response.data;
};
// Canned Responses
export const getCannedResponses = async (): Promise<CannedResponse[]> => {
const response = await apiClient.get('/api/tickets/canned-responses/');
return response.data;
};