[frontend]: add chat settings page
This commit is contained in:
parent
4c0e463aec
commit
ed59327cb7
20
frontend/src/app/(site)/dashboard/chat/page.tsx
Normal file
20
frontend/src/app/(site)/dashboard/chat/page.tsx
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { getTranslations } from 'next-intl/server';
|
||||||
|
|
||||||
|
import { ChangeChatSettings } from '@/components/features/chat/settings/ChangeChatSettings';
|
||||||
|
import { NO_INDEX_PAGE } from '@/libs/constants/seo.constants';
|
||||||
|
|
||||||
|
import type { Metadata } from 'next';
|
||||||
|
|
||||||
|
export async function generateMetadata(): Promise<Metadata> {
|
||||||
|
const t = await getTranslations('dashboard.chat.header');
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: t('heading'),
|
||||||
|
description: t('description'),
|
||||||
|
...NO_INDEX_PAGE,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const ChatSettingsPage = () => <ChangeChatSettings />;
|
||||||
|
|
||||||
|
export default ChatSettingsPage;
|
||||||
@ -0,0 +1,132 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
|
import { useTranslations } from 'next-intl';
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
|
import { toast } from 'sonner';
|
||||||
|
|
||||||
|
import { Form, FormField } from '@/components/ui/common/Form';
|
||||||
|
import { Heading } from '@/components/ui/elements/Heading';
|
||||||
|
import {
|
||||||
|
ToggleCard,
|
||||||
|
ToggleCardSkeleton,
|
||||||
|
} from '@/components/ui/elements/ToggleCard';
|
||||||
|
import { useChangeChatSettingsMutation } from '@/graphql/generated/output';
|
||||||
|
import { useCurrent } from '@/hooks/useCurrent';
|
||||||
|
import { changeChatSettingsSchema } from '@/schemas/chat/change-chat.settings.schema';
|
||||||
|
|
||||||
|
import type { TypeChangeChatSettingsSchema } from '@/schemas/chat/change-chat.settings.schema';
|
||||||
|
|
||||||
|
export const ChangeChatSettings = () => {
|
||||||
|
const t = useTranslations('dashboard.chat');
|
||||||
|
|
||||||
|
const { user, isLoadingProfile } = useCurrent();
|
||||||
|
|
||||||
|
const form = useForm<TypeChangeChatSettingsSchema>({
|
||||||
|
resolver: zodResolver(changeChatSettingsSchema),
|
||||||
|
values: {
|
||||||
|
isChatEnable: user?.stream.isChatEnable ?? false,
|
||||||
|
isChatFollowersOnly: user?.stream.isChatFollowersOnly ?? false,
|
||||||
|
isChatPremiumFollowersOnly:
|
||||||
|
user?.stream.isChatPremiumFollowersOnly ?? false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const [update, { loading: isLoadingUpdate }] = useChangeChatSettingsMutation({
|
||||||
|
onCompleted(data) {
|
||||||
|
toast.success(t('successMessage'));
|
||||||
|
},
|
||||||
|
onError() {
|
||||||
|
toast.error(t('errorMessage'));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function onChange(
|
||||||
|
field: keyof TypeChangeChatSettingsSchema,
|
||||||
|
value: boolean,
|
||||||
|
) {
|
||||||
|
form.setValue(field, value);
|
||||||
|
|
||||||
|
update({
|
||||||
|
variables: {
|
||||||
|
data: { ...form.getValues(), [field]: value },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="lg:px-10">
|
||||||
|
<Heading
|
||||||
|
description={t('header.description')}
|
||||||
|
size="lg"
|
||||||
|
title={t('header.heading')}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="mt-3 space-y-6">
|
||||||
|
{isLoadingProfile
|
||||||
|
? Array.from({ length: 3 }).map((_, index) => (
|
||||||
|
// eslint-disable-next-line react/no-array-index-key
|
||||||
|
<ToggleCardSkeleton key={index} />
|
||||||
|
))
|
||||||
|
: (
|
||||||
|
<Form {...form}>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="isChatEnable"
|
||||||
|
render={({ field }) => (
|
||||||
|
<ToggleCard
|
||||||
|
description={t('isChatEnabled.description')}
|
||||||
|
heading={t('isChatEnabled.heading')}
|
||||||
|
isDisabled={isLoadingUpdate}
|
||||||
|
value={field.value}
|
||||||
|
onChange={(value) => { onChange('isChatEnable', value); }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="isChatFollowersOnly"
|
||||||
|
render={({ field }) => (
|
||||||
|
<ToggleCard
|
||||||
|
description={t(
|
||||||
|
'isChatFollowersOnly.description',
|
||||||
|
)}
|
||||||
|
heading={t('isChatFollowersOnly.heading')}
|
||||||
|
isDisabled={isLoadingUpdate}
|
||||||
|
value={field.value}
|
||||||
|
onChange={(value) => { onChange('isChatFollowersOnly', value); }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="isChatPremiumFollowersOnly"
|
||||||
|
render={({ field }) => (
|
||||||
|
<ToggleCard
|
||||||
|
description={t(
|
||||||
|
'isChatPremiumFollowersOnly.description',
|
||||||
|
)}
|
||||||
|
heading={t(
|
||||||
|
'isChatPremiumFollowersOnly.heading',
|
||||||
|
)}
|
||||||
|
isDisabled={
|
||||||
|
isLoadingUpdate || !user?.isVerified
|
||||||
|
}
|
||||||
|
value={field.value}
|
||||||
|
onChange={(value) => {
|
||||||
|
onChange(
|
||||||
|
'isChatPremiumFollowersOnly',
|
||||||
|
value,
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Form>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -643,6 +643,20 @@ export type VerifyAccountMutationVariables = Exact<{
|
|||||||
|
|
||||||
export type VerifyAccountMutation = { __typename?: 'Mutation', verifyAccount: { __typename?: 'AuthModel', message?: string | null, user?: { __typename?: 'UserModel', isEmailVerified: boolean } | null } };
|
export type VerifyAccountMutation = { __typename?: 'Mutation', verifyAccount: { __typename?: 'AuthModel', message?: string | null, user?: { __typename?: 'UserModel', isEmailVerified: boolean } | null } };
|
||||||
|
|
||||||
|
export type ChangeChatSettingsMutationVariables = Exact<{
|
||||||
|
data: ChangeChatSettingsInput;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
|
||||||
|
export type ChangeChatSettingsMutation = { __typename?: 'Mutation', changeChatSettings: { __typename?: 'StreamModel', id: string } };
|
||||||
|
|
||||||
|
export type SendChatMessageMutationVariables = Exact<{
|
||||||
|
data: SendMessageInput;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
|
||||||
|
export type SendChatMessageMutation = { __typename?: 'Mutation', sendChatMessage: { __typename?: 'ChatMessageModel', streamId: string } };
|
||||||
|
|
||||||
export type CreateIngressMutationVariables = Exact<{
|
export type CreateIngressMutationVariables = Exact<{
|
||||||
ingressType: Scalars['Float']['input'];
|
ingressType: Scalars['Float']['input'];
|
||||||
}>;
|
}>;
|
||||||
@ -768,7 +782,7 @@ export type FindUnreadNotificationsCountQuery = { __typename?: 'Query', findUnre
|
|||||||
export type FindProfileQueryVariables = Exact<{ [key: string]: never; }>;
|
export type FindProfileQueryVariables = Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
|
|
||||||
export type FindProfileQuery = { __typename?: 'Query', findProfile: { __typename?: 'UserModel', avatar?: string | null, bio?: string | null, createdAt: any, email: string, id: string, name: string, updatedAt: any, isEmailVerified: boolean, isTotpEnabled: boolean, isVerified: boolean, displayName: string, socialLink: Array<{ __typename?: 'SocialLinkModel', title: string, url: string, position: number }>, notificationSettings?: { __typename?: 'NotificationSettingsModel', siteNotifications: boolean, telegramNotifications: boolean } | null, stream: { __typename?: 'StreamModel', serverUrl?: string | null, key?: string | null } } };
|
export type FindProfileQuery = { __typename?: 'Query', findProfile: { __typename?: 'UserModel', avatar?: string | null, bio?: string | null, createdAt: any, email: string, id: string, name: string, updatedAt: any, isEmailVerified: boolean, isTotpEnabled: boolean, isVerified: boolean, displayName: string, socialLink: Array<{ __typename?: 'SocialLinkModel', title: string, url: string, position: number }>, notificationSettings?: { __typename?: 'NotificationSettingsModel', siteNotifications: boolean, telegramNotifications: boolean } | null, stream: { __typename?: 'StreamModel', serverUrl?: string | null, key?: string | null, isChatEnable: boolean, isChatFollowersOnly: boolean, isChatPremiumFollowersOnly: boolean } } };
|
||||||
|
|
||||||
export type FindSessionsByUserQueryVariables = Exact<{ [key: string]: never; }>;
|
export type FindSessionsByUserQueryVariables = Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
@ -1053,6 +1067,72 @@ export function useVerifyAccountMutation(baseOptions?: Apollo.MutationHookOption
|
|||||||
export type VerifyAccountMutationHookResult = ReturnType<typeof useVerifyAccountMutation>;
|
export type VerifyAccountMutationHookResult = ReturnType<typeof useVerifyAccountMutation>;
|
||||||
export type VerifyAccountMutationResult = Apollo.MutationResult<VerifyAccountMutation>;
|
export type VerifyAccountMutationResult = Apollo.MutationResult<VerifyAccountMutation>;
|
||||||
export type VerifyAccountMutationOptions = Apollo.BaseMutationOptions<VerifyAccountMutation, VerifyAccountMutationVariables>;
|
export type VerifyAccountMutationOptions = Apollo.BaseMutationOptions<VerifyAccountMutation, VerifyAccountMutationVariables>;
|
||||||
|
export const ChangeChatSettingsDocument = gql`
|
||||||
|
mutation ChangeChatSettings($data: ChangeChatSettingsInput!) {
|
||||||
|
changeChatSettings(data: $data) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export type ChangeChatSettingsMutationFn = Apollo.MutationFunction<ChangeChatSettingsMutation, ChangeChatSettingsMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useChangeChatSettingsMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useChangeChatSettingsMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useChangeChatSettingsMutation` returns a tuple that includes:
|
||||||
|
* - A mutate function that you can call at any time to execute the mutation
|
||||||
|
* - An object with fields that represent the current status of the mutation's execution
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const [changeChatSettingsMutation, { data, loading, error }] = useChangeChatSettingsMutation({
|
||||||
|
* variables: {
|
||||||
|
* data: // value for 'data'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useChangeChatSettingsMutation(baseOptions?: Apollo.MutationHookOptions<ChangeChatSettingsMutation, ChangeChatSettingsMutationVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useMutation<ChangeChatSettingsMutation, ChangeChatSettingsMutationVariables>(ChangeChatSettingsDocument, options);
|
||||||
|
}
|
||||||
|
export type ChangeChatSettingsMutationHookResult = ReturnType<typeof useChangeChatSettingsMutation>;
|
||||||
|
export type ChangeChatSettingsMutationResult = Apollo.MutationResult<ChangeChatSettingsMutation>;
|
||||||
|
export type ChangeChatSettingsMutationOptions = Apollo.BaseMutationOptions<ChangeChatSettingsMutation, ChangeChatSettingsMutationVariables>;
|
||||||
|
export const SendChatMessageDocument = gql`
|
||||||
|
mutation SendChatMessage($data: SendMessageInput!) {
|
||||||
|
sendChatMessage(data: $data) {
|
||||||
|
streamId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export type SendChatMessageMutationFn = Apollo.MutationFunction<SendChatMessageMutation, SendChatMessageMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useSendChatMessageMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useSendChatMessageMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useSendChatMessageMutation` returns a tuple that includes:
|
||||||
|
* - A mutate function that you can call at any time to execute the mutation
|
||||||
|
* - An object with fields that represent the current status of the mutation's execution
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const [sendChatMessageMutation, { data, loading, error }] = useSendChatMessageMutation({
|
||||||
|
* variables: {
|
||||||
|
* data: // value for 'data'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useSendChatMessageMutation(baseOptions?: Apollo.MutationHookOptions<SendChatMessageMutation, SendChatMessageMutationVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useMutation<SendChatMessageMutation, SendChatMessageMutationVariables>(SendChatMessageDocument, options);
|
||||||
|
}
|
||||||
|
export type SendChatMessageMutationHookResult = ReturnType<typeof useSendChatMessageMutation>;
|
||||||
|
export type SendChatMessageMutationResult = Apollo.MutationResult<SendChatMessageMutation>;
|
||||||
|
export type SendChatMessageMutationOptions = Apollo.BaseMutationOptions<SendChatMessageMutation, SendChatMessageMutationVariables>;
|
||||||
export const CreateIngressDocument = gql`
|
export const CreateIngressDocument = gql`
|
||||||
mutation CreateIngress($ingressType: Float!) {
|
mutation CreateIngress($ingressType: Float!) {
|
||||||
createIngress(ingressType: $ingressType)
|
createIngress(ingressType: $ingressType)
|
||||||
@ -1757,6 +1837,9 @@ export const FindProfileDocument = gql`
|
|||||||
stream {
|
stream {
|
||||||
serverUrl
|
serverUrl
|
||||||
key
|
key
|
||||||
|
isChatEnable
|
||||||
|
isChatFollowersOnly
|
||||||
|
isChatPremiumFollowersOnly
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,5 @@
|
|||||||
|
mutation ChangeChatSettings($data: ChangeChatSettingsInput!) {
|
||||||
|
changeChatSettings(data: $data) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
mutation SendChatMessage($data: SendMessageInput!) {
|
||||||
|
sendChatMessage(data: $data) {
|
||||||
|
streamId
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -23,6 +23,9 @@ query FindProfile {
|
|||||||
stream {
|
stream {
|
||||||
serverUrl
|
serverUrl
|
||||||
key
|
key
|
||||||
|
isChatEnable
|
||||||
|
isChatFollowersOnly
|
||||||
|
isChatPremiumFollowersOnly
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
frontend/src/schemas/chat/change-chat.settings.schema.ts
Normal file
11
frontend/src/schemas/chat/change-chat.settings.schema.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
export const changeChatSettingsSchema = z.object({
|
||||||
|
isChatEnable: z.boolean(),
|
||||||
|
isChatFollowersOnly: z.boolean(),
|
||||||
|
isChatPremiumFollowersOnly: z.boolean(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TypeChangeChatSettingsSchema = z.infer<
|
||||||
|
typeof changeChatSettingsSchema
|
||||||
|
>;
|
||||||
7
frontend/src/schemas/chat/send-message.schema.ts
Normal file
7
frontend/src/schemas/chat/send-message.schema.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
export const sendMessageSchema = z.object({
|
||||||
|
text: z.string().min(1),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TypeSendMessageSchema = z.infer<typeof sendMessageSchema>;
|
||||||
Loading…
x
Reference in New Issue
Block a user