[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 = [
|
||||
...compat.extends("next/core-web-vitals", "next/typescript"),
|
||||
{
|
||||
ignores: ['src/graphql/generated']
|
||||
}
|
||||
];
|
||||
|
||||
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 createNextIntlPlugin from 'next-intl/plugin';
|
||||
|
||||
const withNextIntl = createNextIntlPlugin('./src/libs/i18n/request.ts')
|
||||
|
||||
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",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev --turbopack",
|
||||
"build": "next build",
|
||||
"dev": "yarn run codegen && next dev --turbopack",
|
||||
"build": "yarn run codegen && next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
"lint": "next lint",
|
||||
"codegen": "graphql-codegen --config graphql.config.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "19.1.0",
|
||||
"react-dom": "19.1.0",
|
||||
"next": "15.4.4"
|
||||
"@apollo/client": "3.13.9",
|
||||
"@graphql-codegen/cli": "5.0.7",
|
||||
"@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": {
|
||||
"typescript": "^5",
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^19",
|
||||
"@types/react-dom": "^19",
|
||||
"@tailwindcss/postcss": "^4",
|
||||
"tailwindcss": "^4",
|
||||
"eslint": "^9",
|
||||
"@eslint/eslintrc": "3.3.1",
|
||||
"@tailwindcss/postcss": "4.1.11",
|
||||
"@types/node": "22.17.0",
|
||||
"@types/react": "19.1.9",
|
||||
"@types/react-dom": "19.1.7",
|
||||
"eslint": "9.32.0",
|
||||
"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 { NextIntlClientProvider } from 'next-intl';
|
||||
import { getLocale, getMessages } from 'next-intl/server';
|
||||
import { Geist, Geist_Mono } from "next/font/google";
|
||||
import "../styles/globals.css";
|
||||
|
||||
@ -17,17 +20,24 @@ export const metadata: Metadata = {
|
||||
description: "Generated by create next app",
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
export default async function RootLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
const locale = await getLocale()
|
||||
const messages = await getMessages()
|
||||
|
||||
return (
|
||||
<html lang="en">
|
||||
<html lang={locale}>
|
||||
<body
|
||||
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
||||
>
|
||||
<ApolloClientProvider>
|
||||
<NextIntlClientProvider messages={messages}>
|
||||
{children}
|
||||
</NextIntlClientProvider>
|
||||
</ApolloClientProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
@ -1,103 +1,13 @@
|
||||
import Image from "next/image";
|
||||
'use client'
|
||||
|
||||
import { useTranslations } from 'next-intl';
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<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>
|
||||
const t = useTranslations('home')
|
||||
|
||||
<div className="flex gap-4 items-center flex-col sm:flex-row">
|
||||
<a
|
||||
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"
|
||||
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>
|
||||
return (
|
||||
<div>
|
||||
{t('title')}
|
||||
</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