* feat(profile): implement local hooks for profile and service data editing - Added `useProfileEdit` and `useServiceEdit` hooks to manage pending changes and save functionality for profile and service data cards. - Updated `ProfileDataCard` and `ServiceDataCard` components to utilize these hooks, enhancing user experience with save and cancel options. - Introduced buttons for saving and canceling changes, improving the overall interactivity of the forms. - Refactored input handling to use `updateField` for better state management. * feat(bot): integrate Redis and update bot configuration - Added Redis service to both docker-compose files for local development and production environments. - Updated bot configuration to utilize the Grammy framework, replacing Telegraf. - Implemented graceful shutdown for the bot, ensuring proper resource management. - Refactored bot commands and removed deprecated message handling logic. - Enhanced environment variable management for Redis connection settings. - Updated dependencies in package.json to include new Grammy-related packages. * fix(registration): improve error handling for customer creation - Updated error handling in the registration feature to return a generic error message when documentId is not present, enhancing user experience by providing clearer feedback. * feat(bot): add unhandled command message and integrate unhandled feature - Introduced a new message for unhandled commands in Russian localization to improve user feedback. - Integrated the unhandled feature into the bot's middleware for better command handling. * feat(locales): update Russian localization with additional contact information - Enhanced the short description in the Russian localization file to include a contact note for user inquiries, improving user support accessibility. * feat(help): enhance help command with support information - Updated the help command to include a support message in the Russian localization, providing users with a contact point for inquiries. - Improved the command response by combining the list of available commands with the new support information, enhancing user experience. * fix(orders): update default sorting order for orders - Changed the default sorting order for orders from 'datetime_start:asc' to 'datetime_start:desc' to ensure the most recent orders are displayed first, improving the user experience in order management. * refactor(orders): remove ClientsOrdersList and streamline OrdersList component - Eliminated the ClientsOrdersList component to simplify the orders page structure. - Updated OrdersList to handle both client and master views, enhancing code reusability. - Improved order fetching logic and UI rendering for better performance and user experience. * fix(order-form): hide next button on success & error pages * refactor(bot): streamline bot middleware and improve key generator function - Removed unused session middleware and sequentialize function from the bot's error boundary. - Simplified the key generator function for rate limiting by condensing its implementation. - Enhanced overall code clarity and maintainability in the bot's configuration. * feat(customer): implement banned customer check and enhance customer data handling - Added `isCustomerBanned` function to determine if a customer is banned based on the `bannedUntil` field. - Updated the `BaseService` to throw an error if a banned customer attempts to access certain functionalities. - Enhanced the GraphQL operations to include the `bannedUntil` field in customer queries and mutations, improving data integrity and user experience. - Integrated the `CheckBanned` component in the layout to manage banned customer states effectively. * feat(ban-system): implement multi-level user ban checks across services - Added a comprehensive ban checking system to prevent access for banned users at multiple levels, including database, API, and client-side. - Introduced `bannedUntil` field in the customer model to manage temporary and permanent bans effectively. - Enhanced `BaseService` and various service classes to include ban checks, ensuring that banned users cannot perform actions or access data. - Updated error handling to provide consistent feedback for banned users across the application. - Improved user experience with a dedicated ban check component and a user-friendly ban notification page. * packages(apps/web): upgrade next@15.5.0
171 lines
5.5 KiB
TypeScript
171 lines
5.5 KiB
TypeScript
'use client';
|
||
|
||
import { Button } from '@repo/ui/components/ui/button';
|
||
import { Card } from '@repo/ui/components/ui/card';
|
||
import { Ban, Check, Lock, RotateCcw, Save, Trash2, Undo, Unlock } from 'lucide-react';
|
||
|
||
type FloatingActionPanelProps = {
|
||
readonly isLoading?: boolean;
|
||
readonly isOpen?: boolean;
|
||
readonly onCancel?: () => void;
|
||
readonly onComplete?: () => void;
|
||
readonly onConfirm?: () => void;
|
||
readonly onDelete?: () => void;
|
||
readonly onRepeat?: () => void;
|
||
readonly onReturn?: () => void;
|
||
readonly onSave?: () => void;
|
||
readonly onToggle?: () => void;
|
||
};
|
||
|
||
export default function FloatingActionPanel({
|
||
isLoading = false,
|
||
isOpen,
|
||
onCancel,
|
||
onComplete,
|
||
onConfirm,
|
||
onDelete,
|
||
onRepeat,
|
||
onReturn,
|
||
onSave,
|
||
onToggle,
|
||
}: FloatingActionPanelProps) {
|
||
// Если не переданы обработчики, скрываем панель
|
||
if (
|
||
!onCancel &&
|
||
!onConfirm &&
|
||
!onDelete &&
|
||
!onComplete &&
|
||
!onRepeat &&
|
||
!onToggle &&
|
||
!onReturn &&
|
||
!onSave
|
||
)
|
||
return null;
|
||
|
||
return (
|
||
<Card className="fixed inset-x-4 bottom-4 z-50 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-500 text-white hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-700'
|
||
: 'bg-gray-500 text-white hover:bg-gray-600 dark:bg-gray-600 dark:hover:bg-gray-700'
|
||
}
|
||
`}
|
||
disabled={isLoading}
|
||
onClick={onToggle}
|
||
size="sm"
|
||
>
|
||
{isOpen ? (
|
||
<>
|
||
<Lock className="mr-2 size-4" />
|
||
<span>Закрыть</span>
|
||
</>
|
||
) : (
|
||
<>
|
||
<Unlock className="mr-2 size-4" />
|
||
<span>Открыть</span>
|
||
</>
|
||
)}
|
||
</Button>
|
||
)}
|
||
|
||
{/* Кнопка повторить */}
|
||
{onRepeat && (
|
||
<Button
|
||
className="w-full rounded-2xl bg-purple-500 text-sm text-white transition-all duration-200 hover:bg-purple-600 dark:bg-purple-600 dark:hover:bg-purple-700 sm:w-auto"
|
||
disabled={isLoading}
|
||
onClick={onRepeat}
|
||
size="sm"
|
||
>
|
||
<RotateCcw className="mr-2 size-4" />
|
||
<span>Повторить</span>
|
||
</Button>
|
||
)}
|
||
|
||
{/* Кнопка выполнено */}
|
||
{onComplete && (
|
||
<Button
|
||
className="w-full rounded-2xl bg-green-500 text-sm text-white transition-all duration-200 hover:bg-green-600 dark:bg-green-600 dark:hover:bg-green-700 sm:w-auto"
|
||
disabled={isLoading}
|
||
onClick={onComplete}
|
||
size="sm"
|
||
>
|
||
<Check className="mr-2 size-4" />
|
||
<span>Завершить</span>
|
||
</Button>
|
||
)}
|
||
|
||
{/* Кнопка удалить */}
|
||
{onDelete && (
|
||
<Button
|
||
className="w-full rounded-2xl bg-orange-500 text-sm text-white transition-all duration-200 hover:bg-orange-600 dark:bg-orange-600 dark:hover:bg-orange-700 sm:w-auto"
|
||
disabled={isLoading}
|
||
onClick={onDelete}
|
||
size="sm"
|
||
>
|
||
<Trash2 className="mr-2 size-4" />
|
||
<span>Удалить</span>
|
||
</Button>
|
||
)}
|
||
|
||
{/* Кнопка отменить */}
|
||
{onCancel && (
|
||
<Button
|
||
className="w-full rounded-2xl bg-red-500 text-sm text-white transition-all duration-200 hover:bg-red-600 dark:bg-red-600 dark:hover:bg-red-700 sm:w-auto"
|
||
disabled={isLoading}
|
||
onClick={onCancel}
|
||
size="sm"
|
||
>
|
||
<Ban className="mr-2 size-4" />
|
||
<span>Отменить</span>
|
||
</Button>
|
||
)}
|
||
|
||
{/* Кнопка подтвердить */}
|
||
{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"
|
||
disabled={isLoading}
|
||
onClick={onConfirm}
|
||
size="sm"
|
||
>
|
||
<Check className="mr-2 size-4" />
|
||
<span>Подтвердить</span>
|
||
</Button>
|
||
)}
|
||
|
||
{/* Кнопка вернуть */}
|
||
{onReturn && (
|
||
<Button
|
||
className="w-full rounded-2xl bg-blue-400 text-sm text-white transition-all duration-200 hover:bg-blue-500 dark:bg-blue-500 dark:hover:bg-blue-600 sm:w-auto"
|
||
disabled={isLoading}
|
||
onClick={onReturn}
|
||
size="sm"
|
||
>
|
||
<Undo className="mr-2 size-4" />
|
||
<span>Вернуть</span>
|
||
</Button>
|
||
)}
|
||
|
||
{/* Кнопка сохранить */}
|
||
{onSave && (
|
||
<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"
|
||
disabled={isLoading}
|
||
onClick={onSave}
|
||
size="sm"
|
||
>
|
||
<Save className="mr-2 size-4" />
|
||
<span>Сохранить</span>
|
||
</Button>
|
||
)}
|
||
</div>
|
||
</Card>
|
||
);
|
||
}
|