feat(orders, slots, schedule): enhance order and slot button functionality with date validation and conditional rendering
This commit is contained in:
parent
ee6ccbef84
commit
ba88305bbf
@ -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<OrderComponentProps>) {
|
||||
const push = usePushWithData();
|
||||
@ -49,14 +50,22 @@ export function OrderButtons({ documentId }: Readonly<OrderComponentProps>) {
|
||||
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 (
|
||||
<FloatingActionPanel
|
||||
isLoading={isPending}
|
||||
onCancel={isCreated || (isMaster && isCancelling) || isApproved ? handleCancel : undefined}
|
||||
onComplete={isMaster && isApproved ? handleOnComplete : undefined}
|
||||
onConfirm={isMaster && isCreated ? handleApprove : undefined}
|
||||
onRepeat={isCancelled || isCompleted ? handleOnRepeat : undefined}
|
||||
onReturn={isMaster && isCancelled ? handleApprove : undefined}
|
||||
onCancel={canCancel ? handleCancel : undefined}
|
||||
onComplete={canComplete ? handleOnComplete : undefined}
|
||||
onConfirm={canConfirm ? handleApprove : undefined}
|
||||
onRepeat={canRepeat ? handleOnRepeat : undefined}
|
||||
onReturn={canReturn ? handleApprove : undefined}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -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 <LoadingSpinner />;
|
||||
}
|
||||
|
||||
const shouldShowAddForm = now.isSame(selectedDate, 'day') || now.isBefore(selectedDate, 'day');
|
||||
const isSelectedDateTodayOrAfter = selectedDate && isTodayOrAfter(selectedDate);
|
||||
|
||||
if (!slots?.length) {
|
||||
return (
|
||||
<Wrapper>
|
||||
<DataNotFound title="Слоты не найдены" />
|
||||
{shouldShowAddForm && <DaySlotAddForm />}
|
||||
{isSelectedDateTodayOrAfter && <DaySlotAddForm />}
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
@ -43,7 +41,7 @@ export function DaySlotsList() {
|
||||
<Wrapper>
|
||||
<h1 className="font-bold">Слоты</h1>
|
||||
{slots.map((slot) => slot && <SlotCard key={slot.documentId} {...slot} />)}
|
||||
{shouldShowAddForm && <DaySlotAddForm />}
|
||||
{isSelectedDateTodayOrAfter && <DaySlotAddForm />}
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
||||
@ -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<SlotComponentProps>) {
|
||||
@ -29,22 +30,29 @@ export function SlotButtons({ documentId }: Readonly<SlotComponentProps>) {
|
||||
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 (
|
||||
<FloatingActionPanel
|
||||
isLoading={isPendingUpdate || isPendingDelete}
|
||||
isOpen={isOpened}
|
||||
onDelete={hasOrders ? undefined : () => handleDeleteSlot()}
|
||||
onToggle={() => {
|
||||
if (isOpened) handleCloseSlot();
|
||||
if (isClosed) handleOpenSlot();
|
||||
}}
|
||||
onDelete={canDelete ? handleDeleteSlot : undefined}
|
||||
onToggle={canToggle ? handleToggle : undefined}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -6,8 +6,11 @@ import 'dayjs/locale/ru';
|
||||
|
||||
type DateTime = Exclude<ConfigType, null | undefined>;
|
||||
|
||||
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 '';
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user