bring the results of queries and hooks into a single form
This commit is contained in:
parent
2683e31570
commit
284142eb4f
@ -16,7 +16,8 @@ import { message } from 'telegraf/filters';
|
||||
const bot = new Telegraf(environment.BOT_TOKEN);
|
||||
|
||||
bot.start(async (context) => {
|
||||
const customer = await getCustomer({ telegramId: context.from.id });
|
||||
const data = await getCustomer({ telegramId: context.from.id });
|
||||
const customer = data?.data?.customers?.at(0);
|
||||
|
||||
if (customer) {
|
||||
return context.reply(
|
||||
@ -33,7 +34,8 @@ bot.start(async (context) => {
|
||||
});
|
||||
|
||||
bot.command('addcontact', async (context) => {
|
||||
const customer = await getCustomer({ telegramId: context.from.id });
|
||||
const data = await getCustomer({ telegramId: context.from.id });
|
||||
const customer = data?.data?.customers?.at(0);
|
||||
|
||||
if (!customer) {
|
||||
return context.reply(
|
||||
@ -50,7 +52,8 @@ bot.command('addcontact', async (context) => {
|
||||
});
|
||||
|
||||
bot.command('becomemaster', async (context) => {
|
||||
const customer = await getCustomer({ telegramId: context.from.id });
|
||||
const data = await getCustomer({ telegramId: context.from.id });
|
||||
const customer = data?.data?.customers?.at(0);
|
||||
|
||||
if (!customer) {
|
||||
return context.reply('Сначала поделитесь своим номером телефона.', KEYBOARD_SHARE_PHONE);
|
||||
@ -73,7 +76,9 @@ bot.command('becomemaster', async (context) => {
|
||||
});
|
||||
|
||||
bot.on(message('contact'), async (context) => {
|
||||
const customer = await getCustomer({ telegramId: context.from.id });
|
||||
const data = await getCustomer({ telegramId: context.from.id });
|
||||
const customer = data?.data?.customers?.at(0);
|
||||
|
||||
const isRegistration = !customer;
|
||||
|
||||
const { contact } = context.message;
|
||||
|
||||
@ -9,11 +9,9 @@ export async function getClients() {
|
||||
|
||||
const { user } = session;
|
||||
|
||||
const getCustomerClientsResponse = await getCustomerClients({ telegramId: user?.telegramId });
|
||||
const response = await getCustomerClients({ telegramId: user?.telegramId });
|
||||
|
||||
return {
|
||||
clients: getCustomerClientsResponse?.clients,
|
||||
};
|
||||
return response.data?.customers?.at(0);
|
||||
}
|
||||
|
||||
export async function getMasters() {
|
||||
@ -22,9 +20,7 @@ export async function getMasters() {
|
||||
|
||||
const { user } = session;
|
||||
|
||||
const getCustomerMastersResponse = await getCustomerMasters({ telegramId: user?.telegramId });
|
||||
const response = await getCustomerMasters({ telegramId: user?.telegramId });
|
||||
|
||||
return {
|
||||
masters: getCustomerMastersResponse?.masters,
|
||||
};
|
||||
return response.data?.customers?.at(0);
|
||||
}
|
||||
|
||||
@ -9,10 +9,11 @@ export async function getProfile(input?: GetCustomerQueryVariables) {
|
||||
if (!session) throw new Error('Missing session');
|
||||
|
||||
const { user } = session;
|
||||
|
||||
const telegramId = input?.telegramId || user?.telegramId;
|
||||
|
||||
const customer = await getCustomer({ telegramId });
|
||||
const { data } = await getCustomer({ telegramId });
|
||||
const customer = data?.customers?.at(0);
|
||||
|
||||
return customer;
|
||||
}
|
||||
|
||||
@ -22,11 +23,12 @@ export async function updateProfile(input: CustomerInput) {
|
||||
|
||||
const { user } = session;
|
||||
|
||||
const customer = await getCustomer({ telegramId: user?.telegramId });
|
||||
const { data } = await getCustomer({ telegramId: user?.telegramId });
|
||||
const customer = data.customers.at(0);
|
||||
if (!customer) throw new Error('Customer not found');
|
||||
|
||||
await updateCustomerProfile({
|
||||
data: input,
|
||||
documentId: customer.documentId,
|
||||
documentId: customer?.documentId,
|
||||
});
|
||||
}
|
||||
|
||||
@ -28,19 +28,21 @@ export const SlotCard = withContext(ContextProvider)(function (
|
||||
const { documentId } = props;
|
||||
|
||||
const { data } = useSlotQuery({ documentId });
|
||||
if (!data?.slot) return null;
|
||||
const slot = data?.data?.slot;
|
||||
|
||||
const ordersNumber = data.slot.orders?.length;
|
||||
if (!slot) return null;
|
||||
|
||||
const ordersNumber = slot.orders?.length;
|
||||
const hasOrders = Boolean(ordersNumber);
|
||||
|
||||
const isOpened = data?.slot?.state === Enum_Slot_State.Open;
|
||||
const isClosed = data?.slot?.state === Enum_Slot_State.Closed;
|
||||
const isOpened = slot?.state === Enum_Slot_State.Open;
|
||||
const isClosed = slot?.state === Enum_Slot_State.Closed;
|
||||
|
||||
return (
|
||||
<Link href={`/slots/${documentId}`} rel="noopener noreferrer">
|
||||
<div className="flex items-center justify-between rounded-2xl bg-background p-4 px-6 dark:bg-primary/5">
|
||||
<div className="flex flex-col gap-2">
|
||||
<ReadonlyTimeRange {...data.slot} />
|
||||
<ReadonlyTimeRange {...slot} />
|
||||
<span
|
||||
className={cn(
|
||||
'text-xs font-normal',
|
||||
@ -50,14 +52,14 @@ export const SlotCard = withContext(ContextProvider)(function (
|
||||
{hasOrders ? 'Есть записи' : 'Свободно'}
|
||||
</span>
|
||||
</div>
|
||||
{data.slot.state && (
|
||||
{slot.state && (
|
||||
<Badge
|
||||
className={cn(
|
||||
isOpened ? 'bg-green-100 text-green-500 dark:bg-green-700 dark:text-green-100' : '',
|
||||
isClosed ? 'bg-red-100 text-red-500 dark:bg-red-700 dark:text-red-100' : '',
|
||||
)}
|
||||
>
|
||||
{getBadgeText(data.slot.state)}
|
||||
{getBadgeText(slot.state)}
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -5,17 +5,18 @@ import { formatDate, formatTime } from '@/utils/date';
|
||||
|
||||
export function DateTimeCard({ documentId }: Readonly<SlotComponentProps>) {
|
||||
const { data } = useSlotQuery({ documentId });
|
||||
const slot = data?.data?.slot;
|
||||
|
||||
if (!data?.slot) return null;
|
||||
if (!slot) return null;
|
||||
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
<span className="mb-2 tracking-wide">{formatDate(data?.slot?.date).user()}</span>
|
||||
<span className="mb-2 tracking-wide">{formatDate(slot?.date).user()}</span>
|
||||
<span className="mt-2 text-3xl font-bold tracking-wide">
|
||||
{formatTime(data?.slot?.time_start).user()}
|
||||
{formatTime(slot?.time_start).user()}
|
||||
</span>
|
||||
<span className="mt-2 text-3xl font-bold tracking-wide">
|
||||
{formatTime(data?.slot?.time_end).user()}
|
||||
{formatTime(slot?.time_end).user()}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -22,11 +22,12 @@ export function OrdersList({
|
||||
documentId,
|
||||
}: Readonly<SlotComponentProps> & { readonly className?: string }) {
|
||||
const { data } = useSlotQuery({ documentId });
|
||||
const slot = data?.data?.slot;
|
||||
|
||||
return (
|
||||
<div className={cn('bg-transparent p-4', className)}>
|
||||
<h1 className="mb-2 text-2xl font-bold">Записи</h1>
|
||||
{data?.slot?.orders.map((order) => {
|
||||
{slot?.orders.map((order) => {
|
||||
return order && <Order key={order?.documentId} {...order} />;
|
||||
})}
|
||||
</div>
|
||||
@ -41,26 +42,24 @@ function getBadgeText(state: Enum_Order_State) {
|
||||
|
||||
function Order({ documentId }: Readonly<OrderComponentProps>) {
|
||||
const { data } = useOrderQuery({ documentId });
|
||||
const order = data?.data?.order;
|
||||
|
||||
if (!data?.data.order) return null;
|
||||
if (!order) return null;
|
||||
|
||||
const isCompleted = data?.data.order?.state === Enum_Order_State.Completed;
|
||||
const isCancelled = data?.data.order?.state === Enum_Order_State.Cancelled;
|
||||
const isCompleted = order?.state === Enum_Order_State.Completed;
|
||||
const isCancelled = order?.state === Enum_Order_State.Cancelled;
|
||||
|
||||
return (
|
||||
<Link href={`/records/${documentId}`} rel="noopener noreferrer">
|
||||
<div className="flex items-center justify-between rounded-2xl bg-background p-4 px-6 dark:bg-primary/5">
|
||||
<div className="flex flex-col justify-around gap-2">
|
||||
<ReadonlyTimeRange
|
||||
time_end={data?.data.order?.time_end}
|
||||
time_start={data?.data.order?.time_start}
|
||||
/>
|
||||
<ReadonlyTimeRange time_end={order?.time_end} time_start={order?.time_start} />
|
||||
<span className="truncate text-xs font-bold text-foreground">
|
||||
{data.data.order.services.map((service) => service?.name).join(', ')}
|
||||
{order.services.map((service) => service?.name).join(', ')}
|
||||
</span>
|
||||
<span className="text-xs text-foreground">{data?.data.order?.client?.name}</span>
|
||||
<span className="text-xs text-foreground">{order?.client?.name}</span>
|
||||
</div>
|
||||
{data?.data.order?.state && (
|
||||
{order?.state && (
|
||||
<Badge
|
||||
className={cn(
|
||||
isCompleted
|
||||
@ -69,7 +68,7 @@ function Order({ documentId }: Readonly<OrderComponentProps>) {
|
||||
isCancelled ? 'bg-red-100 text-red-500 dark:bg-red-700 dark:text-red-100' : '',
|
||||
)}
|
||||
>
|
||||
{getBadgeText(data?.data.order?.state)}
|
||||
{getBadgeText(order?.state)}
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -9,9 +9,10 @@ import { useRouter } from 'next/navigation';
|
||||
|
||||
export function SlotButtons({ documentId }: Readonly<SlotComponentProps>) {
|
||||
const { data } = useSlotQuery({ documentId });
|
||||
const slot = data?.data?.slot;
|
||||
|
||||
const isOpened = data?.slot?.state === Enum_Slot_State.Open;
|
||||
const isClosed = data?.slot?.state === Enum_Slot_State.Closed;
|
||||
const isOpened = slot?.state === Enum_Slot_State.Open;
|
||||
const isClosed = slot?.state === Enum_Slot_State.Closed;
|
||||
|
||||
const { mutate: mutateSlot } = useSlotMutation({ documentId });
|
||||
|
||||
|
||||
@ -4,7 +4,8 @@ import { LoadingSpinner } from '@/components/common/spinner';
|
||||
import { useSlots } from '@/hooks/slots';
|
||||
|
||||
export function SlotsList() {
|
||||
const { data: slots, isLoading } = useSlots();
|
||||
const { data, isLoading } = useSlots();
|
||||
const slots = data?.data.slots;
|
||||
|
||||
if (isLoading) return <LoadingSpinner />;
|
||||
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
import { getClients, getMasters } from '@/actions/contacts';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
export const useClientsQuery = () => {
|
||||
return useQuery({ queryFn: getClients, queryKey: ['contacts', 'clients', 'get'] });
|
||||
};
|
||||
export const useClientsQuery = () =>
|
||||
useQuery({ queryFn: getClients, queryKey: ['contacts', 'clients', 'get'] });
|
||||
|
||||
export const useMastersQuery = () => {
|
||||
return useQuery({ queryFn: getMasters, queryKey: ['contacts', 'masters', 'get'] });
|
||||
};
|
||||
export const useMastersQuery = () =>
|
||||
useQuery({ queryFn: getMasters, queryKey: ['contacts', 'masters', 'get'] });
|
||||
|
||||
@ -5,13 +5,11 @@ import * as GQL from '../types';
|
||||
export async function login() {
|
||||
const { mutate } = createApolloClient();
|
||||
|
||||
const response = await mutate({
|
||||
return mutate({
|
||||
mutation: GQL.LoginDocument,
|
||||
variables: {
|
||||
identifier: environment.LOGIN_GRAPHQL,
|
||||
password: environment.PASSWORD_GRAPHQL,
|
||||
},
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@ -33,34 +33,28 @@ export async function createOrUpdateUser(input: GQL.CreateCustomerMutationVariab
|
||||
export async function getCustomer(input: GQL.GetCustomerQueryVariables) {
|
||||
const { query } = await getClientWithToken();
|
||||
|
||||
const response = await query({
|
||||
return query({
|
||||
query: GQL.GetCustomerDocument,
|
||||
variables: input,
|
||||
});
|
||||
|
||||
return response?.data?.customers?.at(0);
|
||||
}
|
||||
|
||||
export async function getCustomerMasters(input: GQL.GetCustomerMastersQueryVariables) {
|
||||
const { query } = await getClientWithToken();
|
||||
|
||||
const response = await query({
|
||||
return query({
|
||||
query: GQL.GetCustomerMastersDocument,
|
||||
variables: input,
|
||||
});
|
||||
|
||||
return response?.data?.customers?.at(0);
|
||||
}
|
||||
|
||||
export async function getCustomerClients(input: GQL.GetCustomerClientsQueryVariables) {
|
||||
const { query } = await getClientWithToken();
|
||||
|
||||
const response = await query({
|
||||
return query({
|
||||
query: GQL.GetCustomerClientsDocument,
|
||||
variables: input,
|
||||
});
|
||||
|
||||
return response?.data?.customers?.at(0);
|
||||
}
|
||||
|
||||
type AddCustomerMasterInput = Pick<GQL.CreateCustomerMutationVariables, 'phone' | 'telegramId'> & {
|
||||
|
||||
@ -5,36 +5,28 @@ import * as GQL from '../types';
|
||||
export async function createSlot(input: GQL.CreateSlotMutationVariables['input']) {
|
||||
const { mutate } = await getClientWithToken();
|
||||
|
||||
// TODO: check slot does not overlap with others
|
||||
|
||||
return mutate({
|
||||
mutation: GQL.CreateSlotDocument,
|
||||
variables: { input },
|
||||
}).catch((err) => {
|
||||
console.error(JSON.stringify(err, null, 2));
|
||||
});
|
||||
}
|
||||
|
||||
export async function getSlots(input: GQL.GetSlotsQueryVariables) {
|
||||
const { query } = await getClientWithToken();
|
||||
|
||||
const response = await query({
|
||||
return query({
|
||||
query: GQL.GetSlotsDocument,
|
||||
variables: input,
|
||||
});
|
||||
|
||||
return response?.data?.slots;
|
||||
}
|
||||
|
||||
export async function getSlot(input: GQL.GetSlotQueryVariables) {
|
||||
const { query } = await getClientWithToken();
|
||||
|
||||
const response = await query({
|
||||
return query({
|
||||
query: GQL.GetSlotDocument,
|
||||
variables: input,
|
||||
});
|
||||
|
||||
return response?.data;
|
||||
}
|
||||
|
||||
export async function updateSlot(input: GQL.UpdateSlotMutationVariables) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user