From 76de850bf5dc2d1b3ff0ac1265fe0e8732c186ee Mon Sep 17 00:00:00 2001 From: vchikalkin Date: Thu, 3 Jul 2025 16:15:22 +0300 Subject: [PATCH] feat(profile): add BookContactButton component to enhance booking functionality --- .../app/(main)/profile/[telegramId]/page.tsx | 8 ++- apps/web/components/profile/orders-list.tsx | 56 +++++++++++++++++++ apps/web/stores/order/hooks.tsx | 23 ++++---- 3 files changed, 74 insertions(+), 13 deletions(-) diff --git a/apps/web/app/(main)/profile/[telegramId]/page.tsx b/apps/web/app/(main)/profile/[telegramId]/page.tsx index 39aaab0..1a242b0 100644 --- a/apps/web/app/(main)/profile/[telegramId]/page.tsx +++ b/apps/web/app/(main)/profile/[telegramId]/page.tsx @@ -1,7 +1,12 @@ import { getCustomer } from '@/actions/api/customers'; import { Container } from '@/components/layout'; import { PageHeader } from '@/components/navigation'; -import { ContactDataCard, PersonCard, ProfileOrdersList } from '@/components/profile'; +import { + BookContactButton, + ContactDataCard, + PersonCard, + ProfileOrdersList, +} from '@/components/profile'; import { dehydrate, HydrationBoundary, QueryClient } from '@tanstack/react-query'; type Props = { params: Promise<{ telegramId: string }> }; @@ -24,6 +29,7 @@ export default async function ProfilePage(props: Readonly) { + ); diff --git a/apps/web/components/profile/orders-list.tsx b/apps/web/components/profile/orders-list.tsx index fc8a425..fce90ff 100644 --- a/apps/web/components/profile/orders-list.tsx +++ b/apps/web/components/profile/orders-list.tsx @@ -4,6 +4,62 @@ import { OrderCard } from '../shared/order-card'; import { type ProfileProps } from './types'; import { useCustomerQuery, useIsMaster } from '@/hooks/api/customers'; import { useOrdersQuery } from '@/hooks/api/orders'; +import { usePushWithData } from '@/hooks/url'; +import { CalendarPlus } from 'lucide-react'; + +export function BookContactButton({ telegramId }: Readonly) { + const { data: { customer } = {}, isLoading: isCustomerLoading } = useCustomerQuery(); + const isMaster = useIsMaster(); + + const { data: { customer: profile } = {}, isLoading: isProfileLoading } = useCustomerQuery({ + telegramId, + }); + + const push = usePushWithData(); + + const handleBook = () => { + if (!profile || !customer) return; + + if (isMaster) { + push('/orders/add', { + client: { + documentId: profile.documentId, + }, + slot: { + master: { + documentId: customer.documentId, + }, + }, + }); + } else { + push('/orders/add', { + client: { + documentId: customer.documentId, + }, + slot: { + master: { + documentId: profile.documentId, + }, + }, + }); + } + }; + + if (isCustomerLoading || isProfileLoading || !profile || !customer) return null; + + return ( +
+ +
+ ); +} export function ProfileOrdersList({ telegramId }: Readonly) { const { data: { customer } = {} } = useCustomerQuery(); diff --git a/apps/web/stores/order/hooks.tsx b/apps/web/stores/order/hooks.tsx index 07c054f..642d485 100644 --- a/apps/web/stores/order/hooks.tsx +++ b/apps/web/stores/order/hooks.tsx @@ -4,7 +4,7 @@ import { useOrderStore } from './context'; import { type Steps } from './types'; import { useCustomerQuery, useIsMaster } from '@/hooks/api/customers'; import { type OrderFieldsFragment } from '@repo/graphql/types'; -import { useCallback, useEffect, useRef } from 'react'; +import { useEffect, useRef } from 'react'; const STEPS: Steps[] = [ 'master-select', @@ -18,7 +18,6 @@ export const CLIENT_STEPS: Steps[] = STEPS.filter((step) => step !== 'client-sel export function useInitOrderStore(initData: null | OrderFieldsFragment) { const initialized = useRef(false); - const { data: { customer } = {} } = useCustomerQuery(); const isMaster = useIsMaster(); @@ -29,19 +28,17 @@ export function useInitOrderStore(initData: null | OrderFieldsFragment) { const setStepsSequence = useOrderStore((store) => store._setStepSequence); const step = useOrderStore((store) => store.step); - const setFirstStep = useCallback(() => { - const steps = isMaster ? MASTER_STEPS : CLIENT_STEPS; - setStepsSequence(steps); - setStep(steps[0] as Steps); - }, [isMaster, setStep, setStepsSequence]); - useEffect(() => { if (initialized.current || !customer || step !== 'loading') return; + const steps = isMaster ? MASTER_STEPS : CLIENT_STEPS; + setStepsSequence(steps); + + // Инициализация из initData (например, для повторного заказа) if (initData) { const masterId = initData.slot?.master?.documentId; const clientId = initData.client?.documentId; - const serviceId = initData.services[0]?.documentId; + const serviceId = initData.services?.[0]?.documentId; if (masterId) setMasterId(masterId); if (clientId) setClientId(clientId); @@ -49,17 +46,20 @@ export function useInitOrderStore(initData: null | OrderFieldsFragment) { if (masterId && clientId && serviceId) { setStep('datetime-select'); + } else if (masterId && clientId) { + setStep('service-select'); } else { - setFirstStep(); + setStep(steps[0] ?? 'loading'); } } else { + // Обычная инициализация (новый заказ) if (isMaster) { setMasterId(customer.documentId); } else { setClientId(customer.documentId); } - setFirstStep(); + setStep(steps[0] ?? 'loading'); } initialized.current = true; @@ -68,7 +68,6 @@ export function useInitOrderStore(initData: null | OrderFieldsFragment) { initData, isMaster, setClientId, - setFirstStep, setMasterId, setServiceId, setStep,