[frontend]: add graphql and i18n
This commit is contained in:
parent
d579e44014
commit
9dce83aa83
10
frontend/apollo.config.js
Normal file
10
frontend/apollo.config.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
require('dotenv/config')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
service: {
|
||||||
|
endpoint: {
|
||||||
|
url: process.env.NEXT_PUBLIC_SERVER_URL,
|
||||||
|
skipSSLValidation: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -11,6 +11,9 @@ const compat = new FlatCompat({
|
|||||||
|
|
||||||
const eslintConfig = [
|
const eslintConfig = [
|
||||||
...compat.extends("next/core-web-vitals", "next/typescript"),
|
...compat.extends("next/core-web-vitals", "next/typescript"),
|
||||||
|
{
|
||||||
|
ignores: ['src/graphql/generated']
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
export default eslintConfig;
|
export default eslintConfig;
|
||||||
|
|||||||
19
frontend/graphql.config.ts
Normal file
19
frontend/graphql.config.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { CodegenConfig } from '@graphql-codegen/cli';
|
||||||
|
import 'dotenv/config'
|
||||||
|
|
||||||
|
const config: CodegenConfig = {
|
||||||
|
schema: process.env.NEXT_PUBLIC_SERVER_URL,
|
||||||
|
documents: ['./src/graphql/**/*.graphql'],
|
||||||
|
generates: {
|
||||||
|
'./src/graphql/generated/output.ts': {
|
||||||
|
plugins: [
|
||||||
|
'typescript',
|
||||||
|
'typescript-operations',
|
||||||
|
'typescript-react-apollo'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ignoreNoDocuments: true
|
||||||
|
}
|
||||||
|
|
||||||
|
export default config
|
||||||
6
frontend/graphql.d.ts
vendored
Normal file
6
frontend/graphql.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
declare module '*.graphql' {
|
||||||
|
import {DocumentNode} from 'graphql'
|
||||||
|
const schema: DocumentNode
|
||||||
|
|
||||||
|
export = schema
|
||||||
|
}
|
||||||
@ -1,7 +1,10 @@
|
|||||||
import type { NextConfig } from "next";
|
import type { NextConfig } from "next";
|
||||||
|
import createNextIntlPlugin from 'next-intl/plugin';
|
||||||
|
|
||||||
|
const withNextIntl = createNextIntlPlugin('./src/libs/i18n/request.ts')
|
||||||
|
|
||||||
const nextConfig: NextConfig = {
|
const nextConfig: NextConfig = {
|
||||||
/* config options here */
|
reactStrictMode: true
|
||||||
};
|
};
|
||||||
|
|
||||||
export default nextConfig;
|
export default withNextIntl(nextConfig);
|
||||||
|
|||||||
6149
frontend/package-lock.json
generated
6149
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -3,25 +3,33 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev --turbopack",
|
"dev": "yarn run codegen && next dev --turbopack",
|
||||||
"build": "next build",
|
"build": "yarn run codegen && next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint"
|
"lint": "next lint",
|
||||||
|
"codegen": "graphql-codegen --config graphql.config.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react": "19.1.0",
|
"@apollo/client": "3.13.9",
|
||||||
"react-dom": "19.1.0",
|
"@graphql-codegen/cli": "5.0.7",
|
||||||
"next": "15.4.4"
|
"@graphql-codegen/typescript": "4.1.6",
|
||||||
|
"@graphql-codegen/typescript-operations": "4.6.1",
|
||||||
|
"@graphql-codegen/typescript-react-apollo": "4.3.3",
|
||||||
|
"graphql": "16.11.0",
|
||||||
|
"next": "15.4.5",
|
||||||
|
"next-intl": "^4.3.4",
|
||||||
|
"react": "19.1.1",
|
||||||
|
"react-dom": "19.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^5",
|
"@eslint/eslintrc": "3.3.1",
|
||||||
"@types/node": "^20",
|
"@tailwindcss/postcss": "4.1.11",
|
||||||
"@types/react": "^19",
|
"@types/node": "22.17.0",
|
||||||
"@types/react-dom": "^19",
|
"@types/react": "19.1.9",
|
||||||
"@tailwindcss/postcss": "^4",
|
"@types/react-dom": "19.1.7",
|
||||||
"tailwindcss": "^4",
|
"eslint": "9.32.0",
|
||||||
"eslint": "^9",
|
|
||||||
"eslint-config-next": "15.4.4",
|
"eslint-config-next": "15.4.4",
|
||||||
"@eslint/eslintrc": "^3"
|
"tailwindcss": "4.1.11",
|
||||||
|
"typescript": "5.8.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
5
frontend/public/languages/en.json
Normal file
5
frontend/public/languages/en.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"home": {
|
||||||
|
"title": "Home page"
|
||||||
|
}
|
||||||
|
}
|
||||||
5
frontend/public/languages/ru.json
Normal file
5
frontend/public/languages/ru.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"home": {
|
||||||
|
"title": "Домашняя страница"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,7 @@
|
|||||||
|
import ApolloClientProvider from '@/providers/ApolloClientProvider';
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
|
import { NextIntlClientProvider } from 'next-intl';
|
||||||
|
import { getLocale, getMessages } from 'next-intl/server';
|
||||||
import { Geist, Geist_Mono } from "next/font/google";
|
import { Geist, Geist_Mono } from "next/font/google";
|
||||||
import "../styles/globals.css";
|
import "../styles/globals.css";
|
||||||
|
|
||||||
@ -17,17 +20,24 @@ export const metadata: Metadata = {
|
|||||||
description: "Generated by create next app",
|
description: "Generated by create next app",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function RootLayout({
|
export default async function RootLayout({
|
||||||
children,
|
children,
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>) {
|
||||||
|
const locale = await getLocale()
|
||||||
|
const messages = await getMessages()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang={locale}>
|
||||||
<body
|
<body
|
||||||
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
||||||
>
|
>
|
||||||
{children}
|
<ApolloClientProvider>
|
||||||
|
<NextIntlClientProvider messages={messages}>
|
||||||
|
{children}
|
||||||
|
</NextIntlClientProvider>
|
||||||
|
</ApolloClientProvider>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,103 +1,13 @@
|
|||||||
import Image from "next/image";
|
'use client'
|
||||||
|
|
||||||
|
import { useTranslations } from 'next-intl';
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
const t = useTranslations('home')
|
||||||
<div className="font-sans grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20">
|
|
||||||
<main className="flex flex-col gap-[32px] row-start-2 items-center sm:items-start">
|
|
||||||
<Image
|
|
||||||
className="dark:invert"
|
|
||||||
src="/next.svg"
|
|
||||||
alt="Next.js logo"
|
|
||||||
width={180}
|
|
||||||
height={38}
|
|
||||||
priority
|
|
||||||
/>
|
|
||||||
<ol className="font-mono list-inside list-decimal text-sm/6 text-center sm:text-left">
|
|
||||||
<li className="mb-2 tracking-[-.01em]">
|
|
||||||
Get started by editing{" "}
|
|
||||||
<code className="bg-black/[.05] dark:bg-white/[.06] font-mono font-semibold px-1 py-0.5 rounded">
|
|
||||||
src/app/page.tsx
|
|
||||||
</code>
|
|
||||||
.
|
|
||||||
</li>
|
|
||||||
<li className="tracking-[-.01em]">
|
|
||||||
Save and see your changes instantly.
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
<div className="flex gap-4 items-center flex-col sm:flex-row">
|
return (
|
||||||
<a
|
<div>
|
||||||
className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:w-auto"
|
{t('title')}
|
||||||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
className="dark:invert"
|
|
||||||
src="/vercel.svg"
|
|
||||||
alt="Vercel logomark"
|
|
||||||
width={20}
|
|
||||||
height={20}
|
|
||||||
/>
|
|
||||||
Deploy now
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 w-full sm:w-auto md:w-[158px]"
|
|
||||||
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
Read our docs
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
<footer className="row-start-3 flex gap-[24px] flex-wrap items-center justify-center">
|
|
||||||
<a
|
|
||||||
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
|
||||||
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
aria-hidden
|
|
||||||
src="/file.svg"
|
|
||||||
alt="File icon"
|
|
||||||
width={16}
|
|
||||||
height={16}
|
|
||||||
/>
|
|
||||||
Learn
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
|
||||||
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
aria-hidden
|
|
||||||
src="/window.svg"
|
|
||||||
alt="Window icon"
|
|
||||||
width={16}
|
|
||||||
height={16}
|
|
||||||
/>
|
|
||||||
Examples
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
|
||||||
href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
aria-hidden
|
|
||||||
src="/globe.svg"
|
|
||||||
alt="Globe icon"
|
|
||||||
width={16}
|
|
||||||
height={16}
|
|
||||||
/>
|
|
||||||
Go to nextjs.org →
|
|
||||||
</a>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
646
frontend/src/graphql/generated/output.ts
Normal file
646
frontend/src/graphql/generated/output.ts
Normal file
@ -0,0 +1,646 @@
|
|||||||
|
import { gql } from '@apollo/client';
|
||||||
|
import * as Apollo from '@apollo/client';
|
||||||
|
export type Maybe<T> = T | null;
|
||||||
|
export type InputMaybe<T> = Maybe<T>;
|
||||||
|
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
|
||||||
|
export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> };
|
||||||
|
export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> };
|
||||||
|
export type MakeEmpty<T extends { [key: string]: unknown }, K extends keyof T> = { [_ in K]?: never };
|
||||||
|
export type Incremental<T> = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never };
|
||||||
|
const defaultOptions = {} as const;
|
||||||
|
/** All built-in and custom scalars, mapped to their actual values */
|
||||||
|
export type Scalars = {
|
||||||
|
ID: { input: string; output: string; }
|
||||||
|
String: { input: string; output: string; }
|
||||||
|
Boolean: { input: boolean; output: boolean; }
|
||||||
|
Int: { input: number; output: number; }
|
||||||
|
Float: { input: number; output: number; }
|
||||||
|
DateTime: { input: any; output: any; }
|
||||||
|
Upload: { input: any; output: any; }
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AuthModel = {
|
||||||
|
__typename?: 'AuthModel';
|
||||||
|
message?: Maybe<Scalars['String']['output']>;
|
||||||
|
user?: Maybe<UserModel>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CategoryModel = {
|
||||||
|
__typename?: 'CategoryModel';
|
||||||
|
createdAt: Scalars['DateTime']['output'];
|
||||||
|
description?: Maybe<Scalars['String']['output']>;
|
||||||
|
id: Scalars['ID']['output'];
|
||||||
|
slug: Scalars['String']['output'];
|
||||||
|
streams: Array<StreamModel>;
|
||||||
|
thumbnailUrl: Scalars['String']['output'];
|
||||||
|
title: Scalars['String']['output'];
|
||||||
|
updatedAt: Scalars['DateTime']['output'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ChangeChatSettingsInput = {
|
||||||
|
isChatEnable: Scalars['Boolean']['input'];
|
||||||
|
isChatFollowersOnly: Scalars['Boolean']['input'];
|
||||||
|
isChatPremiumFollowersOnly: Scalars['Boolean']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ChangeEmailInput = {
|
||||||
|
email: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ChangeNotificationSettingsInput = {
|
||||||
|
siteNotifications: Scalars['Boolean']['input'];
|
||||||
|
telegramNotifications: Scalars['Boolean']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ChangeNotificationsSettingsResponse = {
|
||||||
|
__typename?: 'ChangeNotificationsSettingsResponse';
|
||||||
|
notificationSettings: NotificationSettingsModel;
|
||||||
|
telegramAuthToken?: Maybe<Scalars['String']['output']>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ChangePasswordInput = {
|
||||||
|
newPassword: Scalars['String']['input'];
|
||||||
|
oldPassword: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ChangeProfileInfoInput = {
|
||||||
|
bio: Scalars['String']['input'];
|
||||||
|
displayName: Scalars['String']['input'];
|
||||||
|
name: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ChangeStreamInfoInput = {
|
||||||
|
categoryId: Scalars['String']['input'];
|
||||||
|
title: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ChatMessageModel = {
|
||||||
|
__typename?: 'ChatMessageModel';
|
||||||
|
createdAt: Scalars['DateTime']['output'];
|
||||||
|
id: Scalars['ID']['output'];
|
||||||
|
streamId: Scalars['ID']['output'];
|
||||||
|
text: Scalars['String']['output'];
|
||||||
|
updatedAt: Scalars['DateTime']['output'];
|
||||||
|
userId: Scalars['ID']['output'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CreatePlanInput = {
|
||||||
|
description?: InputMaybe<Scalars['String']['input']>;
|
||||||
|
price: Scalars['Float']['input'];
|
||||||
|
title: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CreateUserInput = {
|
||||||
|
email: Scalars['String']['input'];
|
||||||
|
name: Scalars['String']['input'];
|
||||||
|
password: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type DeactivateAccountInput = {
|
||||||
|
email: Scalars['String']['input'];
|
||||||
|
password: Scalars['String']['input'];
|
||||||
|
pin?: InputMaybe<Scalars['String']['input']>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type DeviceModel = {
|
||||||
|
__typename?: 'DeviceModel';
|
||||||
|
browser: Scalars['String']['output'];
|
||||||
|
os: Scalars['String']['output'];
|
||||||
|
type: Scalars['String']['output'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type EnableTotpInput = {
|
||||||
|
pin: Scalars['String']['input'];
|
||||||
|
secret: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type FilterInput = {
|
||||||
|
searchTerm?: InputMaybe<Scalars['String']['input']>;
|
||||||
|
skip?: InputMaybe<Scalars['Float']['input']>;
|
||||||
|
take?: InputMaybe<Scalars['Float']['input']>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type FollowModel = {
|
||||||
|
__typename?: 'FollowModel';
|
||||||
|
createdAt: Scalars['DateTime']['output'];
|
||||||
|
follower: UserModel;
|
||||||
|
followerId: Scalars['ID']['output'];
|
||||||
|
following: UserModel;
|
||||||
|
followingId: Scalars['ID']['output'];
|
||||||
|
id: Scalars['ID']['output'];
|
||||||
|
updatedAt: Scalars['DateTime']['output'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GenerateStreamTokenInput = {
|
||||||
|
channelId: Scalars['String']['input'];
|
||||||
|
userId: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GenerateTokenModel = {
|
||||||
|
__typename?: 'GenerateTokenModel';
|
||||||
|
token: Scalars['String']['output'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type LocationModel = {
|
||||||
|
__typename?: 'LocationModel';
|
||||||
|
city: Scalars['String']['output'];
|
||||||
|
country: Scalars['String']['output'];
|
||||||
|
latitude: Scalars['Float']['output'];
|
||||||
|
longitude: Scalars['Float']['output'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type LoginInput = {
|
||||||
|
login: Scalars['String']['input'];
|
||||||
|
password: Scalars['String']['input'];
|
||||||
|
pin?: InputMaybe<Scalars['String']['input']>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type MakePaymentModel = {
|
||||||
|
__typename?: 'MakePaymentModel';
|
||||||
|
url: Scalars['String']['output'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Mutation = {
|
||||||
|
__typename?: 'Mutation';
|
||||||
|
changeChatSettings: StreamModel;
|
||||||
|
changeEmail: UserModel;
|
||||||
|
changeNotificationSettigs: ChangeNotificationsSettingsResponse;
|
||||||
|
changePassword: UserModel;
|
||||||
|
changeProfileAvatar: Scalars['Boolean']['output'];
|
||||||
|
changeProfileInfo: UserModel;
|
||||||
|
changeStreamInfo: StreamModel;
|
||||||
|
changeStreamThumbnail: Scalars['Boolean']['output'];
|
||||||
|
clearSessionCookie: Scalars['Boolean']['output'];
|
||||||
|
createIngress: Scalars['Boolean']['output'];
|
||||||
|
createSocialLink: SocialLinkModel;
|
||||||
|
createSponsorshipPlan: PlanModel;
|
||||||
|
createUser: UserModel;
|
||||||
|
deactivateAccount: AuthModel;
|
||||||
|
disableTotp: Scalars['Boolean']['output'];
|
||||||
|
enableTotp: Scalars['Boolean']['output'];
|
||||||
|
followChannel: FollowModel;
|
||||||
|
generateStreamToken: GenerateTokenModel;
|
||||||
|
loginUser: AuthModel;
|
||||||
|
logoutUser: Scalars['Boolean']['output'];
|
||||||
|
makePayment: MakePaymentModel;
|
||||||
|
removeProfileAvatar: Scalars['Boolean']['output'];
|
||||||
|
removeSession: Scalars['Boolean']['output'];
|
||||||
|
removeSocialLink: Scalars['Boolean']['output'];
|
||||||
|
removeSponsorshipPlan: PlanModel;
|
||||||
|
removeStreamThumbnail: Scalars['Boolean']['output'];
|
||||||
|
reorderSocialLink: Scalars['Boolean']['output'];
|
||||||
|
resetPassword: Scalars['Boolean']['output'];
|
||||||
|
sendChatMessage: ChatMessageModel;
|
||||||
|
setNewPassword: Scalars['Boolean']['output'];
|
||||||
|
unfollowChannel: FollowModel;
|
||||||
|
updateSocialLink: SocialLinkModel;
|
||||||
|
verifyAccount: AuthModel;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationChangeChatSettingsArgs = {
|
||||||
|
data: ChangeChatSettingsInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationChangeEmailArgs = {
|
||||||
|
data: ChangeEmailInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationChangeNotificationSettigsArgs = {
|
||||||
|
data: ChangeNotificationSettingsInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationChangePasswordArgs = {
|
||||||
|
data: ChangePasswordInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationChangeProfileAvatarArgs = {
|
||||||
|
avatar: Scalars['Upload']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationChangeProfileInfoArgs = {
|
||||||
|
data: ChangeProfileInfoInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationChangeStreamInfoArgs = {
|
||||||
|
data: ChangeStreamInfoInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationChangeStreamThumbnailArgs = {
|
||||||
|
thumbnail: Scalars['Upload']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationCreateIngressArgs = {
|
||||||
|
ingressType: Scalars['Float']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationCreateSocialLinkArgs = {
|
||||||
|
data: SocialLinkInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationCreateSponsorshipPlanArgs = {
|
||||||
|
data: CreatePlanInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationCreateUserArgs = {
|
||||||
|
data: CreateUserInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationDeactivateAccountArgs = {
|
||||||
|
data: DeactivateAccountInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationEnableTotpArgs = {
|
||||||
|
data: EnableTotpInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationFollowChannelArgs = {
|
||||||
|
channelId: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationGenerateStreamTokenArgs = {
|
||||||
|
data: GenerateStreamTokenInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationLoginUserArgs = {
|
||||||
|
data: LoginInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationMakePaymentArgs = {
|
||||||
|
planId: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationRemoveSessionArgs = {
|
||||||
|
id: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationRemoveSocialLinkArgs = {
|
||||||
|
id: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationRemoveSponsorshipPlanArgs = {
|
||||||
|
planId: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationReorderSocialLinkArgs = {
|
||||||
|
list: Array<SocialLinkOrderInput>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationResetPasswordArgs = {
|
||||||
|
data: ResetPasswordInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationSendChatMessageArgs = {
|
||||||
|
data: SendMessageInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationSetNewPasswordArgs = {
|
||||||
|
data: NewPasswordInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationUnfollowChannelArgs = {
|
||||||
|
channelId: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationUpdateSocialLinkArgs = {
|
||||||
|
data: SocialLinkInput;
|
||||||
|
id: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationVerifyAccountArgs = {
|
||||||
|
data: VerificationInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type NewPasswordInput = {
|
||||||
|
password: Scalars['String']['input'];
|
||||||
|
passwordRepeat: Scalars['String']['input'];
|
||||||
|
token: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type NotificationModel = {
|
||||||
|
__typename?: 'NotificationModel';
|
||||||
|
createdAt: Scalars['DateTime']['output'];
|
||||||
|
id: Scalars['String']['output'];
|
||||||
|
isRead: Scalars['Boolean']['output'];
|
||||||
|
text: Scalars['String']['output'];
|
||||||
|
type: NotificationType;
|
||||||
|
updatedAt: Scalars['DateTime']['output'];
|
||||||
|
user: UserModel;
|
||||||
|
userId: Scalars['String']['output'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type NotificationSettingsModel = {
|
||||||
|
__typename?: 'NotificationSettingsModel';
|
||||||
|
createdAt: Scalars['DateTime']['output'];
|
||||||
|
id: Scalars['String']['output'];
|
||||||
|
siteNotifications: Scalars['Boolean']['output'];
|
||||||
|
telegramNotifications: Scalars['Boolean']['output'];
|
||||||
|
updatedAt: Scalars['DateTime']['output'];
|
||||||
|
user: UserModel;
|
||||||
|
userId: Scalars['String']['output'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export enum NotificationType {
|
||||||
|
EnableTwoFactor = 'ENABLE_TWO_FACTOR',
|
||||||
|
NewFollower = 'NEW_FOLLOWER',
|
||||||
|
NewSponsorship = 'NEW_SPONSORSHIP',
|
||||||
|
StreamStart = 'STREAM_START',
|
||||||
|
VerifiedChannel = 'VERIFIED_CHANNEL'
|
||||||
|
}
|
||||||
|
|
||||||
|
export type PlanModel = {
|
||||||
|
__typename?: 'PlanModel';
|
||||||
|
channel: UserModel;
|
||||||
|
channelId: Scalars['ID']['output'];
|
||||||
|
createdAt: Scalars['DateTime']['output'];
|
||||||
|
description?: Maybe<Scalars['String']['output']>;
|
||||||
|
id: Scalars['ID']['output'];
|
||||||
|
price: Scalars['Float']['output'];
|
||||||
|
stripePlanId: Scalars['ID']['output'];
|
||||||
|
stripeProductId: Scalars['ID']['output'];
|
||||||
|
title: Scalars['String']['output'];
|
||||||
|
updatedAt: Scalars['DateTime']['output'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Query = {
|
||||||
|
__typename?: 'Query';
|
||||||
|
findAllCategories: Array<CategoryModel>;
|
||||||
|
findAllStreams: Array<StreamModel>;
|
||||||
|
findCategoryBySlug: CategoryModel;
|
||||||
|
findChannelByUsername: UserModel;
|
||||||
|
findChannelFollowersCount: Scalars['Float']['output'];
|
||||||
|
findCurrentSession: SessionModel;
|
||||||
|
findMessagesByStream: Array<ChatMessageModel>;
|
||||||
|
findMyFollowers: Array<FollowModel>;
|
||||||
|
findMyFollowings: Array<FollowModel>;
|
||||||
|
findMySponsors: Array<SubscriptionModel>;
|
||||||
|
findMySponsorshipPlans: Array<PlanModel>;
|
||||||
|
findMyTransactions: Array<TransactionModel>;
|
||||||
|
findNotificationByUser: Array<NotificationModel>;
|
||||||
|
findProfile: UserModel;
|
||||||
|
findRandomCategories: Array<CategoryModel>;
|
||||||
|
findRandomStreams: Array<StreamModel>;
|
||||||
|
findRecommendedChannels: Array<UserModel>;
|
||||||
|
findSessionsByUser: Array<SessionModel>;
|
||||||
|
findSocialLinks: Array<SocialLinkModel>;
|
||||||
|
findSponsorsByChannel: Array<SubscriptionModel>;
|
||||||
|
findUnreadNotificationsCount: Scalars['Float']['output'];
|
||||||
|
generateTotpSecret: TotpModel;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type QueryFindAllStreamsArgs = {
|
||||||
|
filters: FilterInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type QueryFindCategoryBySlugArgs = {
|
||||||
|
slug: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type QueryFindChannelByUsernameArgs = {
|
||||||
|
name: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type QueryFindChannelFollowersCountArgs = {
|
||||||
|
channelId: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type QueryFindMessagesByStreamArgs = {
|
||||||
|
streamId: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type QueryFindSponsorsByChannelArgs = {
|
||||||
|
channelId: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ResetPasswordInput = {
|
||||||
|
email: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SendMessageInput = {
|
||||||
|
streamId: Scalars['String']['input'];
|
||||||
|
text: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SessionMetadataModel = {
|
||||||
|
__typename?: 'SessionMetadataModel';
|
||||||
|
device: DeviceModel;
|
||||||
|
ip: Scalars['String']['output'];
|
||||||
|
location: LocationModel;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SessionModel = {
|
||||||
|
__typename?: 'SessionModel';
|
||||||
|
createdAt: Scalars['String']['output'];
|
||||||
|
id: Scalars['ID']['output'];
|
||||||
|
metadata: SessionMetadataModel;
|
||||||
|
userId: Scalars['String']['output'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SocialLinkInput = {
|
||||||
|
title: Scalars['String']['input'];
|
||||||
|
url: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SocialLinkModel = {
|
||||||
|
__typename?: 'SocialLinkModel';
|
||||||
|
createdAt: Scalars['DateTime']['output'];
|
||||||
|
id: Scalars['ID']['output'];
|
||||||
|
position: Scalars['Float']['output'];
|
||||||
|
title: Scalars['String']['output'];
|
||||||
|
updatedAt: Scalars['DateTime']['output'];
|
||||||
|
url: Scalars['String']['output'];
|
||||||
|
userId: Scalars['ID']['output'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SocialLinkOrderInput = {
|
||||||
|
id: Scalars['String']['input'];
|
||||||
|
position: Scalars['Float']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type StreamModel = {
|
||||||
|
__typename?: 'StreamModel';
|
||||||
|
category: CategoryModel;
|
||||||
|
categoryId: Scalars['ID']['output'];
|
||||||
|
chatMessages: Array<ChatMessageModel>;
|
||||||
|
createdAt: Scalars['DateTime']['output'];
|
||||||
|
id: Scalars['ID']['output'];
|
||||||
|
ingressId?: Maybe<Scalars['String']['output']>;
|
||||||
|
isChatEnable: Scalars['Boolean']['output'];
|
||||||
|
isChatFollowersOnly: Scalars['Boolean']['output'];
|
||||||
|
isChatPremiumFollowersOnly: Scalars['Boolean']['output'];
|
||||||
|
isLive: Scalars['Boolean']['output'];
|
||||||
|
key?: Maybe<Scalars['String']['output']>;
|
||||||
|
serverUrl?: Maybe<Scalars['String']['output']>;
|
||||||
|
thumbnailUrl?: Maybe<Scalars['String']['output']>;
|
||||||
|
title: Scalars['String']['output'];
|
||||||
|
updatedAt: Scalars['DateTime']['output'];
|
||||||
|
user: UserModel;
|
||||||
|
userId: Scalars['ID']['output'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Subscription = {
|
||||||
|
__typename?: 'Subscription';
|
||||||
|
chatMessageAdded: ChatMessageModel;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type SubscriptionChatMessageAddedArgs = {
|
||||||
|
streamId: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SubscriptionModel = {
|
||||||
|
__typename?: 'SubscriptionModel';
|
||||||
|
channel: UserModel;
|
||||||
|
channelId: Scalars['String']['output'];
|
||||||
|
createdAt: Scalars['DateTime']['output'];
|
||||||
|
expiresAt: Scalars['DateTime']['output'];
|
||||||
|
id: Scalars['ID']['output'];
|
||||||
|
plan: PlanModel;
|
||||||
|
planId: Scalars['String']['output'];
|
||||||
|
updatedAt: Scalars['DateTime']['output'];
|
||||||
|
user: UserModel;
|
||||||
|
userId: Scalars['String']['output'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TotpModel = {
|
||||||
|
__typename?: 'TotpModel';
|
||||||
|
qrcodeUrl: Scalars['String']['output'];
|
||||||
|
secret: Scalars['String']['output'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TransactionModel = {
|
||||||
|
__typename?: 'TransactionModel';
|
||||||
|
amount: Scalars['Float']['output'];
|
||||||
|
createdAt: Scalars['DateTime']['output'];
|
||||||
|
currency: Scalars['String']['output'];
|
||||||
|
id: Scalars['ID']['output'];
|
||||||
|
status: TransactionStatus;
|
||||||
|
stripeSubscriptionId: Scalars['ID']['output'];
|
||||||
|
updatedAt: Scalars['DateTime']['output'];
|
||||||
|
user: UserModel;
|
||||||
|
userId: Scalars['ID']['output'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export enum TransactionStatus {
|
||||||
|
Expired = 'EXPIRED',
|
||||||
|
Failed = 'FAILED',
|
||||||
|
Pending = 'PENDING',
|
||||||
|
Success = 'SUCCESS'
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UserModel = {
|
||||||
|
__typename?: 'UserModel';
|
||||||
|
avatar?: Maybe<Scalars['String']['output']>;
|
||||||
|
bio?: Maybe<Scalars['String']['output']>;
|
||||||
|
createdAt: Scalars['DateTime']['output'];
|
||||||
|
deactivatedAt?: Maybe<Scalars['DateTime']['output']>;
|
||||||
|
displayName: Scalars['String']['output'];
|
||||||
|
email: Scalars['String']['output'];
|
||||||
|
followers: Array<FollowModel>;
|
||||||
|
followings: Array<FollowModel>;
|
||||||
|
id: Scalars['ID']['output'];
|
||||||
|
isDeactivated: Scalars['Boolean']['output'];
|
||||||
|
isEmailVerified: Scalars['Boolean']['output'];
|
||||||
|
isTotpEnabled: Scalars['Boolean']['output'];
|
||||||
|
isVerified: Scalars['Boolean']['output'];
|
||||||
|
name: Scalars['String']['output'];
|
||||||
|
notification: Array<NotificationModel>;
|
||||||
|
notificationSettings: NotificationSettingsModel;
|
||||||
|
password: Scalars['String']['output'];
|
||||||
|
socialLink: Array<SocialLinkModel>;
|
||||||
|
stream: StreamModel;
|
||||||
|
telegramId?: Maybe<Scalars['String']['output']>;
|
||||||
|
totpSecret?: Maybe<Scalars['String']['output']>;
|
||||||
|
updatedAt: Scalars['DateTime']['output'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type VerificationInput = {
|
||||||
|
token: Scalars['String']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type FindChannelByUsernameQueryVariables = Exact<{
|
||||||
|
name: Scalars['String']['input'];
|
||||||
|
}>;
|
||||||
|
|
||||||
|
|
||||||
|
export type FindChannelByUsernameQuery = { __typename?: 'Query', findChannelByUsername: { __typename?: 'UserModel', name: string, avatar?: string | null, displayName: string, stream: { __typename?: 'StreamModel', title: string } } };
|
||||||
|
|
||||||
|
|
||||||
|
export const FindChannelByUsernameDocument = gql`
|
||||||
|
query FindChannelByUsername($name: String!) {
|
||||||
|
findChannelByUsername(name: $name) {
|
||||||
|
name
|
||||||
|
avatar
|
||||||
|
displayName
|
||||||
|
stream {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useFindChannelByUsernameQuery__
|
||||||
|
*
|
||||||
|
* To run a query within a React component, call `useFindChannelByUsernameQuery` and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useFindChannelByUsernameQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||||
|
* you can use to render your UI.
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const { data, loading, error } = useFindChannelByUsernameQuery({
|
||||||
|
* variables: {
|
||||||
|
* name: // value for 'name'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useFindChannelByUsernameQuery(baseOptions: Apollo.QueryHookOptions<FindChannelByUsernameQuery, FindChannelByUsernameQueryVariables> & ({ variables: FindChannelByUsernameQueryVariables; skip?: boolean; } | { skip: boolean; }) ) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useQuery<FindChannelByUsernameQuery, FindChannelByUsernameQueryVariables>(FindChannelByUsernameDocument, options);
|
||||||
|
}
|
||||||
|
export function useFindChannelByUsernameLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<FindChannelByUsernameQuery, FindChannelByUsernameQueryVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useLazyQuery<FindChannelByUsernameQuery, FindChannelByUsernameQueryVariables>(FindChannelByUsernameDocument, options);
|
||||||
|
}
|
||||||
|
export function useFindChannelByUsernameSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions<FindChannelByUsernameQuery, FindChannelByUsernameQueryVariables>) {
|
||||||
|
const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useSuspenseQuery<FindChannelByUsernameQuery, FindChannelByUsernameQueryVariables>(FindChannelByUsernameDocument, options);
|
||||||
|
}
|
||||||
|
export type FindChannelByUsernameQueryHookResult = ReturnType<typeof useFindChannelByUsernameQuery>;
|
||||||
|
export type FindChannelByUsernameLazyQueryHookResult = ReturnType<typeof useFindChannelByUsernameLazyQuery>;
|
||||||
|
export type FindChannelByUsernameSuspenseQueryHookResult = ReturnType<typeof useFindChannelByUsernameSuspenseQuery>;
|
||||||
|
export type FindChannelByUsernameQueryResult = Apollo.QueryResult<FindChannelByUsernameQuery, FindChannelByUsernameQueryVariables>;
|
||||||
10
frontend/src/graphql/queries/FindChannelByUsername.graphql
Normal file
10
frontend/src/graphql/queries/FindChannelByUsername.graphql
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
query FindChannelByUsername($name: String!) {
|
||||||
|
findChannelByUsername(name: $name) {
|
||||||
|
name
|
||||||
|
avatar
|
||||||
|
displayName
|
||||||
|
stream {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
frontend/src/libs/apollo-client.ts
Normal file
11
frontend/src/libs/apollo-client.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { ApolloClient, createHttpLink, InMemoryCache } from '@apollo/client';
|
||||||
|
|
||||||
|
const httpLink = createHttpLink({
|
||||||
|
uri: process.env.NEXT_PUBLIC_SERVER_URL,
|
||||||
|
credentials: 'include'
|
||||||
|
})
|
||||||
|
|
||||||
|
export const client = new ApolloClient({
|
||||||
|
link: httpLink,
|
||||||
|
cache: new InMemoryCache()
|
||||||
|
})
|
||||||
5
frontend/src/libs/i18n/config.ts
Normal file
5
frontend/src/libs/i18n/config.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export const COOKIE_NAME = 'language'
|
||||||
|
export const languages = ['ru', 'en'] as const
|
||||||
|
export const defaultLanguages: Language = 'ru';
|
||||||
|
|
||||||
|
export type Language = (typeof languages)[number]
|
||||||
14
frontend/src/libs/i18n/language.ts
Normal file
14
frontend/src/libs/i18n/language.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
'use server'
|
||||||
|
|
||||||
|
import { cookies } from "next/headers";
|
||||||
|
import { COOKIE_NAME, defaultLanguages, Language } from "./config";
|
||||||
|
|
||||||
|
export async function getCurrentLanguage() {
|
||||||
|
const cookieStore = await cookies();
|
||||||
|
return <Language>cookieStore.get(COOKIE_NAME)?.value ?? defaultLanguages;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function setCurrentLanguage(lang: Language) {
|
||||||
|
const cookieStore = await cookies();
|
||||||
|
return cookieStore.set(COOKIE_NAME, lang);
|
||||||
|
}
|
||||||
12
frontend/src/libs/i18n/request.ts
Normal file
12
frontend/src/libs/i18n/request.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { getRequestConfig } from 'next-intl/server';
|
||||||
|
import { getCurrentLanguage } from "./language"
|
||||||
|
|
||||||
|
export default getRequestConfig(async () => {
|
||||||
|
const locale = await getCurrentLanguage();
|
||||||
|
const messages = (await import(`../../../public/languages/${locale}.json`)).default;
|
||||||
|
|
||||||
|
return {
|
||||||
|
locale,
|
||||||
|
messages,
|
||||||
|
}
|
||||||
|
})
|
||||||
17
frontend/src/providers/ApolloClientProvider.tsx
Normal file
17
frontend/src/providers/ApolloClientProvider.tsx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { client } from '@/libs/apollo-client';
|
||||||
|
import { ApolloProvider } from '@apollo/client';
|
||||||
|
import React, { PropsWithChildren } from 'react';
|
||||||
|
|
||||||
|
const ApolloClientProvider = (props: PropsWithChildren) => {
|
||||||
|
const {children} = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ApolloProvider client={client}>
|
||||||
|
{children}
|
||||||
|
</ApolloProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ApolloClientProvider;
|
||||||
5705
frontend/yarn.lock
Normal file
5705
frontend/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user