Vlad Chikalkin ccfc65ca9b
Fix/bugs features pt 2 (#58)
* refactor(profile): comment out change role feature

* refactor(orders): update OrderServices and ServiceSelect components to utilize ServiceCard, and enhance service fields with duration in GraphQL types

* refactor(schedule): implement forbidden order states to disable editing slots with active orders

* fix(deploy): update SSH configuration to use dynamic port from secrets for improved flexibility

* refactor(api/orders): simplify order creation logic by removing unnecessary validations and improving error handling

* refactor(contact-row): replace role display logic with useIsMaster hook for improved clarity

* refactor(profile/orders-list): update header text from "Общие записи" to "Недавние записи" for better clarity
gql: GetOrders add sort slot.date:desc

* refactor(profile/orders-list): enhance OrderCard component by adding avatarSource prop based on user role

* feat(order-form): implement date selection with event highlighting and monthly view for available time slots

* refactor(i18n/config): update timeZone from 'Europe/Amsterdam' to 'Europe/Moscow'

* refactor(order-form/datetime-select): enhance date selection logic to include slot availability check

* refactor(datetime-format): integrate dayjs timezone support with default Moscow timezone for date and time formatting

* fix(contact-row): replace useIsMaster hook with isCustomerMaster utility for role display logic

* refactor(service-card): replace formatTime with getMinutes for duration display

* refactor(order-datetime): update date and time handling to use datetime_start and datetime_end for improved consistency

* refactor(profile): streamline profile and slot pages by integrating session user retrieval and updating booking logic with BookButton component

* fix(navigation): append query parameter to bottom-nav links and enhance back navigation logic in success page
2025-07-18 17:11:43 +03:00

146 lines
4.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { getClientWithToken } from '../apollo/client';
import * as GQL from '../types';
import { BaseService } from './base';
import { CustomersService } from './customers';
import { NotifyService } from './notify';
import { ServicesService } from './services';
import { type VariablesOf } from '@graphql-typed-document-node/core';
import { isCustomerMaster } from '@repo/utils/customer';
import { getMinutes } from '@repo/utils/datetime-format';
import dayjs from 'dayjs';
const ERRORS = {
INVALID_SERVICE_DURATION: 'Invalid service duration',
MISSING_CLIENT: 'Missing client',
MISSING_ORDER: 'Order not found',
MISSING_SERVICE_ID: 'Missing service id',
MISSING_SERVICES: 'Missing services',
MISSING_SLOT: 'Missing slot id',
MISSING_START_TIME: 'Missing time start',
MISSING_USER: 'User not found',
NO_PERMISSION: 'No permission',
};
export class OrdersService extends BaseService {
async createOrder(variables: VariablesOf<typeof GQL.CreateOrderDocument>) {
// Проверки на существование обязательных полей для предотвращения ошибок типов
if (!variables.input.slot) throw new Error(ERRORS.MISSING_SLOT);
if (!variables.input.services?.length) throw new Error(ERRORS.MISSING_SERVICES);
if (!variables.input.services[0]) throw new Error(ERRORS.MISSING_SERVICE_ID);
if (!variables.input.datetime_start) throw new Error(ERRORS.MISSING_START_TIME);
if (!variables.input.client) throw new Error(ERRORS.MISSING_CLIENT);
const customersService = new CustomersService(this.customer);
const servicesService = new ServicesService(this.customer);
const { customer } = await customersService.getCustomer(this.customer);
if (!customer) throw new Error(ERRORS.MISSING_USER);
const { service } = await servicesService.getService({
documentId: variables.input.services[0],
});
if (!service?.duration) throw new Error(ERRORS.INVALID_SERVICE_DURATION);
const datetimeEnd = dayjs(variables.input.datetime_start)
.add(getMinutes(service.duration), 'minute')
.toISOString();
const { mutate } = await getClientWithToken();
const mutationResult = await mutate({
mutation: GQL.CreateOrderDocument,
variables: {
...variables,
input: {
...variables.input,
datetime_end: datetimeEnd,
state: isCustomerMaster(customer)
? GQL.Enum_Order_State.Approved
: GQL.Enum_Order_State.Created,
},
},
});
const error = mutationResult.errors?.at(0);
if (error) throw new Error(error.message);
// Уведомление об создании заказа
const notifyService = new NotifyService(this.customer);
notifyService.orderCreated(variables, isCustomerMaster(customer));
return mutationResult.data;
}
async getOrder(variables: VariablesOf<typeof GQL.GetOrderDocument>) {
const { query } = await getClientWithToken();
const result = await query({
query: GQL.GetOrderDocument,
variables,
});
return result.data;
}
async getOrders(variables: VariablesOf<typeof GQL.GetOrdersDocument>) {
const { query } = await getClientWithToken();
const result = await query({
query: GQL.GetOrdersDocument,
variables,
});
return result.data;
}
async updateOrder(variables: VariablesOf<typeof GQL.UpdateOrderDocument>) {
const customersService = new CustomersService(this.customer);
const { customer } = await customersService.getCustomer(this.customer);
if (!customer) throw new Error(ERRORS.MISSING_USER);
const { query } = await getClientWithToken();
const {
data: { order },
} = await query({
query: GQL.GetOrderDocument,
variables: { documentId: variables.documentId },
});
if (!order) throw new Error(ERRORS.MISSING_ORDER);
const isOrderClient = order.client?.documentId === customer.documentId;
const isOrderMaster = order.slot?.master?.documentId === customer.documentId;
if (!isOrderClient && !isOrderMaster) throw new Error(ERRORS.NO_PERMISSION);
if (isOrderClient && Object.keys(variables.data).length > 1)
throw new Error(ERRORS.NO_PERMISSION);
if (
isOrderClient &&
variables.data.state &&
variables.data.state !== GQL.Enum_Order_State.Cancelling
) {
throw new Error(ERRORS.NO_PERMISSION);
}
const { mutate } = await getClientWithToken();
const mutationResult = await mutate({
mutation: GQL.UpdateOrderDocument,
variables,
});
const error = mutationResult.errors?.at(0);
if (error) throw new Error(error.message);
// Уведомление об изменении заказа
const notifyService = new NotifyService(this.customer);
notifyService.orderUpdated(variables);
return mutationResult.data;
}
}