feat: ticket modal collapsible notes and time entries
- New GET /api/tickets/[id]/notes: fetches TicketNotes from Autotask, enriches with creator resource names, sorted newest first - Modal: collapsible Notes section (lazy fetch on expand, shows count badge) - Modal: collapsible Time Entries section (lazy fetch, count + total hours in header) - Both sections fetch once and cache for the modal session
This commit is contained in:
parent
0a318fb9d6
commit
b72fe2c70e
2 changed files with 215 additions and 9 deletions
53
app/api/tickets/[id]/notes/route.ts
Normal file
53
app/api/tickets/[id]/notes/route.ts
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { getAutotaskClient } from '@/lib/services/autotask-factory';
|
||||
|
||||
export async function GET(
|
||||
request: NextRequest,
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
try {
|
||||
const { id } = await params;
|
||||
const client = getAutotaskClient();
|
||||
|
||||
const notes = await client.queryEntity('TicketNotes', {
|
||||
filter: [
|
||||
{ op: 'eq', field: 'ticketID', value: parseInt(id) }
|
||||
],
|
||||
});
|
||||
|
||||
// Enrich with resource names
|
||||
const resourceCache: Record<number, string> = {};
|
||||
const enriched = await Promise.all(
|
||||
(notes as any[]).map(async (note) => {
|
||||
let creatorName = null;
|
||||
const resourceId = note.creatorResourceID;
|
||||
if (resourceId) {
|
||||
if (resourceCache[resourceId]) {
|
||||
creatorName = resourceCache[resourceId];
|
||||
} else {
|
||||
try {
|
||||
const resource = await client.getEntityById('Resources', resourceId) as any;
|
||||
creatorName = resource ? `${resource.firstName} ${resource.lastName}` : null;
|
||||
if (creatorName) resourceCache[resourceId] = creatorName;
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
return { ...note, creatorName };
|
||||
})
|
||||
);
|
||||
|
||||
enriched.sort((a, b) =>
|
||||
new Date(b.createDateTime || 0).getTime() - new Date(a.createDateTime || 0).getTime()
|
||||
);
|
||||
|
||||
return NextResponse.json({ notes: enriched });
|
||||
} catch (error) {
|
||||
console.error('Error fetching ticket notes:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Failed to fetch ticket notes' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue