feat(profile): add BookContactButton component to enhance booking functionality
This commit is contained in:
parent
6eb421bfd4
commit
76de850bf5
@ -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<Props>) {
|
||||
<PersonCard telegramId={telegramId} />
|
||||
<ContactDataCard telegramId={telegramId} />
|
||||
<ProfileOrdersList telegramId={telegramId} />
|
||||
<BookContactButton telegramId={telegramId} />
|
||||
</Container>
|
||||
</HydrationBoundary>
|
||||
);
|
||||
|
||||
@ -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<ProfileProps>) {
|
||||
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 (
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
<button
|
||||
className="flex items-center justify-center gap-2 self-center rounded-xl bg-primary/5 px-6 py-2 font-semibold text-primary shadow-sm transition-colors hover:bg-primary/10"
|
||||
onClick={handleBook}
|
||||
type="button"
|
||||
>
|
||||
<CalendarPlus className="size-5 text-primary" />
|
||||
<span>{isMaster ? 'Записать' : 'Записаться'}</span>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function ProfileOrdersList({ telegramId }: Readonly<ProfileProps>) {
|
||||
const { data: { customer } = {} } = useCustomerQuery();
|
||||
|
||||
@ -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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user