diff --git a/apps/web/components/orders/order-buttons.tsx b/apps/web/components/orders/order-buttons.tsx index 5e83856..8a019eb 100644 --- a/apps/web/components/orders/order-buttons.tsx +++ b/apps/web/components/orders/order-buttons.tsx @@ -7,6 +7,7 @@ import { useIsMaster } from '@/hooks/api/customers'; import { useOrderMutation, useOrderQuery } from '@/hooks/api/orders'; import { usePushWithData } from '@/hooks/url'; import { Enum_Order_State } from '@repo/graphql/types'; +import { isBeforeToday } from '@repo/utils/datetime-format'; export function OrderButtons({ documentId }: Readonly) { const push = usePushWithData(); @@ -49,14 +50,22 @@ export function OrderButtons({ documentId }: Readonly) { push('/orders/add', order); } + const isOrderStale = order?.datetime_start && isBeforeToday(order?.datetime_start); + + const canCancel = !isOrderStale && (isCreated || (isMaster && isCancelling) || isApproved); + const canComplete = isMaster && isApproved; + const canConfirm = !isOrderStale && isMaster && isCreated; + const canRepeat = isCancelled || isCompleted; + const canReturn = !isOrderStale && isMaster && isCancelled; + return ( ); } diff --git a/apps/web/components/schedule/day-slots-list/index.tsx b/apps/web/components/schedule/day-slots-list/index.tsx index ad94952..e3df2eb 100644 --- a/apps/web/components/schedule/day-slots-list/index.tsx +++ b/apps/web/components/schedule/day-slots-list/index.tsx @@ -7,14 +7,12 @@ 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 { getDateUTCRange } from '@repo/utils/datetime-format'; -import dayjs from 'dayjs'; +import { getDateUTCRange, isTodayOrAfter } from '@repo/utils/datetime-format'; import { type PropsWithChildren } from 'react'; export function DaySlotsList() { const { data: { customer } = {} } = useCustomerQuery(); const selectedDate = useDateTimeStore((store) => store.date); - const now = dayjs(); const { endOfDay, startOfDay } = getDateUTCRange(selectedDate).day(); const { data: { slots } = {}, isLoading } = useMasterSlotsQuery({ @@ -28,13 +26,13 @@ export function DaySlotsList() { return ; } - const shouldShowAddForm = now.isSame(selectedDate, 'day') || now.isBefore(selectedDate, 'day'); + const isSelectedDateTodayOrAfter = selectedDate && isTodayOrAfter(selectedDate); if (!slots?.length) { return ( - {shouldShowAddForm && } + {isSelectedDateTodayOrAfter && } ); } @@ -43,7 +41,7 @@ export function DaySlotsList() {

Слоты

{slots.map((slot) => slot && )} - {shouldShowAddForm && } + {isSelectedDateTodayOrAfter && }
); } diff --git a/apps/web/components/schedule/slot-buttons.tsx b/apps/web/components/schedule/slot-buttons.tsx index 018469a..5a19a37 100644 --- a/apps/web/components/schedule/slot-buttons.tsx +++ b/apps/web/components/schedule/slot-buttons.tsx @@ -5,6 +5,7 @@ import FloatingActionPanel from '../shared/action-panel'; import { type SlotComponentProps } from './types'; import { useSlotDelete, useSlotMutation, useSlotQuery } from '@/hooks/api/slots'; import { Enum_Slot_State } from '@repo/graphql/types'; +import { isBeforeToday } from '@repo/utils/datetime-format'; import { useRouter } from 'next/navigation'; export function SlotButtons({ documentId }: Readonly) { @@ -29,22 +30,29 @@ export function SlotButtons({ documentId }: Readonly) { return updateSlot({ data: { state: Enum_Slot_State.Closed } }); } - function handleDeleteSlot() { + const handleToggle = () => { + if (isOpened) handleCloseSlot(); + if (isClosed) handleOpenSlot(); + }; + + const handleDeleteSlot = () => { router.back(); return deleteSlot(); - } + }; const hasOrders = Boolean(slot?.orders.length); + const isSlotStale = slot?.datetime_start && isBeforeToday(slot?.datetime_start); + + const canDelete = !isSlotStale && !hasOrders; + const canToggle = !isSlotStale; + return ( handleDeleteSlot()} - onToggle={() => { - if (isOpened) handleCloseSlot(); - if (isClosed) handleOpenSlot(); - }} + onDelete={canDelete ? handleDeleteSlot : undefined} + onToggle={canToggle ? handleToggle : undefined} /> ); } diff --git a/packages/utils/src/datetime-format.ts b/packages/utils/src/datetime-format.ts index 15ad2d1..93c75af 100644 --- a/packages/utils/src/datetime-format.ts +++ b/packages/utils/src/datetime-format.ts @@ -6,8 +6,11 @@ import 'dayjs/locale/ru'; type DateTime = Exclude; -if (!dayjs.prototype.tz) { +if (!dayjs.prototype.utc) { dayjs.extend(utc); +} + +if (!dayjs.prototype.tz) { dayjs.extend(timezone); } @@ -88,6 +91,17 @@ export function getTimeZoneLabel(tz: string = DEFAULT_TZ): string { return `GMT${offset}`; } +export function isBeforeToday(date: Date | string) { + const nowUtc = dayjs().tz(DEFAULT_TZ); + const inputDateUtc = dayjs(date).tz(DEFAULT_TZ); + + return inputDateUtc.isBefore(nowUtc, 'day'); +} + +export function isTodayOrAfter(date: Date | string) { + return !isBeforeToday(date); +} + export function sumTime(datetime: DateTime, durationMinutes: number) { if (!datetime) return '';