refactor(contacts): rename masters to invited and update related functionality
- Changed the terminology from "masters" to "invited" and "invitedBy" across the codebase for clarity and consistency. - Updated the `addContact` function to reflect the new naming convention. - Refactored API actions and server methods to support the new invited structure. - Adjusted components and hooks to utilize the updated invited data, enhancing user experience and simplifying logic.
This commit is contained in:
parent
5dfef524e2
commit
0b188ee5ed
@ -57,9 +57,9 @@ export async function addContact(conversation: Conversation<Context, Context>, c
|
||||
if (!documentId) throw new Error('Клиент не создан');
|
||||
}
|
||||
|
||||
// Добавляем текущего мастера к клиенту
|
||||
const masters = [customer.documentId];
|
||||
await customerService.addMasters({ data: { masters }, documentId });
|
||||
// Добавляем текущего пользователя к приглашенному
|
||||
const invitedBy = [customer.documentId];
|
||||
await customerService.addInvitedBy({ data: { invitedBy }, documentId });
|
||||
|
||||
// Отправляем подтверждения и инструкции
|
||||
await ctx.reply(await conversation.external(({ t }) => t('msg-contact-added', { name })));
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import * as customers from './server/customers';
|
||||
import { wrapClientAction } from '@/utils/actions';
|
||||
|
||||
export const addMasters = wrapClientAction(customers.addMasters);
|
||||
export const getClients = wrapClientAction(customers.getClients);
|
||||
export const addInvitedBy = wrapClientAction(customers.addInvitedBy);
|
||||
export const getInvited = wrapClientAction(customers.getInvited);
|
||||
export const getCustomer = wrapClientAction(customers.getCustomer);
|
||||
export const getMasters = wrapClientAction(customers.getMasters);
|
||||
export const getInvitedBy = wrapClientAction(customers.getInvitedBy);
|
||||
export const updateCustomer = wrapClientAction(customers.updateCustomer);
|
||||
|
||||
@ -6,16 +6,10 @@ import { CustomersService } from '@repo/graphql/api/customers';
|
||||
|
||||
const getService = useService(CustomersService);
|
||||
|
||||
export async function addMasters(...variables: Parameters<CustomersService['addMasters']>) {
|
||||
export async function addInvitedBy(...variables: Parameters<CustomersService['addInvitedBy']>) {
|
||||
const service = await getService();
|
||||
|
||||
return wrapServerAction(() => service.addMasters(...variables));
|
||||
}
|
||||
|
||||
export async function getClients(...variables: Parameters<CustomersService['getClients']>) {
|
||||
const service = await getService();
|
||||
|
||||
return wrapServerAction(() => service.getClients(...variables));
|
||||
return wrapServerAction(() => service.addInvitedBy(...variables));
|
||||
}
|
||||
|
||||
export async function getCustomer(...variables: Parameters<CustomersService['getCustomer']>) {
|
||||
@ -24,10 +18,16 @@ export async function getCustomer(...variables: Parameters<CustomersService['get
|
||||
return wrapServerAction(() => service.getCustomer(...variables));
|
||||
}
|
||||
|
||||
export async function getMasters(...variables: Parameters<CustomersService['getMasters']>) {
|
||||
export async function getInvited(...variables: Parameters<CustomersService['getInvited']>) {
|
||||
const service = await getService();
|
||||
|
||||
return wrapServerAction(() => service.getMasters(...variables));
|
||||
return wrapServerAction(() => service.getInvited(...variables));
|
||||
}
|
||||
|
||||
export async function getInvitedBy(...variables: Parameters<CustomersService['getInvitedBy']>) {
|
||||
const service = await getService();
|
||||
|
||||
return wrapServerAction(() => service.getInvitedBy(...variables));
|
||||
}
|
||||
|
||||
export async function updateCustomer(...variables: Parameters<CustomersService['updateCustomer']>) {
|
||||
|
||||
@ -13,8 +13,8 @@ import { use } from 'react';
|
||||
|
||||
const filterLabels: Record<FilterType, string> = {
|
||||
all: 'Все',
|
||||
clients: 'Клиенты',
|
||||
masters: 'Мастера',
|
||||
invited: 'Приглашенные',
|
||||
invitedBy: 'Кто пригласил',
|
||||
};
|
||||
|
||||
export function ContactsFilter() {
|
||||
@ -30,8 +30,8 @@ export function ContactsFilter() {
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuItem onClick={() => setFilter('all')}>Все</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => setFilter('clients')}>Клиенты</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => setFilter('masters')}>Мастера</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => setFilter('invited')}>Приглашенные</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => setFilter('invitedBy')}>Кто пригласил</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
|
||||
@ -86,13 +86,13 @@ export function ContactsGridBase({ contacts, onSelect, selected, title }: Contac
|
||||
);
|
||||
}
|
||||
|
||||
export const MastersGrid = withContext(ContactsContextProvider)(function () {
|
||||
export const InvitedByGrid = withContext(ContactsContextProvider)(function () {
|
||||
const { contacts, isLoading, setFilter } = useCustomerContacts();
|
||||
const masterId = useOrderStore((store) => store.masterId);
|
||||
const setMasterId = useOrderStore((store) => store.setMasterId);
|
||||
|
||||
useEffect(() => {
|
||||
setFilter('masters');
|
||||
setFilter('invitedBy');
|
||||
}, [setFilter]);
|
||||
|
||||
if (isLoading) return <LoadingSpinner />;
|
||||
@ -102,18 +102,18 @@ export const MastersGrid = withContext(ContactsContextProvider)(function () {
|
||||
contacts={contacts}
|
||||
onSelect={(contactId) => setMasterId(contactId)}
|
||||
selected={masterId}
|
||||
title="Мастера"
|
||||
title="Кто пригласил"
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
export const ClientsGrid = withContext(ContactsContextProvider)(function () {
|
||||
export const InvitedGrid = withContext(ContactsContextProvider)(function () {
|
||||
const { contacts, isLoading, setFilter } = useCustomerContacts();
|
||||
const clientId = useOrderStore((store) => store.clientId);
|
||||
const setClientId = useOrderStore((store) => store.setClientId);
|
||||
|
||||
useEffect(() => {
|
||||
setFilter('clients');
|
||||
setFilter('invited');
|
||||
}, [setFilter]);
|
||||
|
||||
if (isLoading) return <LoadingSpinner />;
|
||||
@ -123,7 +123,7 @@ export const ClientsGrid = withContext(ContactsContextProvider)(function () {
|
||||
contacts={contacts}
|
||||
onSelect={(contactId) => setClientId(contactId)}
|
||||
selected={clientId}
|
||||
title="Клиенты"
|
||||
title="Приглашенные"
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { BackButton } from './back-button';
|
||||
import { ClientsGrid, MastersGrid } from './contacts-grid';
|
||||
import { InvitedGrid, InvitedByGrid } from './contacts-grid';
|
||||
import { DateTimeSelect } from './datetime-select';
|
||||
import { NextButton } from './next-button';
|
||||
import { ErrorPage, SuccessPage } from './result';
|
||||
@ -15,10 +15,10 @@ import { LoadingSpinner } from '@repo/ui/components/ui/spinner';
|
||||
import { type JSX } from 'react';
|
||||
|
||||
const STEP_COMPONENTS: Record<string, JSX.Element> = {
|
||||
'client-select': <ClientsGrid />,
|
||||
'client-select': <InvitedGrid />,
|
||||
'datetime-select': <DateTimeSelect />,
|
||||
error: <ErrorPage />,
|
||||
'master-select': <MastersGrid />,
|
||||
'master-select': <InvitedByGrid />,
|
||||
'service-select': <ServicesSelect />,
|
||||
success: <SuccessPage />,
|
||||
};
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
import { createContext, type PropsWithChildren, useMemo, useState } from 'react';
|
||||
|
||||
export type FilterType = 'all' | 'clients' | 'masters';
|
||||
export type FilterType = 'all' | 'invited' | 'invitedBy';
|
||||
|
||||
type ContextType = { filter: FilterType; setFilter: (filter: FilterType) => void };
|
||||
|
||||
|
||||
@ -1,23 +1,23 @@
|
||||
import { getClients, getMasters } from '@/actions/api/customers';
|
||||
import { getInvited, getInvitedBy } from '@/actions/api/customers';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useSession } from 'next-auth/react';
|
||||
|
||||
export const useClientsQuery = (props?: Parameters<typeof getClients>[0]) => {
|
||||
export const useInvitedQuery = (props?: Parameters<typeof getInvited>[0]) => {
|
||||
const { data: session } = useSession();
|
||||
const telegramId = props?.telegramId || session?.user?.telegramId;
|
||||
|
||||
return useQuery({
|
||||
queryFn: () => getClients({ telegramId }),
|
||||
queryKey: ['customer', 'telegramId', telegramId, 'clients'],
|
||||
queryFn: () => getInvited({ telegramId }),
|
||||
queryKey: ['customer', 'telegramId', telegramId, 'invited'],
|
||||
});
|
||||
};
|
||||
|
||||
export const useMastersQuery = (props?: Parameters<typeof getMasters>[0]) => {
|
||||
export const useInvitedByQuery = (props?: Parameters<typeof getInvitedBy>[0]) => {
|
||||
const { data: session } = useSession();
|
||||
const telegramId = props?.telegramId || session?.user?.telegramId;
|
||||
|
||||
return useQuery({
|
||||
queryFn: () => getMasters({ telegramId }),
|
||||
queryKey: ['customer', 'telegramId', telegramId, 'masters'],
|
||||
queryFn: () => getInvitedBy({ telegramId }),
|
||||
queryKey: ['customer', 'telegramId', telegramId, 'invitedBy'],
|
||||
});
|
||||
};
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import { useClientsQuery, useMastersQuery } from './query';
|
||||
import { useInvitedByQuery, useInvitedQuery } from './query';
|
||||
import { ContactsContext } from '@/context/contacts';
|
||||
import { sift } from 'radashi';
|
||||
import { use, useEffect, useMemo } from 'react';
|
||||
@ -9,39 +9,39 @@ export function useCustomerContacts() {
|
||||
const { filter, setFilter } = use(ContactsContext);
|
||||
|
||||
const {
|
||||
data: clientsData,
|
||||
isLoading: isLoadingClients,
|
||||
refetch: refetchClients,
|
||||
} = useClientsQuery();
|
||||
data: invitedData,
|
||||
isLoading: isLoadingInvited,
|
||||
refetch: refetchInvited,
|
||||
} = useInvitedQuery();
|
||||
|
||||
const {
|
||||
data: mastersData,
|
||||
isLoading: isLoadingMasters,
|
||||
refetch: refetchMasters,
|
||||
} = useMastersQuery();
|
||||
data: invitedByData,
|
||||
isLoading: isLoadingInvitedBy,
|
||||
refetch: refetchInvitedBy,
|
||||
} = useInvitedByQuery();
|
||||
|
||||
const clients = clientsData?.clients || [];
|
||||
const masters = mastersData?.masters || [];
|
||||
const invited = invitedData?.invited || [];
|
||||
const invitedBy = invitedByData?.invitedBy || [];
|
||||
|
||||
const isLoading = isLoadingClients || isLoadingMasters;
|
||||
const isLoading = isLoadingInvited || isLoadingInvitedBy;
|
||||
|
||||
useEffect(() => {
|
||||
if (filter === 'clients') {
|
||||
refetchClients();
|
||||
} else if (filter === 'masters') {
|
||||
refetchMasters();
|
||||
if (filter === 'invited') {
|
||||
refetchInvited();
|
||||
} else if (filter === 'invitedBy') {
|
||||
refetchInvitedBy();
|
||||
} else {
|
||||
refetchClients();
|
||||
refetchMasters();
|
||||
refetchInvited();
|
||||
refetchInvitedBy();
|
||||
}
|
||||
}, [filter, refetchClients, refetchMasters]);
|
||||
}, [filter, refetchInvited, refetchInvitedBy]);
|
||||
|
||||
const contacts = useMemo(() => {
|
||||
if (filter === 'clients') return sift(clients);
|
||||
if (filter === 'masters') return sift(masters);
|
||||
if (filter === 'invited') return sift(invited);
|
||||
if (filter === 'invitedBy') return sift(invitedBy);
|
||||
|
||||
return [...sift(clients), ...sift(masters)];
|
||||
}, [clients, masters, filter]);
|
||||
return [...sift(invited), ...sift(invitedBy)];
|
||||
}, [invited, invitedBy, filter]);
|
||||
|
||||
return { contacts, filter, isLoading, setFilter };
|
||||
}
|
||||
|
||||
@ -5,10 +5,10 @@ import { BaseService } from './base';
|
||||
import { type VariablesOf } from '@graphql-typed-document-node/core';
|
||||
|
||||
export class CustomersService extends BaseService {
|
||||
async addMasters(variables: VariablesOf<typeof GQL.UpdateCustomerDocument>) {
|
||||
async addInvitedBy(variables: VariablesOf<typeof GQL.UpdateCustomerDocument>) {
|
||||
await this.checkIsBanned();
|
||||
|
||||
const newMasterIds = variables.data.masters;
|
||||
const newInvitedByIds = variables.data.invitedBy;
|
||||
|
||||
// Проверяем, что пользователь не пытается изменить поле bannedUntil
|
||||
if (variables.data.bannedUntil !== undefined) {
|
||||
@ -16,21 +16,23 @@ export class CustomersService extends BaseService {
|
||||
}
|
||||
|
||||
const { mutate, query } = await getClientWithToken();
|
||||
const getMastersResult = await query({
|
||||
query: GQL.GetMastersDocument,
|
||||
const getInvitedByResult = await query({
|
||||
query: GQL.GetInvitedByDocument,
|
||||
variables,
|
||||
});
|
||||
|
||||
const existingMasterIds = getMastersResult?.data?.customers
|
||||
const existingInvitedByIds = getInvitedByResult?.data?.customers
|
||||
?.at(0)
|
||||
?.masters.map((x) => x?.documentId);
|
||||
?.invitedBy.map((x) => x?.documentId);
|
||||
|
||||
const newMastersIds = [...new Set([...(existingMasterIds || []), ...(newMasterIds || [])])];
|
||||
const newInvitedByIdsList = [
|
||||
...new Set([...(existingInvitedByIds || []), ...(newInvitedByIds || [])]),
|
||||
];
|
||||
|
||||
const mutationResult = await mutate({
|
||||
mutation: GQL.UpdateCustomerDocument,
|
||||
variables: {
|
||||
data: { masters: newMastersIds },
|
||||
data: { invitedBy: newInvitedByIdsList },
|
||||
documentId: variables.documentId,
|
||||
},
|
||||
});
|
||||
@ -41,21 +43,6 @@ export class CustomersService extends BaseService {
|
||||
return mutationResult.data;
|
||||
}
|
||||
|
||||
async getClients(variables?: VariablesOf<typeof GQL.GetClientsDocument>) {
|
||||
await this.checkIsBanned();
|
||||
|
||||
const { query } = await getClientWithToken();
|
||||
|
||||
const result = await query({
|
||||
query: GQL.GetClientsDocument,
|
||||
variables,
|
||||
});
|
||||
|
||||
const customer = result.data.customers.at(0);
|
||||
|
||||
return customer;
|
||||
}
|
||||
|
||||
async getCustomer(variables: VariablesOf<typeof GQL.GetCustomerDocument>) {
|
||||
await this.checkIsBanned();
|
||||
|
||||
@ -71,13 +58,28 @@ export class CustomersService extends BaseService {
|
||||
return { customer };
|
||||
}
|
||||
|
||||
async getMasters(variables?: VariablesOf<typeof GQL.GetMastersDocument>) {
|
||||
async getInvited(variables?: VariablesOf<typeof GQL.GetInvitedDocument>) {
|
||||
await this.checkIsBanned();
|
||||
|
||||
const { query } = await getClientWithToken();
|
||||
|
||||
const result = await query({
|
||||
query: GQL.GetMastersDocument,
|
||||
query: GQL.GetInvitedDocument,
|
||||
variables,
|
||||
});
|
||||
|
||||
const customer = result.data.customers.at(0);
|
||||
|
||||
return customer;
|
||||
}
|
||||
|
||||
async getInvitedBy(variables?: VariablesOf<typeof GQL.GetInvitedByDocument>) {
|
||||
await this.checkIsBanned();
|
||||
|
||||
const { query } = await getClientWithToken();
|
||||
|
||||
const result = await query({
|
||||
query: GQL.GetInvitedByDocument,
|
||||
variables,
|
||||
});
|
||||
|
||||
|
||||
@ -121,8 +121,8 @@ describe('OrdersService', () => {
|
||||
getCustomer: vi.fn().mockResolvedValue({
|
||||
customer: mockCustomer,
|
||||
}),
|
||||
getMasters: vi.fn().mockResolvedValue({
|
||||
masters: [mockMaster],
|
||||
getInvitedBy: vi.fn().mockResolvedValue({
|
||||
invitedBy: [mockMaster],
|
||||
}),
|
||||
}));
|
||||
|
||||
@ -240,8 +240,8 @@ describe('OrdersService', () => {
|
||||
getCustomer: vi.fn().mockResolvedValue({
|
||||
customer: masterCustomer,
|
||||
}),
|
||||
getMasters: vi.fn().mockResolvedValue({
|
||||
masters: [masterCustomer],
|
||||
getInvitedBy: vi.fn().mockResolvedValue({
|
||||
invitedBy: [masterCustomer],
|
||||
}),
|
||||
}));
|
||||
|
||||
@ -381,8 +381,8 @@ describe('OrdersService', () => {
|
||||
});
|
||||
mockCustomersService.mockImplementation(() => ({
|
||||
getCustomer: mockGetCustomer,
|
||||
getMasters: vi.fn().mockResolvedValue({
|
||||
masters: [mockMaster],
|
||||
getInvitedBy: vi.fn().mockResolvedValue({
|
||||
invitedBy: [mockMaster],
|
||||
}),
|
||||
}));
|
||||
|
||||
@ -432,8 +432,8 @@ describe('OrdersService', () => {
|
||||
});
|
||||
mockCustomersService.mockImplementation(() => ({
|
||||
getCustomer: mockGetCustomer,
|
||||
getMasters: vi.fn().mockResolvedValue({
|
||||
masters: [mockMaster],
|
||||
getInvitedBy: vi.fn().mockResolvedValue({
|
||||
invitedBy: [mockMaster],
|
||||
}),
|
||||
}));
|
||||
|
||||
@ -468,8 +468,8 @@ describe('OrdersService', () => {
|
||||
});
|
||||
mockCustomersService.mockImplementation(() => ({
|
||||
getCustomer: mockGetCustomer,
|
||||
getMasters: vi.fn().mockResolvedValue({
|
||||
masters: [mockMaster],
|
||||
getInvitedBy: vi.fn().mockResolvedValue({
|
||||
invitedBy: [mockMaster],
|
||||
}),
|
||||
}));
|
||||
|
||||
@ -509,8 +509,8 @@ describe('OrdersService', () => {
|
||||
});
|
||||
mockCustomersService.mockImplementation(() => ({
|
||||
getCustomer: mockGetCustomer,
|
||||
getMasters: vi.fn().mockResolvedValue({
|
||||
masters: [mockMaster],
|
||||
getInvitedBy: vi.fn().mockResolvedValue({
|
||||
invitedBy: [mockMaster],
|
||||
}),
|
||||
}));
|
||||
|
||||
@ -555,8 +555,8 @@ describe('OrdersService', () => {
|
||||
});
|
||||
mockCustomersService.mockImplementation(() => ({
|
||||
getCustomer: mockGetCustomer,
|
||||
getMasters: vi.fn().mockResolvedValue({
|
||||
masters: [inactiveMaster],
|
||||
getInvitedBy: vi.fn().mockResolvedValue({
|
||||
invitedBy: [inactiveMaster],
|
||||
}),
|
||||
}));
|
||||
|
||||
@ -602,8 +602,8 @@ describe('OrdersService', () => {
|
||||
});
|
||||
mockCustomersService.mockImplementation(() => ({
|
||||
getCustomer: mockGetCustomer,
|
||||
getMasters: vi.fn().mockResolvedValue({
|
||||
masters: [activeCustomerAsMaster],
|
||||
getInvitedBy: vi.fn().mockResolvedValue({
|
||||
invitedBy: [activeCustomerAsMaster],
|
||||
}),
|
||||
}));
|
||||
|
||||
@ -638,8 +638,8 @@ describe('OrdersService', () => {
|
||||
});
|
||||
mockCustomersService.mockImplementation(() => ({
|
||||
getCustomer: mockGetCustomer,
|
||||
getMasters: vi.fn().mockResolvedValue({
|
||||
masters: [], // клиент не связан с мастером
|
||||
getInvitedBy: vi.fn().mockResolvedValue({
|
||||
invitedBy: [], // клиент не связан с мастером
|
||||
}),
|
||||
}));
|
||||
|
||||
@ -685,8 +685,8 @@ describe('OrdersService', () => {
|
||||
});
|
||||
mockCustomersService.mockImplementation(() => ({
|
||||
getCustomer: mockGetCustomer,
|
||||
getMasters: vi.fn().mockResolvedValue({
|
||||
masters: [mockMaster],
|
||||
getInvitedBy: vi.fn().mockResolvedValue({
|
||||
invitedBy: [mockMaster],
|
||||
}),
|
||||
}));
|
||||
|
||||
@ -726,8 +726,8 @@ describe('OrdersService', () => {
|
||||
});
|
||||
mockCustomersService.mockImplementation(() => ({
|
||||
getCustomer: mockGetCustomer,
|
||||
getMasters: vi.fn().mockResolvedValue({
|
||||
masters: [mockMaster],
|
||||
getInvitedBy: vi.fn().mockResolvedValue({
|
||||
invitedBy: [mockMaster],
|
||||
}),
|
||||
}));
|
||||
|
||||
|
||||
@ -33,7 +33,7 @@ query GetCustomer($phone: String, $telegramId: Long, $documentId: ID) {
|
||||
}
|
||||
}
|
||||
|
||||
query GetMasters($phone: String, $telegramId: Long, $documentId: ID) {
|
||||
query GetInvitedBy($phone: String, $telegramId: Long, $documentId: ID) {
|
||||
customers(
|
||||
filters: {
|
||||
or: [
|
||||
@ -45,13 +45,13 @@ query GetMasters($phone: String, $telegramId: Long, $documentId: ID) {
|
||||
}
|
||||
) {
|
||||
documentId
|
||||
masters {
|
||||
invitedBy {
|
||||
...CustomerFields
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query GetClients($phone: String, $telegramId: Long) {
|
||||
query GetInvited($phone: String, $telegramId: Long) {
|
||||
customers(
|
||||
filters: {
|
||||
or: [{ phone: { eq: $phone } }, { telegramId: { eq: $telegramId } }]
|
||||
@ -59,7 +59,7 @@ query GetClients($phone: String, $telegramId: Long) {
|
||||
}
|
||||
) {
|
||||
documentId
|
||||
clients {
|
||||
invited {
|
||||
...CustomerFields
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user