diff --git a/apps/web/actions/api/orders.ts b/apps/web/actions/api/orders.ts index bc5321f..5a4b4da 100644 --- a/apps/web/actions/api/orders.ts +++ b/apps/web/actions/api/orders.ts @@ -22,3 +22,9 @@ export async function getOrders(...variables: Parameters) { + const service = await getServicesService(); + + return service.updateOrder(...variables); +} diff --git a/apps/web/app/(main)/orders/[documentId]/page.tsx b/apps/web/app/(main)/orders/[documentId]/page.tsx index 7ac7486..e9f4b74 100644 --- a/apps/web/app/(main)/orders/[documentId]/page.tsx +++ b/apps/web/app/(main)/orders/[documentId]/page.tsx @@ -1,7 +1,7 @@ import { getOrder } from '@/actions/api/orders'; import { Container } from '@/components/layout'; import { PageHeader } from '@/components/navigation'; -import { OrderContacts, OrderDateTime, OrderServices } from '@/components/orders'; +import { OrderButtons, OrderContacts, OrderDateTime, OrderServices } from '@/components/orders'; import { type OrderPageParameters } from '@/components/orders/types'; import { dehydrate, HydrationBoundary, QueryClient } from '@tanstack/react-query'; @@ -25,6 +25,8 @@ export default async function ProfilePage(props: Readonly) { +
+ ); diff --git a/apps/web/components/orders/index.ts b/apps/web/components/orders/index.ts index 094008c..adece76 100644 --- a/apps/web/components/orders/index.ts +++ b/apps/web/components/orders/index.ts @@ -1,4 +1,5 @@ export * from '../shared/action-panel'; +export * from './order-buttons'; export * from './order-contacts'; export * from './order-datetime'; export * from './order-form'; diff --git a/apps/web/components/orders/order-buttons.tsx b/apps/web/components/orders/order-buttons.tsx new file mode 100644 index 0000000..4e332fe --- /dev/null +++ b/apps/web/components/orders/order-buttons.tsx @@ -0,0 +1,50 @@ +/* eslint-disable canonical/id-match */ +'use client'; +import FloatingActionPanel from '../shared/action-panel'; +import { type OrderComponentProps } from './types'; +import { useCustomerQuery } from '@/hooks/api/customers'; +import { useOrderMutation, useOrderQuery } from '@/hooks/api/orders'; +import { Enum_Customer_Role, Enum_Order_State } from '@repo/graphql/types'; + +export function OrderButtons({ documentId }: Readonly) { + const { data: { customer } = {} } = useCustomerQuery(); + + const isMaster = customer?.role === Enum_Customer_Role.Master; + + const { data: { order } = {} } = useOrderQuery({ documentId }); + + const { mutate: updateSlot } = useOrderMutation({ documentId }); + + if (!order) return null; + + const isApproved = order?.state === Enum_Order_State.Approved; + const isCompleted = order?.state === Enum_Order_State.Completed; + const isCancelling = order?.state === Enum_Order_State.Cancelling; + const isCancelled = order?.state === Enum_Order_State.Cancelled; + + function handleApprove() { + if (isMaster) { + updateSlot({ data: { state: Enum_Order_State.Approved } }); + } + } + + function handleCancel() { + if (isMaster) { + updateSlot({ data: { state: Enum_Order_State.Cancelled } }); + } else { + updateSlot({ data: { state: Enum_Order_State.Cancelling } }); + } + } + + return ( + handleCancel()} + onConfirm={ + !isMaster || isApproved || isCancelled || isCancelling || isCompleted + ? undefined + : () => handleApprove() + } + /> + ); +} diff --git a/apps/web/components/shared/action-panel.tsx b/apps/web/components/shared/action-panel.tsx index 5df48ed..84e7a07 100644 --- a/apps/web/components/shared/action-panel.tsx +++ b/apps/web/components/shared/action-panel.tsx @@ -2,25 +2,43 @@ import { Button } from '@repo/ui/components/ui/button'; import { Card } from '@repo/ui/components/ui/card'; -import { Ban, Check, Lock, Trash2, Unlock } from 'lucide-react'; +import { Ban, Check, Loader2, Lock, RotateCcw, Trash2, Unlock } from 'lucide-react'; type FloatingActionPanelProps = { + readonly isCancelling?: boolean; readonly isOpen?: boolean; readonly onCancel?: () => void; readonly onConfirm?: () => void; readonly onDelete?: () => void; + readonly onRepeat?: () => void; readonly onToggle?: () => void; }; export default function FloatingActionPanel({ + isCancelling = false, isOpen, onCancel, onConfirm, onDelete, + onRepeat, onToggle, }: FloatingActionPanelProps) { + // Если слот отменяется, показываем статус вместо кнопок + if (isCancelling) { + return ( + +
+ + + Слот отменяется... + +
+
+ ); + } + return ( - +
{/* Кнопка закрыть/открыть */} {onToggle && ( @@ -50,6 +68,18 @@ export default function FloatingActionPanel({ )} + {/* Кнопка повторить */} + {onRepeat && ( + + )} + {/* Кнопка удалить */} {onDelete && (