diff --git a/apps/web/actions/profile.ts b/apps/web/actions/profile.ts
new file mode 100644
index 0000000..93bd5f4
--- /dev/null
+++ b/apps/web/actions/profile.ts
@@ -0,0 +1,44 @@
+'use server';
+import { authOptions } from '@/config/auth';
+import { getCustomer, updateCustomerProfile } from '@repo/graphql/api';
+import { type CustomerInput, type Enum_Customer_Role } from '@repo/graphql/types';
+import { getServerSession } from 'next-auth/next';
+import { revalidatePath } from 'next/cache';
+
+export async function updateProfile(input: CustomerInput) {
+ const session = await getServerSession(authOptions);
+
+ if (session) {
+ const { user } = session;
+ const getCustomerResponse = await getCustomer({ telegramId: user?.telegramId });
+ const customer = getCustomerResponse.data.customers.at(0);
+ if (customer) {
+ await updateCustomerProfile({
+ data: input,
+ documentId: customer.documentId,
+ });
+ }
+ }
+
+ revalidatePath('/profile');
+}
+
+export async function updateRole(role: Enum_Customer_Role) {
+ const session = await getServerSession(authOptions);
+
+ if (session) {
+ const { user } = session;
+ const getCustomerResponse = await getCustomer({ telegramId: user?.telegramId });
+ const customer = getCustomerResponse.data.customers.at(0);
+ if (customer) {
+ await updateCustomerProfile({
+ data: {
+ role,
+ },
+ documentId: customer.documentId,
+ });
+ }
+ }
+
+ revalidatePath('/profile');
+}
diff --git a/apps/web/app/(auth)/browser/page.tsx b/apps/web/app/(auth)/browser/page.tsx
new file mode 100644
index 0000000..a989110
--- /dev/null
+++ b/apps/web/app/(auth)/browser/page.tsx
@@ -0,0 +1,31 @@
+/* eslint-disable promise/prefer-await-to-then */
+'use client';
+import { getTelegramUser } from '@/mocks/get-telegram-user';
+import { LoadingSpinner } from '@repo/ui/components/ui/spinner';
+import { signIn, useSession } from 'next-auth/react';
+import { useTheme } from 'next-themes';
+import { redirect } from 'next/navigation';
+import { useEffect } from 'react';
+
+export default function Auth() {
+ const { status } = useSession();
+ useTheme();
+
+ useEffect(() => {
+ if (status === 'authenticated') {
+ redirect('/profile');
+ }
+
+ if (status === 'unauthenticated' && process.env.NODE_ENV === 'development') {
+ getTelegramUser().then((user) => {
+ signIn('telegram', {
+ callbackUrl: '/profile',
+ redirect: false,
+ telegramId: String(user?.id),
+ });
+ });
+ }
+ }, [status]);
+
+ return ;
+}
diff --git a/apps/web/app/(auth)/page.tsx b/apps/web/app/(auth)/page.tsx
index 32d357a..82767ed 100644
--- a/apps/web/app/(auth)/page.tsx
+++ b/apps/web/app/(auth)/page.tsx
@@ -1,42 +1,12 @@
'use client';
-import { initData, isMiniAppDark, useSignal } from '@telegram-apps/sdk-react';
-import { signIn, useSession } from 'next-auth/react';
+import { useClientOnce } from '@/hooks/telegram';
+import { isTMA } from '@telegram-apps/sdk-react';
import { redirect } from 'next/navigation';
-import { useEffect } from 'react';
-export default function Auth() {
- const initDataState = useSignal(initData.state);
- const isDark = isMiniAppDark();
- const { data: session, status } = useSession();
+export default function Page() {
+ useClientOnce(() => {
+ const isTG = isTMA('simple');
- useEffect(() => {
- if (status === 'authenticated') {
- redirect('/profile');
- }
-
- if (status === 'unauthenticated' && initDataState?.user?.id) {
- signIn('telegram', {
- callbackUrl: '/profile',
- redirect: false,
- telegramId: String(initDataState.user.id),
- });
- }
- }, [initDataState, status]);
-
- if (status === 'loading') {
- return
Loading Auth...
;
- }
-
- return (
-
- {session ? (
-
- Hello, {JSON.stringify(session)}
- Dark: {JSON.stringify(isDark)}
-
- ) : (
-
Not authenticated
- )}
-
- );
+ redirect(isTG ? '/telegram' : '/browser');
+ });
}
diff --git a/apps/web/app/(auth)/layout.tsx b/apps/web/app/(auth)/telegram/layout.tsx
similarity index 64%
rename from apps/web/app/(auth)/layout.tsx
rename to apps/web/app/(auth)/telegram/layout.tsx
index 6225cd2..eed2cc2 100644
--- a/apps/web/app/(auth)/layout.tsx
+++ b/apps/web/app/(auth)/telegram/layout.tsx
@@ -1,6 +1,6 @@
import { TelegramProvider } from '@/providers';
import { type PropsWithChildren } from 'react';
-export default async function RootLayout({ children }: Readonly) {
+export default async function Layout({ children }: Readonly) {
return {children};
}
diff --git a/apps/web/app/(auth)/telegram/page.tsx b/apps/web/app/(auth)/telegram/page.tsx
new file mode 100644
index 0000000..3ac0030
--- /dev/null
+++ b/apps/web/app/(auth)/telegram/page.tsx
@@ -0,0 +1,32 @@
+'use client';
+import { LoadingSpinner } from '@repo/ui/components/ui/spinner';
+import { initData, isMiniAppDark, useSignal } from '@telegram-apps/sdk-react';
+import { signIn, useSession } from 'next-auth/react';
+import { useTheme } from 'next-themes';
+import { redirect } from 'next/navigation';
+import { useEffect } from 'react';
+
+export default function Auth() {
+ const initDataUser = useSignal(initData.user);
+ const isDark = isMiniAppDark();
+ const { status } = useSession();
+ const { setTheme } = useTheme();
+
+ useEffect(() => {
+ setTheme(isDark ? 'dark' : 'light');
+
+ if (status === 'authenticated') {
+ redirect('/profile');
+ }
+
+ if (status === 'unauthenticated' && initDataUser?.id) {
+ signIn('telegram', {
+ callbackUrl: '/profile',
+ redirect: false,
+ telegramId: String(initDataUser.id),
+ });
+ }
+ }, [initDataUser, isDark, setTheme, status]);
+
+ return ;
+}
diff --git a/apps/web/app/(main)/layout.tsx b/apps/web/app/(main)/layout.tsx
index 96bb536..038c98f 100644
--- a/apps/web/app/(main)/layout.tsx
+++ b/apps/web/app/(main)/layout.tsx
@@ -1,11 +1,9 @@
-import { Header } from '@/components/header';
import { BottomNav } from '@/components/navigation';
import { type PropsWithChildren } from 'react';
export default async function Layout({ children }: Readonly) {
return (
-
{children}
diff --git a/apps/web/app/(main)/profile/page.tsx b/apps/web/app/(main)/profile/page.tsx
index 2e9ea4f..cf1567c 100644
--- a/apps/web/app/(main)/profile/page.tsx
+++ b/apps/web/app/(main)/profile/page.tsx
@@ -1,8 +1,47 @@
+import { updateProfile, updateRole } from '@/actions/profile';
+import { CheckboxWithText } from '@/components/profile/checkbox-with-text';
+import { ProfileField } from '@/components/profile/profile-field';
import { authOptions } from '@/config/auth';
+import { getCustomer } from '@repo/graphql/api';
+import { Avatar, AvatarFallback, AvatarImage } from '@repo/ui/components/ui/avatar';
+import { Card, CardContent, CardHeader } from '@repo/ui/components/ui/card';
import { getServerSession } from 'next-auth/next';
export default async function ProfilePage() {
const session = await getServerSession(authOptions);
+ const { data } = await getCustomer({ telegramId: session?.user?.telegramId });
+ const user = data.customers.at(0);
+ const photoUrl = user?.photoUrl ?? 'https://github.com/shadcn.png';
- return {JSON.stringify(session, null, 2)};
+ if (!user) return 'Профиль не найден';
+
+ return (
+
+
+
+
+
+ {user?.name.charAt(0)}
+
+ {user?.name}
+
+
+
+
+
+
+
+
+ );
}
diff --git a/apps/web/app/layout.tsx b/apps/web/app/layout.tsx
index bcd7dac..def6cb2 100644
--- a/apps/web/app/layout.tsx
+++ b/apps/web/app/layout.tsx
@@ -1,7 +1,8 @@
import { AuthProvider } from '@/providers';
+import { ThemeProvider } from '@/providers/theme-provider';
import { I18nProvider } from '@/utils/i18n/provider';
-import { type Metadata } from 'next';
import '@repo/ui/globals.css';
+import { type Metadata } from 'next';
import { getLocale } from 'next-intl/server';
import { type PropsWithChildren } from 'react';
@@ -14,9 +15,11 @@ export default async function RootLayout({ children }: Readonly
-
+
- {children}
+
+ {children}
+
diff --git a/apps/web/components/header/index.tsx b/apps/web/components/header/index.tsx
deleted file mode 100644
index 17a4bbd..0000000
--- a/apps/web/components/header/index.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import { Profile } from './profile';
-
-export function Header() {
- return (
-
- );
-}
diff --git a/apps/web/components/header/profile.tsx b/apps/web/components/header/profile.tsx
deleted file mode 100644
index cf1931f..0000000
--- a/apps/web/components/header/profile.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import { Avatar, AvatarFallback, AvatarImage } from '@repo/ui/components/ui/avatar';
-
-type Props = {
- readonly fallback: string;
- readonly src: string;
- readonly username: string;
-};
-
-export function Profile({ fallback, src, username }: Props) {
- return (
-
-
{username}
-
-
- {fallback}
-
-
- );
-}
diff --git a/apps/web/components/profile/checkbox-with-text.tsx b/apps/web/components/profile/checkbox-with-text.tsx
new file mode 100644
index 0000000..91ac194
--- /dev/null
+++ b/apps/web/components/profile/checkbox-with-text.tsx
@@ -0,0 +1,63 @@
+/* eslint-disable canonical/id-match */
+/* eslint-disable promise/prefer-await-to-then */
+'use client';
+import { Enum_Customer_Role } from '@repo/graphql/types';
+import { Checkbox, type CheckboxProps } from '@repo/ui/components/ui/checkbox';
+import { useState } from 'react';
+import { useDebouncedCallback } from 'use-debounce';
+
+type Props = Pick & {
+ readonly description?: string;
+ readonly onChange?: (value: Enum_Customer_Role) => Promise | void;
+ readonly text: string;
+};
+
+export function CheckboxWithText({ checked: initialValue, description, onChange, text }: Props) {
+ const [checked, setChecked] = useState(initialValue);
+ const { debouncedCallback, isPending } = useDebouncedOnChangeCallback(onChange);
+
+ const handleChange = () => {
+ const newValue = !checked;
+ setChecked(newValue);
+ debouncedCallback(newValue);
+ };
+
+ return (
+
+
+
+
+ {description ?
{description}
: false}
+
+
+ );
+}
+
+function useDebouncedOnChangeCallback(
+ callback: ((value: Enum_Customer_Role) => Promise | void) | undefined,
+) {
+ const [isPending, setIsPending] = useState(false);
+
+ const debouncedCallback = useDebouncedCallback((checked: boolean) => {
+ if (!callback) return;
+
+ setIsPending(true);
+ const result = callback(checked ? Enum_Customer_Role.Master : Enum_Customer_Role.Client);
+
+ if (result instanceof Promise) {
+ result.finally(() => setIsPending(false));
+ } else {
+ setIsPending(false);
+ }
+ }, 300);
+
+ return {
+ debouncedCallback,
+ isPending,
+ };
+}
diff --git a/apps/web/components/profile/profile-field.tsx b/apps/web/components/profile/profile-field.tsx
new file mode 100644
index 0000000..89d385e
--- /dev/null
+++ b/apps/web/components/profile/profile-field.tsx
@@ -0,0 +1,85 @@
+/* eslint-disable promise/prefer-await-to-then */
+'use client';
+import { type CustomerInput } from '@repo/graphql/types';
+import { Input } from '@repo/ui/components/ui/input';
+import { Label } from '@repo/ui/components/ui/label';
+import { type ChangeEvent, useEffect, useRef, useState } from 'react';
+import { useDebouncedCallback } from 'use-debounce';
+
+type ProfileFieldProps = {
+ readonly disabled?: boolean;
+ readonly fieldName?: keyof CustomerInput;
+ readonly id: string;
+ readonly label: string;
+ readonly onChange?: (value: CustomerInput) => Promise | void;
+ readonly value: string;
+};
+
+export function ProfileField({
+ disabled = false,
+ fieldName,
+ id,
+ label,
+ onChange,
+ value: initialValue,
+}: ProfileFieldProps) {
+ const [value, setValue] = useState(initialValue);
+ const { debouncedCallback, isPending } = useDebouncedOnChangeCallback(onChange, fieldName);
+ const inputRef = useFocus(isPending);
+
+ const handleChange = (event: ChangeEvent) => {
+ const newValue = event.target.value;
+ setValue(newValue);
+ debouncedCallback(newValue);
+ };
+
+ return (
+
+
+
+
+ );
+}
+
+function useDebouncedOnChangeCallback(
+ callback: ((value: CustomerInput) => Promise | void) | undefined,
+ fieldName: string | undefined,
+) {
+ const [isPending, setIsPending] = useState(false);
+
+ const debouncedCallback = useDebouncedCallback((newValue: string) => {
+ if (!callback || !fieldName) return;
+
+ setIsPending(true);
+ const result = callback({ [fieldName]: newValue });
+
+ if (result instanceof Promise) {
+ result.finally(() => setIsPending(false));
+ } else {
+ setIsPending(false);
+ }
+ }, 300);
+
+ return {
+ debouncedCallback,
+ isPending,
+ };
+}
+
+function useFocus(isPending: boolean) {
+ const inputRef = useRef(null);
+
+ useEffect(() => {
+ if (inputRef.current) {
+ inputRef.current.focus();
+ }
+ }, [isPending]);
+ return inputRef;
+}
diff --git a/apps/web/config/env.ts b/apps/web/config/env.ts
index c3ccf3b..4c88620 100644
--- a/apps/web/config/env.ts
+++ b/apps/web/config/env.ts
@@ -2,7 +2,6 @@
import { z } from 'zod';
export const envSchema = z.object({
- NEXTAUTH_SECRET: z.string(),
+ __DEV_TELEGRAM_ID: z.string(),
});
-
export const env = envSchema.parse(process.env);
diff --git a/apps/web/mocks/get-telegram-user.ts b/apps/web/mocks/get-telegram-user.ts
new file mode 100644
index 0000000..1516fd5
--- /dev/null
+++ b/apps/web/mocks/get-telegram-user.ts
@@ -0,0 +1,12 @@
+'use server';
+
+import { env } from '@/config/env';
+
+export async function getTelegramUser() {
+ if (process.env.NODE_ENV !== 'production')
+ return {
+ id: env.__DEV_TELEGRAM_ID,
+ };
+
+ return null;
+}
diff --git a/apps/web/package.json b/apps/web/package.json
index cb7f982..18a219a 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -21,8 +21,10 @@
"next": "catalog:",
"next-auth": "^4.24.11",
"next-intl": "catalog:",
+ "next-themes": "^0.4.4",
"react": "catalog:",
"react-dom": "catalog:",
+ "use-debounce": "^10.0.4",
"zod": "catalog:"
},
"devDependencies": {
diff --git a/apps/web/providers/theme-provider.tsx b/apps/web/providers/theme-provider.tsx
new file mode 100644
index 0000000..dd140f5
--- /dev/null
+++ b/apps/web/providers/theme-provider.tsx
@@ -0,0 +1,34 @@
+'use client';
+import { ThemeProvider as NextThemesProvider } from 'next-themes';
+import { type ComponentProps, useEffect, useState } from 'react';
+
+/**
+ * mouted - fix for Next.js 15 Hydration Failed
+ */
+export function ThemeProvider({
+ children,
+ ...props
+}: Readonly>) {
+ const [mounted, setMounted] = useState(false);
+
+ useEffect(() => {
+ setMounted(true);
+ }, []);
+
+ if (!mounted) {
+ // eslint-disable-next-line react/jsx-no-useless-fragment
+ return <>>;
+ }
+
+ return (
+
+ {children}
+
+ );
+}
diff --git a/apps/web/types/next-auth.d.ts b/apps/web/types/next-auth.d.ts
index 0152d68..9bf0e89 100644
--- a/apps/web/types/next-auth.d.ts
+++ b/apps/web/types/next-auth.d.ts
@@ -7,4 +7,8 @@ declare module 'next-auth' {
telegramId?: null | string;
};
}
+
+ interface User extends DefaultUser {
+ telegramId?: null | string;
+ }
}
diff --git a/packages/graphql/api/customer.ts b/packages/graphql/api/customer.ts
index 2206662..a0bd9cb 100644
--- a/packages/graphql/api/customer.ts
+++ b/packages/graphql/api/customer.ts
@@ -1,3 +1,4 @@
+'use server';
import { getClientWithToken } from '../apollo/client';
import * as GQL from '../types';
@@ -18,3 +19,12 @@ export async function getCustomer(variables: GQL.GetCustomerQueryVariables) {
variables,
});
}
+
+export async function updateCustomerProfile(variables: GQL.UpdateCustomerProfileMutationVariables) {
+ const { mutate } = await getClientWithToken();
+
+ return mutate({
+ mutation: GQL.UpdateCustomerProfileDocument,
+ variables,
+ });
+}
diff --git a/packages/graphql/graphql.config.cjs b/packages/graphql/graphql.config.cjs
index a9c2fad..c1d69b9 100644
--- a/packages/graphql/graphql.config.cjs
+++ b/packages/graphql/graphql.config.cjs
@@ -4,9 +4,10 @@ module.exports = {
generates: {
'./types/operations.generated.ts': {
config: {
- avoidOptionals: true,
+ avoidOptionals: false,
onlyOperationTypes: true,
useTypeImports: true,
+ maybeValue: 'T | null | undefined'
},
plugins: ['typescript', 'typescript-operations', 'typed-document-node'],
},
diff --git a/packages/graphql/operations/customer.graphql b/packages/graphql/operations/customer.graphql
index f438738..d6e9f15 100644
--- a/packages/graphql/operations/customer.graphql
+++ b/packages/graphql/operations/customer.graphql
@@ -1,19 +1,27 @@
+fragment CustomerProfile on Customer {
+ active
+ documentId
+ name
+ phone
+ photoUrl
+ role
+ telegramId
+}
+
mutation CreateCustomer($name: String!, $telegramId: Long!, $phone: String!) {
createCustomer(data: { name: $name, telegramId: $telegramId, phone: $phone, role: client }) {
- documentId
- name
- telegramId
- phone
- role
- active
- createdAt
- updatedAt
- publishedAt
+ ...CustomerProfile
}
}
query GetCustomer($telegramId: Long!) {
customers(filters: { telegramId: { eq: $telegramId } }) {
- name
+ ...CustomerProfile
+ }
+}
+
+mutation UpdateCustomerProfile($documentId: ID!, $data: CustomerInput!) {
+ updateCustomer(documentId: $documentId, data: $data) {
+ ...CustomerProfile
}
}
diff --git a/packages/graphql/types/operations.generated.ts b/packages/graphql/types/operations.generated.ts
index 47bf8b9..caec0c5 100644
--- a/packages/graphql/types/operations.generated.ts
+++ b/packages/graphql/types/operations.generated.ts
@@ -1,6 +1,6 @@
import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
-export type Maybe = T | null;
-export type InputMaybe = Maybe;
+export type Maybe = T | null | undefined;
+export type InputMaybe = T | null | undefined;
export type Exact = { [K in keyof T]: T[K] };
export type MakeOptional = Omit & { [SubKey in K]?: Maybe };
export type MakeMaybe = Omit & { [SubKey in K]: Maybe };
@@ -19,119 +19,121 @@ export type Scalars = {
};
export type BlockFiltersInput = {
- and: InputMaybe>>;
- client: InputMaybe;
- createdAt: InputMaybe;
- dateend: InputMaybe;
- datestart: InputMaybe;
- documentId: InputMaybe;
- master: InputMaybe;
- not: InputMaybe;
- or: InputMaybe>>;
- orders: InputMaybe;
- publishedAt: InputMaybe;
- sessionsCompleted: InputMaybe;
- sessionsTotal: InputMaybe;
- state: InputMaybe;
- updatedAt: InputMaybe;
+ and?: InputMaybe>>;
+ client?: InputMaybe;
+ createdAt?: InputMaybe;
+ dateend?: InputMaybe;
+ datestart?: InputMaybe;
+ documentId?: InputMaybe;
+ master?: InputMaybe;
+ not?: InputMaybe;
+ or?: InputMaybe>>;
+ orders?: InputMaybe;
+ publishedAt?: InputMaybe;
+ sessionsCompleted?: InputMaybe;
+ sessionsTotal?: InputMaybe;
+ state?: InputMaybe;
+ updatedAt?: InputMaybe;
};
export type BlockInput = {
- client: InputMaybe;
- dateend: InputMaybe;
- datestart: InputMaybe;
- master: InputMaybe;
- orders: InputMaybe>>;
- publishedAt: InputMaybe;
- sessionsCompleted: InputMaybe;
- sessionsTotal: InputMaybe;
- state: InputMaybe;
+ client?: InputMaybe;
+ dateend?: InputMaybe;
+ datestart?: InputMaybe;
+ master?: InputMaybe;
+ orders?: InputMaybe>>;
+ publishedAt?: InputMaybe;
+ sessionsCompleted?: InputMaybe;
+ sessionsTotal?: InputMaybe;
+ state?: InputMaybe;
};
export type BooleanFilterInput = {
- and: InputMaybe>>;
- between: InputMaybe>>;
- contains: InputMaybe;
- containsi: InputMaybe;
- endsWith: InputMaybe;
- eq: InputMaybe;
- eqi: InputMaybe;
- gt: InputMaybe;
- gte: InputMaybe;
- in: InputMaybe>>;
- lt: InputMaybe;
- lte: InputMaybe;
- ne: InputMaybe;
- nei: InputMaybe;
- not: InputMaybe;
- notContains: InputMaybe;
- notContainsi: InputMaybe;
- notIn: InputMaybe>>;
- notNull: InputMaybe;
- null: InputMaybe;
- or: InputMaybe>>;
- startsWith: InputMaybe;
+ and?: InputMaybe>>;
+ between?: InputMaybe>>;
+ contains?: InputMaybe;
+ containsi?: InputMaybe;
+ endsWith?: InputMaybe;
+ eq?: InputMaybe;
+ eqi?: InputMaybe;
+ gt?: InputMaybe;
+ gte?: InputMaybe;
+ in?: InputMaybe>>;
+ lt?: InputMaybe;
+ lte?: InputMaybe;
+ ne?: InputMaybe;
+ nei?: InputMaybe;
+ not?: InputMaybe;
+ notContains?: InputMaybe;
+ notContainsi?: InputMaybe;
+ notIn?: InputMaybe>>;
+ notNull?: InputMaybe;
+ null?: InputMaybe;
+ or?: InputMaybe>>;
+ startsWith?: InputMaybe;
};
export type CustomerFiltersInput = {
- active: InputMaybe;
- and: InputMaybe>>;
- blocks: InputMaybe;
- clients: InputMaybe;
- createdAt: InputMaybe;
- documentId: InputMaybe;
- masters: InputMaybe;
- name: InputMaybe;
- not: InputMaybe;
- or: InputMaybe>>;
- orders: InputMaybe;
- phone: InputMaybe;
- publishedAt: InputMaybe;
- role: InputMaybe;
- setting: InputMaybe;
- slots: InputMaybe;
- telegramId: InputMaybe;
- updatedAt: InputMaybe;
+ active?: InputMaybe;
+ and?: InputMaybe>>;
+ blocks?: InputMaybe;
+ clients?: InputMaybe;
+ createdAt?: InputMaybe;
+ documentId?: InputMaybe;
+ masters?: InputMaybe;
+ name?: InputMaybe;
+ not?: InputMaybe;
+ or?: InputMaybe>>;
+ orders?: InputMaybe;
+ phone?: InputMaybe;
+ photoUrl?: InputMaybe;
+ publishedAt?: InputMaybe;
+ role?: InputMaybe;
+ setting?: InputMaybe;
+ slots?: InputMaybe;
+ telegramId?: InputMaybe;
+ updatedAt?: InputMaybe;
};
export type CustomerInput = {
- active: InputMaybe;
- blocks: InputMaybe>>;
- clients: InputMaybe>>;
- masters: InputMaybe>>;
- name: InputMaybe;
- orders: InputMaybe>>;
- phone: InputMaybe;
- publishedAt: InputMaybe;
- role: InputMaybe;
- setting: InputMaybe;
- slots: InputMaybe>>;
- telegramId: InputMaybe;
+ active?: InputMaybe;
+ blocks?: InputMaybe>>;
+ clients?: InputMaybe>>;
+ masters?: InputMaybe>>;
+ name?: InputMaybe;
+ orders?: InputMaybe>>;
+ phone?: InputMaybe;
+ photoUrl?: InputMaybe;
+ publishedAt?: InputMaybe;
+ role?: InputMaybe;
+ setting?: InputMaybe;
+ slots?: InputMaybe>>;
+ telegramId?: InputMaybe;
};
export type DateTimeFilterInput = {
- and: InputMaybe>>;
- between: InputMaybe>>;
- contains: InputMaybe;
- containsi: InputMaybe;
- endsWith: InputMaybe;
- eq: InputMaybe;
- eqi: InputMaybe;
- gt: InputMaybe;
- gte: InputMaybe;
- in: InputMaybe>>;
- lt: InputMaybe;
- lte: InputMaybe;
- ne: InputMaybe;
- nei: InputMaybe;
- not: InputMaybe;
- notContains: InputMaybe;
- notContainsi: InputMaybe;
- notIn: InputMaybe>>;
- notNull: InputMaybe;
- null: InputMaybe;
- or: InputMaybe>>;
- startsWith: InputMaybe;
+ and?: InputMaybe>>;
+ between?: InputMaybe>>;
+ contains?: InputMaybe;
+ containsi?: InputMaybe;
+ endsWith?: InputMaybe;
+ eq?: InputMaybe;
+ eqi?: InputMaybe;
+ gt?: InputMaybe;
+ gte?: InputMaybe;
+ in?: InputMaybe>>;
+ lt?: InputMaybe;
+ lte?: InputMaybe;
+ ne?: InputMaybe;
+ nei?: InputMaybe;
+ not?: InputMaybe;
+ notContains?: InputMaybe;
+ notContainsi?: InputMaybe;
+ notIn?: InputMaybe>>;
+ notNull?: InputMaybe;
+ null?: InputMaybe;
+ or?: InputMaybe>>;
+ startsWith?: InputMaybe;
};
export enum Enum_Block_State {
@@ -160,179 +162,179 @@ export enum Enum_Slot_State {
}
export type FileInfoInput = {
- alternativeText: InputMaybe;
- caption: InputMaybe;
- name: InputMaybe;
+ alternativeText?: InputMaybe;
+ caption?: InputMaybe;
+ name?: InputMaybe;
};
export type FloatFilterInput = {
- and: InputMaybe>>;
- between: InputMaybe>>;
- contains: InputMaybe;
- containsi: InputMaybe;
- endsWith: InputMaybe;
- eq: InputMaybe;
- eqi: InputMaybe;
- gt: InputMaybe;
- gte: InputMaybe;
- in: InputMaybe>>;
- lt: InputMaybe;
- lte: InputMaybe;
- ne: InputMaybe;
- nei: InputMaybe;
- not: InputMaybe;
- notContains: InputMaybe;
- notContainsi: InputMaybe;
- notIn: InputMaybe>>;
- notNull: InputMaybe;
- null: InputMaybe;
- or: InputMaybe>>;
- startsWith: InputMaybe;
+ and?: InputMaybe>>;
+ between?: InputMaybe>>;
+ contains?: InputMaybe;
+ containsi?: InputMaybe