mirror of
https://github.com/open-reception/appointment-booking-software.git
synced 2026-08-17 21:25:52 +02:00
Speed up calendar response time by removing agent data from calendar response
This commit is contained in:
@@ -186,9 +186,6 @@ describe("ScheduleService", () => {
|
||||
channelId: "channel1",
|
||||
agent: {
|
||||
id: "agent1",
|
||||
name: "Test Agent",
|
||||
description: "Test Description",
|
||||
logo: null,
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -241,7 +238,6 @@ describe("ScheduleService", () => {
|
||||
expect(actualSlot.duration).toBe(60); // 60-minute slots
|
||||
expect(actualSlot.availableAgents).toHaveLength(1);
|
||||
expect(actualSlot.availableAgents[0].id).toBe("agent1");
|
||||
expect(actualSlot.availableAgents[0].name).toBe("Test Agent");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -29,11 +29,13 @@ const scheduleRequestSchema = z.object({
|
||||
|
||||
export type ScheduleRequest = z.infer<typeof scheduleRequestSchema>;
|
||||
|
||||
export type CalendarAgent = Pick<SelectAgent, "id">;
|
||||
|
||||
export interface TimeSlot {
|
||||
from: string; // UTC ISO timestamp
|
||||
to: string; // UTC ISO timestamp
|
||||
duration: number; // minutes
|
||||
availableAgents: SelectAgent[];
|
||||
availableAgents: CalendarAgent[];
|
||||
}
|
||||
|
||||
export interface AppointmentWithKeyShare extends SelectAppointment {
|
||||
@@ -201,7 +203,7 @@ export class ScheduleService {
|
||||
let channelAgents = await db
|
||||
.select({
|
||||
channelId: tenantSchema.channelAgent.channelId,
|
||||
agent: tenantSchema.agent,
|
||||
agent: { id: tenantSchema.agent.id },
|
||||
})
|
||||
.from(tenantSchema.channelAgent)
|
||||
.innerJoin(
|
||||
@@ -266,7 +268,7 @@ export class ScheduleService {
|
||||
slotTemplates: { slotTemplate: SelectSlotTemplate; channelId: string }[];
|
||||
appointments: SelectAppointment[];
|
||||
absences: SelectAgentAbsence[];
|
||||
channelAgents: { channelId: string; agent: SelectAgent }[];
|
||||
channelAgents: { channelId: string; agent: CalendarAgent }[];
|
||||
staffKeyShares: Record<string, string>;
|
||||
timeZone: string;
|
||||
}): Promise<DaySchedule[]> {
|
||||
@@ -357,7 +359,7 @@ export class ScheduleService {
|
||||
date: Date;
|
||||
slotTemplates: SelectSlotTemplate[];
|
||||
appointments: SelectAppointment[];
|
||||
agents: SelectAgent[];
|
||||
agents: CalendarAgent[];
|
||||
absences: SelectAgentAbsence[];
|
||||
timeZone: string;
|
||||
}): TimeSlot[] {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import type { SelectAgent } from "$lib/server/db/tenant-schema";
|
||||
import type { DaySchedule } from "$lib/server/services/schedule-service";
|
||||
import type { CalendarAgent, DaySchedule } from "$lib/server/services/schedule-service";
|
||||
|
||||
export type AppointmentStatus = "available" | "booked" | "reserved";
|
||||
export type TAppointmentFilter = "all" | AppointmentStatus;
|
||||
@@ -33,5 +32,5 @@ export type TCalendarSlot = {
|
||||
color: string | null;
|
||||
column: number;
|
||||
channelId: string;
|
||||
availableAgents?: SelectAgent[];
|
||||
availableAgents?: CalendarAgent[];
|
||||
};
|
||||
|
||||
+34
-28
@@ -2,9 +2,10 @@
|
||||
import { m } from "$i18n/messages";
|
||||
import { Button } from "$lib/components/ui/button";
|
||||
import { Text } from "$lib/components/ui/typography";
|
||||
import type { SelectAgent } from "$lib/server/db/tenant-schema";
|
||||
import type { TAddAppointment } from "./types";
|
||||
import type { CalendarAgent } from "$lib/server/services/schedule-service";
|
||||
import { agents as agentsStore } from "$lib/stores/agents";
|
||||
import UnknownItemIcon from "@lucide/svelte/icons/user-star";
|
||||
import type { TAddAppointment } from "./types";
|
||||
|
||||
let {
|
||||
newAppointment,
|
||||
@@ -12,9 +13,11 @@
|
||||
proceed,
|
||||
}: {
|
||||
newAppointment: TAddAppointment;
|
||||
availableAgents: SelectAgent[];
|
||||
availableAgents: CalendarAgent[];
|
||||
proceed: (data: TAddAppointment) => void;
|
||||
} = $props();
|
||||
|
||||
let agents = $derived($agentsStore.agents);
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
@@ -23,31 +26,34 @@
|
||||
</Text>
|
||||
<ul class="flex w-full flex-col gap-2">
|
||||
{#each availableAgents as agent (agent.id)}
|
||||
<li>
|
||||
<Button
|
||||
variant="outline"
|
||||
class="flex h-auto w-full cursor-pointer items-center gap-4 px-2 py-1.5 text-left"
|
||||
onclick={() => proceed({ ...newAppointment, agentId: agent.id })}
|
||||
>
|
||||
{#if agent.image}
|
||||
<img
|
||||
src={agent.image}
|
||||
alt={agent.name}
|
||||
class="size-8 rounded-full border object-cover object-center"
|
||||
loading="lazy"
|
||||
/>
|
||||
{:else}
|
||||
<UnknownItemIcon
|
||||
class="bg-muted text-muted-foreground size-15 rounded-full border stroke-1 p-1"
|
||||
/>
|
||||
{/if}
|
||||
<div class="flex grow flex-col gap-1">
|
||||
<Text style="md" class="font-medium">
|
||||
{agent.name}
|
||||
</Text>
|
||||
</div>
|
||||
</Button>
|
||||
</li>
|
||||
{@const agentItem = agents.find((it) => it.id === agent.id)}
|
||||
{#if agentItem}
|
||||
<li>
|
||||
<Button
|
||||
variant="outline"
|
||||
class="flex h-auto w-full cursor-pointer items-center gap-4 px-2 py-1.5 text-left"
|
||||
onclick={() => proceed({ ...newAppointment, agentId: agent.id })}
|
||||
>
|
||||
{#if agentItem.image}
|
||||
<img
|
||||
src={agentItem.image}
|
||||
alt={agentItem.name}
|
||||
class="size-8 rounded-full border object-cover object-center"
|
||||
loading="lazy"
|
||||
/>
|
||||
{:else}
|
||||
<UnknownItemIcon
|
||||
class="bg-muted text-muted-foreground size-15 rounded-full border stroke-1 p-1"
|
||||
/>
|
||||
{/if}
|
||||
<div class="flex grow flex-col gap-1">
|
||||
<Text style="md" class="font-medium">
|
||||
{agentItem.name}
|
||||
</Text>
|
||||
</div>
|
||||
</Button>
|
||||
</li>
|
||||
{/if}
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user