From 2ca11832a92fcc9e44ad6153fadc56a98d4951bc Mon Sep 17 00:00:00 2001 From: vchikalkin Date: Wed, 25 Jun 2025 17:57:41 +0300 Subject: [PATCH] highlight days with slots in schedule calendar --- apps/web/actions/api/slots.ts | 6 ++++ apps/web/components/schedule/calendar.tsx | 30 +++++++++++++++++++ .../schedule/day-slots-list/index.tsx | 12 ++++++-- apps/web/hooks/api/slots.ts | 25 ++++++++++++++-- packages/graphql/api/slots.ts | 11 +++++++ 5 files changed, 78 insertions(+), 6 deletions(-) diff --git a/apps/web/actions/api/slots.ts b/apps/web/actions/api/slots.ts index d469909..b6b1fc6 100644 --- a/apps/web/actions/api/slots.ts +++ b/apps/web/actions/api/slots.ts @@ -37,6 +37,12 @@ export async function getSlots(...variables: Parameters) { + const service = await getService(); + + return service.getSlotsOrders(...variables); +} + export async function updateSlot(...variables: Parameters) { const service = await getService(); diff --git a/apps/web/components/schedule/calendar.tsx b/apps/web/components/schedule/calendar.tsx index 08f565c..33506be 100644 --- a/apps/web/components/schedule/calendar.tsx +++ b/apps/web/components/schedule/calendar.tsx @@ -1,13 +1,34 @@ 'use client'; +import { useCustomerQuery } from '@/hooks/api/customers'; +import { useSlotsQuery } from '@/hooks/api/slots'; import { useDateTimeStore } from '@/stores/datetime'; import { Calendar } from '@repo/ui/components/ui/calendar'; import dayjs from 'dayjs'; +import { useState } from 'react'; export function ScheduleCalendar() { + const { data: { customer } = {} } = useCustomerQuery(); + const selectedDate = useDateTimeStore((store) => store.date); const setSelectedDate = useDateTimeStore((store) => store.setDate); + const [currentMonthDate, setCurrentMonthDate] = useState(new Date()); + + const { data: { slots } = {} } = useSlotsQuery({ + filters: { + date: { + gte: dayjs(currentMonthDate).startOf('month').format('YYYY-MM-DD'), + lte: dayjs(currentMonthDate).endOf('month').format('YYYY-MM-DD'), + }, + master: { + documentId: { + eq: customer?.documentId, + }, + }, + }, + }); + return ( { + return slots?.some((slot) => dayjs(slot?.date).isSame(date, 'day')) || false; + }, + }} + modifiersClassNames={{ + hasEvent: 'border-primary border-2 rounded-xl', + }} + onMonthChange={(date) => setCurrentMonthDate(date)} onSelect={(date) => { if (date) setSelectedDate(date); }} diff --git a/apps/web/components/schedule/day-slots-list/index.tsx b/apps/web/components/schedule/day-slots-list/index.tsx index 1485cc8..7cddfde 100644 --- a/apps/web/components/schedule/day-slots-list/index.tsx +++ b/apps/web/components/schedule/day-slots-list/index.tsx @@ -2,16 +2,22 @@ import { DaySlotAddForm } from './day-slot-add-form'; import { SlotCard } from './slot-card'; -import { useSlotsQuery } from '@/hooks/api/slots'; +import { useCustomerQuery } from '@/hooks/api/customers'; +import { useMasterSlotsQuery } from '@/hooks/api/slots'; import { useDateTimeStore } from '@/stores/datetime'; import { LoadingSpinner } from '@repo/ui/components/ui/spinner'; import { formatDate } from '@repo/utils/datetime-format'; export function DaySlotsList() { + const { data: { customer } = {} } = useCustomerQuery(); + const selectedDate = useDateTimeStore((store) => store.date); - const { data: { slots } = {}, isLoading } = useSlotsQuery({ - filters: { date: { eq: formatDate(selectedDate).db() } }, + const { data: { slots } = {}, isLoading } = useMasterSlotsQuery({ + filters: { + date: { eq: formatDate(selectedDate).db() }, + master: { documentId: { eq: customer?.documentId } }, + }, }); if (isLoading) return ; diff --git a/apps/web/hooks/api/slots.ts b/apps/web/hooks/api/slots.ts index a443121..4d2d9c6 100644 --- a/apps/web/hooks/api/slots.ts +++ b/apps/web/hooks/api/slots.ts @@ -7,15 +7,20 @@ import { getAvailableTimeSlots, getSlot, getSlots, + getSlotsOrders, updateSlot, } from '@/actions/api/slots'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import dayjs from 'dayjs'; -export const useSlotsQuery = (variables: Parameters[0]) => { - const { data: { customer } = {} } = useCustomerQuery(); +type UseMasterSlotsVariables = { + filters: Required< + Pick[0]['filters']>, 'date' | 'master'> + >; +}; - const masterId = variables.filters?.master?.documentId?.eq || customer?.documentId; +export const useMasterSlotsQuery = (variables: UseMasterSlotsVariables) => { + const masterId = variables.filters?.master?.documentId?.eq; const date = variables.filters?.date?.eq; return useQuery({ @@ -24,6 +29,13 @@ export const useSlotsQuery = (variables: Parameters[0]) => { }); }; +export const useSlotsQuery = (variables: Parameters[0]) => { + return useQuery({ + queryFn: () => getSlots(variables), + queryKey: ['slots', variables], + }); +}; + export const useSlotQuery = (variables: Parameters[0]) => { const { documentId } = variables; @@ -33,6 +45,13 @@ export const useSlotQuery = (variables: Parameters[0]) => { }); }; +export const useSlotsOrdersQuery = (variables: Parameters[0]) => { + return useQuery({ + queryFn: () => getSlotsOrders(variables), + queryKey: ['slots-orders', variables], + }); +}; + export const useAvailableTimeSlotsQuery = ( ...variables: Parameters ) => { diff --git a/packages/graphql/api/slots.ts b/packages/graphql/api/slots.ts index c1a50d5..c1bf491 100644 --- a/packages/graphql/api/slots.ts +++ b/packages/graphql/api/slots.ts @@ -132,6 +132,17 @@ export class SlotsService extends BaseService { return result.data; } + async getSlotsOrders(variables: VariablesOf) { + const { query } = await getClientWithToken(); + + const result = await query({ + query: GQL.GetSlotsOrdersDocument, + variables, + }); + + return result.data; + } + async updateSlot(variables: VariablesOf) { const { mutate } = await getClientWithToken();