slot page: replace buttons with floating panel

This commit is contained in:
vchikalkin 2025-06-23 20:55:07 +03:00
parent 2ba56c5949
commit 4ed010056a
4 changed files with 102 additions and 31 deletions

View File

@ -23,8 +23,8 @@ export default async function SlotPage(props: Readonly<Props>) {
<PageHeader title="Слот" />
<Container>
<SlotDateTime {...parameters} />
<SlotButtons {...parameters} />
<SlotOrdersList {...parameters} />
<SlotButtons {...parameters} />
</Container>
</HydrationBoundary>
);

View File

@ -1,3 +1,4 @@
export * from '../shared/action-panel';
export * from './order-contacts';
export * from './order-datetime';
export * from './order-form';

View File

@ -1,11 +1,10 @@
/* eslint-disable react/jsx-no-bind */
/* eslint-disable canonical/id-match */
'use client';
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 { Button } from '@repo/ui/components/ui/button';
import { useRouter } from 'next/navigation';
export function SlotButtons({ documentId }: Readonly<SlotComponentProps>) {
@ -38,33 +37,13 @@ export function SlotButtons({ documentId }: Readonly<SlotComponentProps>) {
const hasOrders = Boolean(slot?.orders.length);
return (
<div className="grid grid-cols-[2fr_1fr]">
{isOpened && (
<Button
className="rounded-l-2xl rounded-r-none bg-orange-100 p-6 text-orange-500 dark:bg-yellow-700 dark:text-orange-100"
onClick={handleCloseSlot}
variant="ghost"
>
Закрыть
</Button>
)}
{isClosed && (
<Button
className="rounded-l-2xl rounded-r-none bg-green-100 p-6 text-green-500 dark:bg-green-700 dark:text-green-100"
onClick={handleOpenSlot}
variant="ghost"
>
Открыть
</Button>
)}
<Button
className="rounded-l-none rounded-r-2xl bg-red-100 p-6 text-red-500 dark:bg-red-700 dark:text-red-100"
disabled={hasOrders}
onClick={handleDeleteSlot}
variant="ghost"
>
Удалить
</Button>
</div>
<FloatingActionPanel
isOpen={isOpened}
onDelete={hasOrders ? undefined : () => handleDeleteSlot()}
onToggle={() => {
if (isOpened) handleCloseSlot();
if (isClosed) handleOpenSlot();
}}
/>
);
}

View File

@ -0,0 +1,91 @@
'use client';
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';
type FloatingActionPanelProps = {
readonly isOpen?: boolean;
readonly onCancel?: () => void;
readonly onConfirm?: () => void;
readonly onDelete?: () => void;
readonly onToggle?: () => void;
};
export default function FloatingActionPanel({
isOpen,
onCancel,
onConfirm,
onDelete,
onToggle,
}: FloatingActionPanelProps) {
return (
<Card className="fixed inset-x-4 bottom-4 rounded-3xl border-0 bg-background/95 p-4 shadow-2xl backdrop-blur-sm dark:bg-primary/5 md:bottom-6 md:left-auto md:right-6 md:p-6">
<div className="flex flex-col items-center gap-2 sm:flex-row sm:gap-4">
{/* Кнопка закрыть/открыть */}
{onToggle && (
<Button
className={`
w-full rounded-2xl text-sm transition-all duration-200 sm:w-auto
${
isOpen
? 'bg-blue-100 text-blue-700 hover:bg-blue-200 dark:bg-blue-950/70 dark:text-blue-300 dark:hover:bg-blue-900/70'
: 'bg-gray-100 text-gray-700 hover:bg-gray-200 dark:bg-gray-900/70 dark:text-gray-300 dark:hover:bg-gray-800/70'
}
`}
onClick={onToggle}
size="sm"
>
{isOpen ? (
<>
<Lock className="mr-2 size-4" />
<span>Закрыть</span>
</>
) : (
<>
<Unlock className="mr-2 size-4" />
<span>Открыть</span>
</>
)}
</Button>
)}
{/* Кнопка удалить */}
{onDelete && (
<Button
className="w-full rounded-2xl bg-orange-100 text-sm text-orange-700 transition-all duration-200 hover:bg-orange-200 dark:bg-orange-950/70 dark:text-orange-300 dark:hover:bg-orange-900/70 sm:w-auto"
onClick={onDelete}
size="sm"
>
<Trash2 className="mr-2 size-4" />
<span>Удалить</span>
</Button>
)}
{/* Кнопка отменить */}
{onCancel && (
<Button
className="w-full rounded-2xl bg-red-100 text-sm text-red-700 transition-all duration-200 hover:bg-red-200 dark:bg-red-950/70 dark:text-red-300 dark:hover:bg-red-900/70 sm:w-auto"
onClick={onCancel}
size="sm"
>
<Ban className="mr-2 size-4" />
<span>Отменить</span>
</Button>
)}
{/* Кнопка подтверд<D180><D0B4>ть */}
{onConfirm && (
<Button
className="w-full rounded-2xl bg-green-600 text-sm text-white shadow-lg transition-all duration-200 hover:bg-green-700 dark:bg-green-700 dark:hover:bg-green-600 sm:w-auto"
onClick={onConfirm}
size="sm"
>
<Check className="mr-2 size-4" />
<span>Подтвердить</span>
</Button>
)}
</div>
</Card>
);
}