Add svelte-sonner for notifications and enhance employee search functionality
- Integrated svelte-sonner for toast notifications in the layout. - Implemented server-side search for employees with pagination in the API. - Updated employee loading logic to support search queries and loading more results. - Enhanced employee detail view with navigation and improved UI interactions. - Adjusted cookie handling in hooks for PocketBase authentication.
This commit is contained in:
@@ -14,12 +14,38 @@ export interface EmployeeRecord {
|
||||
|
||||
const COLLECTION = 'Employee_Records';
|
||||
|
||||
export const GET: RequestHandler = async ({ locals }) => {
|
||||
const { items } = await locals.pb
|
||||
.collection(COLLECTION)
|
||||
.getList<EmployeeRecord>(1, 500, { sort: 'Last_Name,First_Name' });
|
||||
/** Escape a string for use inside PocketBase filter double-quotes. */
|
||||
function escapeFilterValue(s: string): string {
|
||||
return s.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
||||
}
|
||||
|
||||
return json({ employees: items });
|
||||
export const GET: RequestHandler = async ({ locals, url }) => {
|
||||
const search = url.searchParams.get('search')?.trim() ?? '';
|
||||
const page = Math.max(1, parseInt(url.searchParams.get('page') ?? '1', 10));
|
||||
const perPage = Math.min(500, Math.max(1, parseInt(url.searchParams.get('perPage') ?? '200', 10)));
|
||||
|
||||
let filter = 'delete != true';
|
||||
if (search.length > 0) {
|
||||
const escaped = escapeFilterValue(search);
|
||||
// Search across main text fields (PocketBase ~ is "contains")
|
||||
filter = `(${[
|
||||
`First_Name ~ "${escaped}"`,
|
||||
`Last_Name ~ "${escaped}"`,
|
||||
`Email_Address ~ "${escaped}"`,
|
||||
`Phone_Number ~ "${escaped}"`,
|
||||
`Voxer_ID ~ "${escaped}"`,
|
||||
`Status ~ "${escaped}"`
|
||||
].join(' || ')}) && delete != true`;
|
||||
}
|
||||
|
||||
const { items, totalItems } = await locals.pb
|
||||
.collection(COLLECTION)
|
||||
.getList<EmployeeRecord>(page, perPage, {
|
||||
filter,
|
||||
sort: 'Last_Name,First_Name'
|
||||
});
|
||||
|
||||
return json({ employees: items, total: totalItems });
|
||||
};
|
||||
|
||||
export const POST: RequestHandler = async ({ request, locals }) => {
|
||||
@@ -30,7 +56,9 @@ export const POST: RequestHandler = async ({ request, locals }) => {
|
||||
Phone_Number: body.Phone_Number ?? '',
|
||||
Email_Address: body.Email_Address ?? '',
|
||||
Voxer_ID: body.Voxer_ID ?? '',
|
||||
Status: body.Status ?? ''
|
||||
Status: body.Status ?? '',
|
||||
delete: false,
|
||||
...(locals.user?.id && { entered_by: locals.user.id })
|
||||
});
|
||||
return json(record);
|
||||
};
|
||||
|
||||
@@ -4,6 +4,26 @@ import type { EmployeeRecord } from '../+server';
|
||||
|
||||
const COLLECTION = 'Employee_Records';
|
||||
|
||||
export const GET: RequestHandler = async ({ params, locals }) => {
|
||||
const id = params.id;
|
||||
try {
|
||||
const employee = await locals.pb
|
||||
.collection(COLLECTION)
|
||||
.getOne<EmployeeRecord>(id);
|
||||
if ((employee as { delete?: boolean }).delete === true) {
|
||||
return json({ error: 'Employee not found' }, { status: 404 });
|
||||
}
|
||||
return json({ employee });
|
||||
} catch (e: unknown) {
|
||||
const is404 =
|
||||
e &&
|
||||
typeof e === 'object' &&
|
||||
'status' in e &&
|
||||
(e as { status: number }).status === 404;
|
||||
return json({ error: 'Employee not found' }, { status: is404 ? 404 : 500 });
|
||||
}
|
||||
};
|
||||
|
||||
export const PATCH: RequestHandler = async ({ params, request, locals }) => {
|
||||
const id = params.id;
|
||||
const body = await request.json();
|
||||
@@ -13,12 +33,17 @@ export const PATCH: RequestHandler = async ({ params, request, locals }) => {
|
||||
...(body.Phone_Number !== undefined && { Phone_Number: body.Phone_Number }),
|
||||
...(body.Email_Address !== undefined && { Email_Address: body.Email_Address }),
|
||||
...(body.Voxer_ID !== undefined && { Voxer_ID: body.Voxer_ID }),
|
||||
...(body.Status !== undefined && { Status: body.Status })
|
||||
...(body.Status !== undefined && { Status: body.Status }),
|
||||
...(body.Notes !== undefined && { Notes: body.Notes }),
|
||||
...(locals.user?.id && { updated_by: locals.user.id })
|
||||
});
|
||||
return json(record);
|
||||
return json({ employee: record });
|
||||
};
|
||||
|
||||
export const DELETE: RequestHandler = async ({ params, locals }) => {
|
||||
await locals.pb.collection(COLLECTION).delete(params.id);
|
||||
await locals.pb.collection(COLLECTION).update(params.id, {
|
||||
delete: true,
|
||||
...(locals.user?.id && { updated_by: locals.user.id })
|
||||
});
|
||||
return new Response(null, { status: 204 });
|
||||
};
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import { json } from '@sveltejs/kit';
|
||||
import type { RequestHandler } from './$types';
|
||||
|
||||
const REPORTS_COLLECTION = 'Employee_Reports';
|
||||
|
||||
export interface EmployeeReportRecord {
|
||||
id: string;
|
||||
report?: string;
|
||||
created: string;
|
||||
updated: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export const GET: RequestHandler = async ({ params, locals }) => {
|
||||
const employeeId = params.id;
|
||||
const { items } = await locals.pb
|
||||
.collection(REPORTS_COLLECTION)
|
||||
.getList<EmployeeReportRecord>(1, 100, {
|
||||
filter: `Employee = "${employeeId}" && delete != true`,
|
||||
sort: '-created'
|
||||
});
|
||||
return json({ reports: items });
|
||||
};
|
||||
|
||||
export const POST: RequestHandler = async ({ params, request, locals }) => {
|
||||
const employeeId = params.id;
|
||||
const body = await request.json();
|
||||
let voxers: Array<{ label: string; url: string }> = [];
|
||||
if (body.voxers != null) {
|
||||
try {
|
||||
voxers = Array.isArray(body.voxers) ? body.voxers : JSON.parse(String(body.voxers));
|
||||
} catch {
|
||||
voxers = [];
|
||||
}
|
||||
}
|
||||
const report = await locals.pb.collection(REPORTS_COLLECTION).create<EmployeeReportRecord>({
|
||||
Employee: employeeId,
|
||||
report: body.report ?? '',
|
||||
voxers,
|
||||
delete: false,
|
||||
...(locals.user?.id && { entered_by: locals.user.id })
|
||||
});
|
||||
return json({ report });
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
import { json } from '@sveltejs/kit';
|
||||
import type { RequestHandler } from './$types';
|
||||
|
||||
const REPORTS_COLLECTION = 'Employee_Reports';
|
||||
|
||||
export interface EmployeeReportRecord {
|
||||
id: string;
|
||||
report?: string;
|
||||
created: string;
|
||||
updated: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export const PATCH: RequestHandler = async ({ params, request, locals }) => {
|
||||
const { reportId } = params;
|
||||
const body = await request.json();
|
||||
const update: Record<string, unknown> = {
|
||||
...(body.report !== undefined && { report: body.report }),
|
||||
...(locals.user?.id && { updated_by: locals.user.id })
|
||||
};
|
||||
if (body.voxers !== undefined) {
|
||||
update.voxers = Array.isArray(body.voxers) ? body.voxers : JSON.parse(String(body.voxers));
|
||||
}
|
||||
const report = await locals.pb
|
||||
.collection(REPORTS_COLLECTION)
|
||||
.update<EmployeeReportRecord>(reportId, update);
|
||||
return json({ report });
|
||||
};
|
||||
|
||||
export const DELETE: RequestHandler = async ({ params, locals }) => {
|
||||
await locals.pb.collection(REPORTS_COLLECTION).update(params.reportId, {
|
||||
delete: true,
|
||||
...(locals.user?.id && { updated_by: locals.user.id })
|
||||
});
|
||||
return new Response(null, { status: 204 });
|
||||
};
|
||||
Reference in New Issue
Block a user