* 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
107 lines
3.4 KiB
TypeScript
107 lines
3.4 KiB
TypeScript
'use client';
|
||
|
||
import { type ProfileProps } from '../types';
|
||
import { TextField } from '@/components/shared/data-fields';
|
||
import { CardSectionHeader } from '@/components/ui';
|
||
import { useCustomerMutation, useCustomerQuery } from '@/hooks/api/customers';
|
||
import { Button } from '@repo/ui/components/ui/button';
|
||
import { Card } from '@repo/ui/components/ui/card';
|
||
import Link from 'next/link';
|
||
import { useState } from 'react';
|
||
|
||
export function ContactDataCard({ telegramId }: Readonly<ProfileProps>) {
|
||
const { data: { customer } = {} } = useCustomerQuery({ telegramId });
|
||
|
||
if (!customer) return null;
|
||
|
||
return (
|
||
<Card className="p-4">
|
||
<div className="flex flex-col gap-4">
|
||
<Link href={customer?.phone ? `tel:${customer?.phone}` : ''}>
|
||
<TextField id="phone" label="Телефон" readOnly value={customer?.phone ?? ''} />
|
||
</Link>
|
||
<Button asChild className="w-full bg-foreground">
|
||
<Link href={`https://t.me/${customer?.phone}`} rel="noopener noreferrer" target="_blank">
|
||
Написать в Telegram
|
||
</Link>
|
||
</Button>
|
||
</div>
|
||
</Card>
|
||
);
|
||
}
|
||
|
||
export function ProfileDataCard() {
|
||
const { data: { customer } = {} } = useCustomerQuery();
|
||
const { cancelChanges, hasChanges, isPending, resetTrigger, saveChanges, updateField } =
|
||
useProfileEdit();
|
||
|
||
if (!customer) return null;
|
||
|
||
return (
|
||
<Card className="p-4">
|
||
<div className="flex flex-col gap-4">
|
||
<CardSectionHeader title="Ваши данные" />
|
||
<TextField
|
||
id="name"
|
||
key={`name-${resetTrigger}`}
|
||
label="Имя"
|
||
onChange={(value) => updateField('name', value)}
|
||
value={customer?.name ?? ''}
|
||
/>
|
||
<TextField disabled id="phone" label="Телефон" readOnly value={customer?.phone ?? ''} />
|
||
{/* <CheckboxWithText
|
||
checked={customer.role !== 'client'}
|
||
description="Разрешить другим пользователям записываться к вам"
|
||
onChange={(checked) =>
|
||
updateField('role', checked ? Role.Master : Role.Client)
|
||
}
|
||
text="Быть мастером"
|
||
/> */}
|
||
{hasChanges && (
|
||
<div className="flex justify-end gap-2">
|
||
<Button disabled={isPending} onClick={cancelChanges} variant="outline">
|
||
Отмена
|
||
</Button>
|
||
<Button disabled={isPending} onClick={saveChanges}>
|
||
{isPending ? 'Сохранение...' : 'Сохранить'}
|
||
</Button>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</Card>
|
||
);
|
||
}
|
||
|
||
function useProfileEdit() {
|
||
const { isPending, mutate } = useCustomerMutation();
|
||
const [pendingChanges, setPendingChanges] = useState<Record<string, unknown>>({});
|
||
const [resetTrigger, setResetTrigger] = useState(0);
|
||
|
||
const updateField = (field: string, value: unknown) => {
|
||
setPendingChanges((previous) => ({ ...previous, [field]: value }));
|
||
};
|
||
|
||
const saveChanges = () => {
|
||
if (Object.keys(pendingChanges).length === 0) return;
|
||
|
||
mutate({ data: pendingChanges });
|
||
setPendingChanges({});
|
||
};
|
||
|
||
const cancelChanges = () => {
|
||
setPendingChanges({});
|
||
setResetTrigger((previous) => previous + 1);
|
||
};
|
||
|
||
const hasChanges = Object.keys(pendingChanges).length > 0;
|
||
|
||
return {
|
||
cancelChanges,
|
||
hasChanges,
|
||
isPending,
|
||
resetTrigger,
|
||
saveChanges,
|
||
updateField,
|
||
};
|
||
}
|