From 25c90984dc9747cabed9528e5e1706591e13a3d6 Mon Sep 17 00:00:00 2001 From: vchikalkin Date: Tue, 10 Jun 2025 17:11:55 +0300 Subject: [PATCH] fix queries, using formatDate & formatTime on client --- .../orders/order-form/datetime-select.tsx | 3 +- .../orders/order-form/submit-button.tsx | 5 +-- .../components/orders/orders-list/index.tsx | 5 +-- .../day-slots-list/day-slot-add-form.tsx | 7 +++-- .../schedule/day-slots-list/index.tsx | 3 +- .../schedule/slot-datetime/slot-date.tsx | 2 +- .../schedule/slot-datetime/slot-time.tsx | 5 ++- .../components/shared/time-range/readonly.tsx | 2 +- apps/web/package.json | 1 + packages/graphql/api/orders.ts | 18 +++-------- packages/graphql/api/slots.ts | 25 ++------------- packages/graphql/package.json | 1 + packages/utils/eslint.config.js | 9 ++++++ packages/utils/package.json | 23 ++++++++++++++ .../utils => utils/src}/datetime-format.ts | 0 packages/utils/tsconfig.json | 13 ++++++++ pnpm-lock.yaml | 31 +++++++++++++++++++ 17 files changed, 106 insertions(+), 47 deletions(-) create mode 100644 packages/utils/eslint.config.js create mode 100644 packages/utils/package.json rename packages/{graphql/utils => utils/src}/datetime-format.ts (100%) create mode 100644 packages/utils/tsconfig.json diff --git a/apps/web/components/orders/order-form/datetime-select.tsx b/apps/web/components/orders/order-form/datetime-select.tsx index 8e2befb..7411206 100644 --- a/apps/web/components/orders/order-form/datetime-select.tsx +++ b/apps/web/components/orders/order-form/datetime-select.tsx @@ -4,6 +4,7 @@ import { useAvailableTimeSlotsQuery } from '@/hooks/api/slots'; import { useOrderStore } from '@/stores/order'; import { Button } from '@repo/ui/components/ui/button'; import { Calendar } from '@repo/ui/components/ui/calendar'; +import { formatDate } from '@repo/utils/datetime-format'; import dayjs from 'dayjs'; export function DateSelect() { @@ -47,7 +48,7 @@ export function TimeSelect() { { filters: { date: { - eq: date, + eq: formatDate(date).db(), }, master: { documentId: { diff --git a/apps/web/components/orders/order-form/submit-button.tsx b/apps/web/components/orders/order-form/submit-button.tsx index 464fafb..94b399b 100644 --- a/apps/web/components/orders/order-form/submit-button.tsx +++ b/apps/web/components/orders/order-form/submit-button.tsx @@ -4,6 +4,7 @@ import { useOrderCreate } from '@/hooks/api/orders'; import { useOrderStore } from '@/stores/order'; import { Button } from '@repo/ui/components/ui/button'; import { LoadingSpinner } from '@repo/ui/components/ui/spinner'; +import { formatDate, formatTime } from '@repo/utils/datetime-format'; import { useEffect } from 'react'; export function SubmitButton() { @@ -18,10 +19,10 @@ export function SubmitButton() { createOrder({ input: { client: clientId, - date, + date: formatDate(date).db(), services: [serviceId], slot: slotId, - time_start: time, + time_start: formatTime(time).db(), }, }); }; diff --git a/apps/web/components/orders/orders-list/index.tsx b/apps/web/components/orders/orders-list/index.tsx index 27c66e6..305c861 100644 --- a/apps/web/components/orders/orders-list/index.tsx +++ b/apps/web/components/orders/orders-list/index.tsx @@ -6,6 +6,7 @@ import { useCustomerQuery } from '@/hooks/api/customers'; import { useOrdersQuery } from '@/hooks/api/orders'; import { useDateTimeStore } from '@/stores/datetime'; import { Enum_Customer_Role } from '@repo/graphql/types'; +import { formatDate } from '@repo/utils/datetime-format'; export function ClientsOrdersList() { const { data: { customer } = {} } = useCustomerQuery(); @@ -19,7 +20,7 @@ export function ClientsOrdersList() { filters: { slot: { date: { - eq: selectedDate, + eq: formatDate(selectedDate).db(), }, master: { documentId: { @@ -57,7 +58,7 @@ export function OrdersList() { }, slot: { date: { - eq: selectedDate, + eq: formatDate(selectedDate).db(), }, }, }, diff --git a/apps/web/components/schedule/day-slots-list/day-slot-add-form.tsx b/apps/web/components/schedule/day-slots-list/day-slot-add-form.tsx index cb74176..62c0161 100644 --- a/apps/web/components/schedule/day-slots-list/day-slot-add-form.tsx +++ b/apps/web/components/schedule/day-slots-list/day-slot-add-form.tsx @@ -8,6 +8,7 @@ import { ScheduleStoreProvider, useScheduleStore } from '@/stores/schedule'; import { withContext } from '@/utils/context'; import { Enum_Slot_State } from '@repo/graphql/types'; import { Button } from '@repo/ui/components/ui/button'; +import { formatDate, formatTime } from '@repo/utils/datetime-format'; import { PlusSquare } from 'lucide-react'; import { type FormEvent } from 'react'; @@ -24,10 +25,10 @@ export const DaySlotAddForm = withContext(ScheduleStoreProvider)(function () { if (startTime && endTime) { addSlot({ input: { - date: selectedDate, + date: formatDate(selectedDate).db(), state: Enum_Slot_State.Open, - time_end: endTime, - time_start: startTime, + time_end: formatTime(endTime).db(), + time_start: formatTime(startTime).db(), }, }); diff --git a/apps/web/components/schedule/day-slots-list/index.tsx b/apps/web/components/schedule/day-slots-list/index.tsx index 9e24619..1485cc8 100644 --- a/apps/web/components/schedule/day-slots-list/index.tsx +++ b/apps/web/components/schedule/day-slots-list/index.tsx @@ -5,12 +5,13 @@ import { SlotCard } from './slot-card'; import { useSlotsQuery } from '@/hooks/api/slots'; import { useDateTimeStore } from '@/stores/datetime'; import { LoadingSpinner } from '@repo/ui/components/ui/spinner'; +import { formatDate } from '@repo/utils/datetime-format'; export function DaySlotsList() { const selectedDate = useDateTimeStore((store) => store.date); const { data: { slots } = {}, isLoading } = useSlotsQuery({ - filters: { date: { eq: selectedDate } }, + filters: { date: { eq: formatDate(selectedDate).db() } }, }); if (isLoading) return ; diff --git a/apps/web/components/schedule/slot-datetime/slot-date.tsx b/apps/web/components/schedule/slot-datetime/slot-date.tsx index d967f69..996e594 100644 --- a/apps/web/components/schedule/slot-datetime/slot-date.tsx +++ b/apps/web/components/schedule/slot-datetime/slot-date.tsx @@ -2,7 +2,7 @@ import { type SlotComponentProps } from '../types'; import { useSlotQuery } from '@/hooks/api/slots'; -import { formatDate } from '@repo/graphql/utils/datetime-format'; +import { formatDate } from '@repo/utils/datetime-format'; export function SlotDate({ documentId }: Readonly) { const { data: { slot } = {} } = useSlotQuery({ documentId }); diff --git a/apps/web/components/schedule/slot-datetime/slot-time.tsx b/apps/web/components/schedule/slot-datetime/slot-time.tsx index aac8b15..fb585c4 100644 --- a/apps/web/components/schedule/slot-datetime/slot-time.tsx +++ b/apps/web/components/schedule/slot-datetime/slot-time.tsx @@ -6,6 +6,7 @@ import { EditableTimeRangeForm, ReadonlyTimeRange } from '@/components/shared/ti import { useSlotMutation, useSlotQuery } from '@/hooks/api/slots'; import { useScheduleStore } from '@/stores/schedule'; import { Button } from '@repo/ui/components/ui/button'; +import { formatTime } from '@repo/utils/datetime-format'; import { PencilLine } from 'lucide-react'; import { useEffect } from 'react'; @@ -32,7 +33,9 @@ function SlotTimeEditForm({ documentId }: Readonly) { }, [editMode, setEndTime, setStartTime, slot]); function handleSubmit() { - updateSlot({ data: { time_end: endTime, time_start: startTime } }); + updateSlot({ + data: { time_end: formatTime(endTime).db(), time_start: formatTime(startTime).db() }, + }); resetTime(); setEditMode(false); } diff --git a/apps/web/components/shared/time-range/readonly.tsx b/apps/web/components/shared/time-range/readonly.tsx index be11032..4aecf6f 100644 --- a/apps/web/components/shared/time-range/readonly.tsx +++ b/apps/web/components/shared/time-range/readonly.tsx @@ -1,5 +1,5 @@ -import { formatTime } from '@repo/graphql/utils/datetime-format'; import { cn } from '@repo/ui/lib/utils'; +import { formatTime } from '@repo/utils/datetime-format'; type TimeRangeProps = { readonly className?: string; diff --git a/apps/web/package.json b/apps/web/package.json index 86df62d..b008e96 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -15,6 +15,7 @@ }, "dependencies": { "@repo/ui": "workspace:*", + "@repo/utils": "workspace:", "@tanstack/react-query": "^5.64.1", "@telegram-apps/sdk-react": "^2.0.19", "dayjs": "catalog:", diff --git a/packages/graphql/api/orders.ts b/packages/graphql/api/orders.ts index a6a3a1e..f6fccbb 100644 --- a/packages/graphql/api/orders.ts +++ b/packages/graphql/api/orders.ts @@ -2,12 +2,12 @@ import { getClientWithToken } from '../apollo/client'; import * as GQL from '../types'; import { Enum_Customer_Role, Enum_Slot_State } from '../types'; -import { formatDate, formatTime, sumTime } from '../utils/datetime-format'; import { BaseService } from './base'; import { CustomersService } from './customers'; import { ServicesService } from './services'; import { SlotsService } from './slots'; import { type VariablesOf } from '@graphql-typed-document-node/core'; +import { formatTime, sumTime } from '@repo/utils/datetime-format'; const ERRORS = { INVALID_CLIENT: 'Invalid client', @@ -48,6 +48,7 @@ export class OrdersService extends BaseService { } const masters = await customersService.getMasters(this.customer); + const masterId = slot?.master?.documentId; if (!masters.customers.some((master) => master?.documentId === masterId)) { throw new Error(ERRORS.INVALID_MASTER); @@ -68,17 +69,17 @@ export class OrdersService extends BaseService { if (!service?.duration) throw new Error(ERRORS.INVALID_SERVICE_DURATION); const endTime = sumTime(variables.input.time_start, service?.duration); + const { mutate } = await getClientWithToken(); + const mutationResult = await mutate({ mutation: GQL.CreateOrderDocument, variables: { input: { client: variables.input.client, - date: formatDate(variables.input.date).db(), services: variables.input.services, slot: variables.input.slot, time_end: formatTime(endTime).db(), - time_start: formatTime(variables.input.time_start).db(), }, }, }); @@ -105,16 +106,7 @@ export class OrdersService extends BaseService { const result = await query({ query: GQL.GetOrdersDocument, - variables: { - filters: { - ...variables.filters, - date: { eq: formatDate(variables?.filters?.date?.eq).db() }, - slot: { - ...variables.filters?.slot, - date: { eq: formatDate(variables?.filters?.slot?.date?.eq).db() }, - }, - }, - }, + variables, }); return result.data; diff --git a/packages/graphql/api/slots.ts b/packages/graphql/api/slots.ts index f6a33f4..79369e0 100644 --- a/packages/graphql/api/slots.ts +++ b/packages/graphql/api/slots.ts @@ -1,10 +1,10 @@ import { getClientWithToken } from '../apollo/client'; import * as GQL from '../types'; -import { formatDate, formatTime, getMinutes } from '../utils/datetime-format'; import { BaseService } from './base'; import { CustomersService } from './customers'; import { ServicesService } from './services'; import { type VariablesOf } from '@graphql-typed-document-node/core'; +import { getMinutes } from '@repo/utils/datetime-format'; import dayjs from 'dayjs'; export class SlotsService extends BaseService { @@ -21,10 +21,7 @@ export class SlotsService extends BaseService { ...variables, input: { ...variables.input, - date: formatDate(variables.input.date).db(), master: customer?.documentId, - time_end: variables.input.time_end && formatTime(variables.input.time_end).db(), - time_start: variables.input.time_start && formatTime(variables.input.time_start).db(), }, }, }); @@ -60,7 +57,6 @@ export class SlotsService extends BaseService { variables: { filters: { ...variables.filters, - date: { eq: formatDate(variables?.filters?.date?.eq).db() }, state: { eq: GQL.Enum_Slot_State.Open }, }, }, @@ -127,12 +123,7 @@ export class SlotsService extends BaseService { const result = await query({ query: GQL.GetSlotsDocument, - variables: { - filters: { - ...variables.filters, - date: { eq: formatDate(variables?.filters?.date?.eq).db() }, - }, - }, + variables, }); return result.data; @@ -143,17 +134,7 @@ export class SlotsService extends BaseService { const mutationResult = await mutate({ mutation: GQL.UpdateSlotDocument, - variables: { - ...variables, - data: { - ...variables.data, - date: variables.data?.date ? formatDate(variables.data.date).db() : undefined, - time_end: variables.data?.time_end ? formatTime(variables.data.time_end).db() : undefined, - time_start: variables.data?.time_start - ? formatTime(variables.data.time_start).db() - : undefined, - }, - }, + variables, }); const error = mutationResult.errors?.at(0); diff --git a/packages/graphql/package.json b/packages/graphql/package.json index 796dd06..c7708f9 100644 --- a/packages/graphql/package.json +++ b/packages/graphql/package.json @@ -9,6 +9,7 @@ }, "dependencies": { "@apollo/client": "catalog:", + "@repo/utils": "workspace:", "dayjs": "catalog:", "jsonwebtoken": "catalog:", "radashi": "catalog:", diff --git a/packages/utils/eslint.config.js b/packages/utils/eslint.config.js new file mode 100644 index 0000000..3fb0644 --- /dev/null +++ b/packages/utils/eslint.config.js @@ -0,0 +1,9 @@ +import { typescript } from '@repo/eslint-config/typescript'; + +/** @type {import("eslint").Linter.Config} */ +export default [ + ...typescript, + { + ignores: ['**/types/**'], + }, +]; diff --git a/packages/utils/package.json b/packages/utils/package.json new file mode 100644 index 0000000..9c2a5b7 --- /dev/null +++ b/packages/utils/package.json @@ -0,0 +1,23 @@ +{ + "name": "@repo/utils", + "version": "0.0.0", + "license": "MIT", + "type": "module", + "scripts": { + "test:unit": "vitest" + }, + "exports": { + "./datetime-format": "./src/datetime-format.ts" + }, + "dependencies": { + "dayjs": "catalog:", + "radashi": "catalog:", + "zod": "catalog:" + }, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*", + "vite-tsconfig-paths": "catalog:", + "vitest": "catalog:" + } +} diff --git a/packages/graphql/utils/datetime-format.ts b/packages/utils/src/datetime-format.ts similarity index 100% rename from packages/graphql/utils/datetime-format.ts rename to packages/utils/src/datetime-format.ts diff --git a/packages/utils/tsconfig.json b/packages/utils/tsconfig.json new file mode 100644 index 0000000..c106372 --- /dev/null +++ b/packages/utils/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@repo/typescript-config/base.json", + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": ["./*"] + }, + "moduleResolution": "bundler", + "module": "ES2022" + }, + "include": ["."], + "exclude": ["dist", "build", "node_modules"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 71e50bf..14a8d1e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -147,6 +147,9 @@ importers: '@repo/ui': specifier: workspace:* version: link:../../packages/ui + '@repo/utils': + specifier: 'workspace:' + version: link:../../packages/utils '@tanstack/react-query': specifier: ^5.64.1 version: 5.64.1(react@19.1.0) @@ -274,6 +277,9 @@ importers: '@apollo/client': specifier: 'catalog:' version: 3.12.4(@types/react@19.1.2)(graphql-ws@5.16.0(graphql@16.9.0))(graphql@16.9.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@repo/utils': + specifier: 'workspace:' + version: link:../utils dayjs: specifier: 'catalog:' version: 1.11.13 @@ -413,6 +419,31 @@ importers: specifier: 'catalog:' version: 5.7.2 + packages/utils: + dependencies: + dayjs: + specifier: 'catalog:' + version: 1.11.13 + radashi: + specifier: 'catalog:' + version: 12.5.1 + zod: + specifier: 'catalog:' + version: 3.24.1 + devDependencies: + '@repo/eslint-config': + specifier: workspace:* + version: link:../eslint-config + '@repo/typescript-config': + specifier: workspace:* + version: link:../typescript-config + vite-tsconfig-paths: + specifier: 'catalog:' + version: 5.1.4(typescript@5.7.2)(vite@5.4.11(@types/node@20.17.8)) + vitest: + specifier: 'catalog:' + version: 2.1.8(@types/node@20.17.8)(jsdom@25.0.1)(msw@2.7.0(@types/node@20.17.8)(typescript@5.7.2)) + packages: '@alloc/quick-lru@5.2.0':