feat: update i18n, next core

This commit is contained in:
SD 2025-02-17 01:01:39 +04:00
parent 9ecb7d6981
commit ccc3e2cb79
57 changed files with 446 additions and 425 deletions

View File

@ -1,5 +1,6 @@
// @ts-check // @ts-check
const withNextIntl = require('next-intl/plugin')(); const createNextIntlPlugin = require('next-intl/plugin');
const withNextIntl = createNextIntlPlugin();
const path = require('path'); const path = require('path');
const json = require('./package.json'); const json = require('./package.json');

579
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -23,20 +23,20 @@ export const useSessionTracking = (locale: string, sessionId: number) => {
useEffect(() => { useEffect(() => {
return () => { return () => {
window.clearInterval(timer.current); window?.clearInterval(timer.current);
} }
}, []); }, []);
const start = () => { const start = () => {
window.clearInterval(timer.current); window?.clearInterval(timer.current);
timer.current = window.setInterval(() => { timer.current = window?.setInterval(() => {
fetchData(); fetchData();
}, DURATION); }, DURATION);
}; };
const stop = () => { const stop = () => {
window.clearInterval(timer.current); window?.clearInterval(timer.current);
}; };
return { return {

View File

@ -1,8 +1,8 @@
import React from 'react'; import React from 'react';
import { unstable_setRequestLocale } from 'next-intl/server'; // import { unstable_setRequestLocale } from 'next-intl/server';
export default function Directions({ params: { locale } }: { params: { locale: string } }) { export default function Directions() {
unstable_setRequestLocale(locale); // unstable_setRequestLocale(locale);
return ( return (
<div className="main-popular"> <div className="main-popular">

View File

@ -1,10 +1,10 @@
import React from 'react'; import React from 'react';
import { unstable_setRequestLocale } from 'next-intl/server'; // import { unstable_setRequestLocale } from 'next-intl/server';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { Experts } from '../../../../components/Experts/Experts'; import { Experts } from '../../../../components/Experts/Experts';
export default function ExpertsPage({ params: { locale } }: { params: { locale: string } }) { export default function ExpertsPage({ params: { locale } }: { params: { locale: string } }) {
unstable_setRequestLocale(locale); // unstable_setRequestLocale(locale);
const t = useTranslations('Experts'); const t = useTranslations('Experts');
return ( return (

View File

@ -1,12 +1,12 @@
import React from 'react'; import React from 'react';
// import { useTranslations } from 'next-intl'; // import { useTranslations } from 'next-intl';
import Link from 'next/link'; import Link from 'next/link';
import { getTranslations, unstable_setRequestLocale } from 'next-intl/server'; import { getTranslations } from 'next-intl/server';
import { i18nText } from '../../../../i18nKeys'; import { i18nText } from '../../../../i18nKeys';
import { fetchBlogPosts } from '../../../../lib/contentful/blogPosts'; import { fetchBlogPosts } from '../../../../lib/contentful/blogPosts';
export default async function News({params: {locale}}: { params: { locale: string } }) { export default async function News({params: {locale}}: { params: { locale: string } }) {
unstable_setRequestLocale(locale); // unstable_setRequestLocale(locale);
const t = await getTranslations('Main'); const t = await getTranslations('Main');
const { data, total } = await fetchBlogPosts({preview: false, sticky: true}) const { data, total } = await fetchBlogPosts({preview: false, sticky: true})

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { Link } from '../../../../../../navigation'; import { Link } from '../../../../../../i18n/routing';
import { CustomSelect } from '../../../../../../components/view/CustomSelect'; import { CustomSelect } from '../../../../../../components/view/CustomSelect';
export default function AddOffer() { export default function AddOffer() {

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { Link } from '../../../../../../navigation'; import { Link } from '../../../../../../i18n/routing';
import { CustomSelect } from '../../../../../../components/view/CustomSelect'; import { CustomSelect } from '../../../../../../components/view/CustomSelect';
export default function NewTopic() { export default function NewTopic() {

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import type { Metadata } from 'next'; import type { Metadata } from 'next';
import { unstable_setRequestLocale } from 'next-intl/server'; // import { unstable_setRequestLocale } from 'next-intl/server';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { i18nText } from '../../../../../i18nKeys'; import { i18nText } from '../../../../../i18nKeys';
@ -10,7 +10,7 @@ export const metadata: Metadata = {
}; };
export default function Information({ params: { locale } }: { params: { locale: string } }) { export default function Information({ params: { locale } }: { params: { locale: string } }) {
unstable_setRequestLocale(locale); // unstable_setRequestLocale(locale);
const t = useTranslations('Account.LegalInformation'); const t = useTranslations('Account.LegalInformation');
return ( return (

View File

@ -1,6 +1,6 @@
'use client' 'use client'
import React from 'react'; import React from 'react';
import { Link } from '../../../../../../navigation'; import { Link } from '../../../../../../i18n/routing';
import { i18nText } from '../../../../../../i18nKeys'; import { i18nText } from '../../../../../../i18nKeys';
import {ChatMessages} from "../../../../../../components/Chat/ChatMessages"; import {ChatMessages} from "../../../../../../components/Chat/ChatMessages";
/* /*

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import type { Metadata } from 'next'; import type { Metadata } from 'next';
import { unstable_setRequestLocale } from 'next-intl/server'; // import { unstable_setRequestLocale } from 'next-intl/server';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import 'dayjs/locale/ru'; import 'dayjs/locale/ru';
import 'dayjs/locale/en'; import 'dayjs/locale/en';
@ -16,7 +16,7 @@ export const metadata: Metadata = {
}; };
export default function Notifications({ params: { locale } }: { params: { locale: string } }) { export default function Notifications({ params: { locale } }: { params: { locale: string } }) {
unstable_setRequestLocale(locale); // unstable_setRequestLocale(locale);
const date = dayjs('2022-05-22').locale(locale); const date = dayjs('2022-05-22').locale(locale);
return ( return (

View File

@ -1,10 +1,10 @@
import React from 'react'; import React from 'react';
import { unstable_setRequestLocale } from 'next-intl/server'; // import { unstable_setRequestLocale } from 'next-intl/server';
import { Link } from '../../../../../../navigation'; import { Link } from '../../../../../../i18n/routing';
import { i18nText } from '../../../../../../i18nKeys/'; import { i18nText } from '../../../../../../i18nKeys/';
export default function ChangePassword({ params: { locale } }: { params: { locale: string } }) { export default function ChangePassword({ params: { locale } }: { params: { locale: string } }) {
unstable_setRequestLocale(locale); // unstable_setRequestLocale(locale);
return ( return (
<> <>

View File

@ -1,10 +1,10 @@
import React, { Suspense } from 'react'; import React, { Suspense } from 'react';
import { unstable_setRequestLocale } from 'next-intl/server'; // import { unstable_setRequestLocale } from 'next-intl/server';
import { ProfileSettings } from '../../../../../components/Account'; import { ProfileSettings } from '../../../../../components/Account';
import { i18nText } from '../../../../../i18nKeys'; import { i18nText } from '../../../../../i18nKeys';
export default function Settings({ params: { locale } }: { params: { locale: string } }) { export default function Settings({ params: { locale } }: { params: { locale: string } }) {
unstable_setRequestLocale(locale); // unstable_setRequestLocale(locale);
return ( return (
<> <>

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { unstable_setRequestLocale } from 'next-intl/server'; // import { unstable_setRequestLocale } from 'next-intl/server';
import type { Metadata } from 'next'; import type { Metadata } from 'next';
import { i18nText } from '../../../../../i18nKeys'; import { i18nText } from '../../../../../i18nKeys';
@ -9,7 +9,7 @@ export const metadata: Metadata = {
}; };
export default function Support({ params: { locale } }: { params: { locale: string } }) { export default function Support({ params: { locale } }: { params: { locale: string } }) {
unstable_setRequestLocale(locale); // unstable_setRequestLocale(locale);
return ( return (
<> <>

View File

@ -1,5 +1,5 @@
import React, { Suspense } from 'react'; import React, { Suspense } from 'react';
import { unstable_setRequestLocale } from 'next-intl/server'; // import { unstable_setRequestLocale } from 'next-intl/server';
import { notFound } from 'next/navigation'; import { notFound } from 'next/navigation';
import { AccountMenu, RoomDetails, RoomsTabs } from '../../../../../../components/Account'; import { AccountMenu, RoomDetails, RoomsTabs } from '../../../../../../components/Account';
import { RoomsType } from '../../../../../../types/rooms'; import { RoomsType } from '../../../../../../types/rooms';
@ -13,7 +13,7 @@ export async function generateStaticParams({
} }
export default function RoomsDetailItem({ params: { locale, slug } }: { params: { locale: string, slug?: string[] } }) { export default function RoomsDetailItem({ params: { locale, slug } }: { params: { locale: string, slug?: string[] } }) {
unstable_setRequestLocale(locale); // unstable_setRequestLocale(locale);
const roomType: string = slug?.length > 0 && slug[0] || ''; const roomType: string = slug?.length > 0 && slug[0] || '';
const roomId: number | null = slug?.length > 1 && Number(slug[1]) || null; const roomId: number | null = slug?.length > 1 && Number(slug[1]) || null;

View File

@ -1,5 +1,5 @@
import React, { Suspense } from 'react'; import React, { Suspense } from 'react';
import { unstable_setRequestLocale } from 'next-intl/server'; // import { unstable_setRequestLocale } from 'next-intl/server';
import { notFound } from 'next/navigation'; import { notFound } from 'next/navigation';
import { AccountMenu, SessionDetails, SessionsTabs } from '../../../../../../components/Account'; import { AccountMenu, SessionDetails, SessionsTabs } from '../../../../../../components/Account';
import { SessionType } from '../../../../../../types/sessions'; import { SessionType } from '../../../../../../types/sessions';
@ -13,7 +13,7 @@ export async function generateStaticParams({
} }
export default function SessionDetailItem({ params: { locale, slug } }: { params: { locale: string, slug?: string[] } }) { export default function SessionDetailItem({ params: { locale, slug } }: { params: { locale: string, slug?: string[] } }) {
unstable_setRequestLocale(locale); // unstable_setRequestLocale(locale);
const sessionType: string = slug?.length > 0 && slug[0] || ''; const sessionType: string = slug?.length > 0 && slug[0] || '';
const sessionId: number | null = slug?.length > 1 && Number(slug[1]) || null; const sessionId: number | null = slug?.length > 1 && Number(slug[1]) || null;

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import type { Metadata } from 'next'; import type { Metadata } from 'next';
import { unstable_setRequestLocale } from 'next-intl/server'; // import { unstable_setRequestLocale } from 'next-intl/server';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { GeneralTopSection } from '../../../components/Page'; import { GeneralTopSection } from '../../../components/Page';
@ -9,8 +9,8 @@ export const metadata: Metadata = {
description: 'Bbuddy desc Take the lead with BB' description: 'Bbuddy desc Take the lead with BB'
}; };
export default function BbClientPage({ params: { locale } }: { params: { locale: string } }) { export default function BbClientPage() {
unstable_setRequestLocale(locale); // unstable_setRequestLocale(locale);
const t = useTranslations('BbClient'); const t = useTranslations('BbClient');
return ( return (

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import type { Metadata } from 'next'; import type { Metadata } from 'next';
import { unstable_setRequestLocale } from 'next-intl/server'; // import { unstable_setRequestLocale } from 'next-intl/server';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { GeneralTopSection } from '../../../components/Page'; import { GeneralTopSection } from '../../../components/Page';
import { ScreenCarousel } from '../../../components/Page/ScreenCarousel'; import { ScreenCarousel } from '../../../components/Page/ScreenCarousel';
@ -10,8 +10,8 @@ export const metadata: Metadata = {
description: 'Bbuddy desc Become a BB expert' description: 'Bbuddy desc Become a BB expert'
}; };
export default function BbExpertPage({ params: { locale } }: { params: { locale: string } }) { export default function BbExpertPage() {
unstable_setRequestLocale(locale); // unstable_setRequestLocale(locale);
const t = useTranslations('BbExpert'); const t = useTranslations('BbExpert');
return ( return (

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import type { Metadata } from 'next'; import type { Metadata } from 'next';
import { draftMode } from 'next/headers' import { draftMode } from 'next/headers'
import {unstable_setRequestLocale} from "next-intl/server"; // import {unstable_setRequestLocale} from "next-intl/server";
import Link from "next/link"; import Link from "next/link";
import {fetchBlogPosts} from "../../../../../lib/contentful/blogPosts"; import {fetchBlogPosts} from "../../../../../lib/contentful/blogPosts";
import {fetchBlogPostCategories} from "../../../../../lib/contentful/blogPostsCategories"; import {fetchBlogPostCategories} from "../../../../../lib/contentful/blogPostsCategories";
@ -20,9 +20,9 @@ interface BlogPostPageProps {
params: BlogPostPageParams params: BlogPostPageParams
} }
export default async function Blog({params, searchParams}: { params: BlogPostPageParams, searhParams?: {page: number} }) { export default async function Blog({params, searchParams}: { params: BlogPostPageParams, searchParams?: {page: number} }) {
unstable_setRequestLocale(params.locale); // unstable_setRequestLocale(params.locale);
const page = searchParams.page || undefined const page = searchParams?.page || undefined
return ( return (
<BlogPosts basePath={'/'+params.locale+'/blog/'} locale={params.locale} currentCat={params.slug} page={page}/> <BlogPosts basePath={'/'+params.locale+'/blog/'} locale={params.locale} currentCat={params.slug} page={page}/>
); );

View File

@ -2,7 +2,7 @@ import React from 'react';
import type { Metadata } from 'next'; import type { Metadata } from 'next';
import * as Util from "node:util"; import * as Util from "node:util";
import {fetchBlogPosts} from "../../../lib/contentful/blogPosts"; import {fetchBlogPosts} from "../../../lib/contentful/blogPosts";
import {unstable_setRequestLocale} from "next-intl/server"; // import {unstable_setRequestLocale} from "next-intl/server";
import Link from "next/link"; import Link from "next/link";
import {fetchBlogPostCategories} from "../../../lib/contentful/blogPostsCategories"; import {fetchBlogPostCategories} from "../../../lib/contentful/blogPostsCategories";
import {CustomPagination} from "../../../components/view/CustomPagination"; import {CustomPagination} from "../../../components/view/CustomPagination";
@ -24,10 +24,10 @@ export async function generateStaticParams(): Promise<BlogPostPageParams[]> {
} }
export default async function Blog({ params: { locale }, searchParams }: { params: { locale: string }, searhParams?: {page: number} }) { export default async function Blog({ params: { locale }, searchParams }: { params: { locale: string }, searchParams?: {page: number} }) {
unstable_setRequestLocale(locale); // unstable_setRequestLocale(locale);
const pageSize = DEFAULT_PAGE_SIZE const pageSize = DEFAULT_PAGE_SIZE
const page = searchParams.page || undefined const page = searchParams?.page || undefined
// BlogPosts('/'+locale+'/blog/', locale, pageSize) // BlogPosts('/'+locale+'/blog/', locale, pageSize)
return ( return (
@ -36,7 +36,6 @@ export default async function Blog({ params: { locale }, searchParams }: { param
locale={locale} locale={locale}
pageSize={pageSize} pageSize={pageSize}
page={page} page={page}
> />
</BlogPosts>
); );
} }

View File

@ -1,6 +1,6 @@
import React, { Suspense } from 'react'; import React, { Suspense } from 'react';
import type { Metadata } from 'next'; import type { Metadata } from 'next';
import { unstable_setRequestLocale } from 'next-intl/server'; // import { unstable_setRequestLocale } from 'next-intl/server';
import { notFound } from 'next/navigation'; import { notFound } from 'next/navigation';
import { getExpertById, getExpertsList } from '../../../../actions/experts'; import { getExpertById, getExpertsList } from '../../../../actions/experts';
import { import {
@ -20,7 +20,7 @@ export const metadata: Metadata = {
export async function generateStaticParams({ export async function generateStaticParams({
params: { locale }, params: { locale },
}: { params: { locale: string } }) { }: { params: { locale: string } }) {
unstable_setRequestLocale(locale); // unstable_setRequestLocale(locale);
const result: { locale: string, expertId: string }[] = []; const result: { locale: string, expertId: string }[] = [];
const experts = await getExpertsList(locale, { themesTagIds: [] }); const experts = await getExpertsList(locale, { themesTagIds: [] });

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import type { Metadata } from 'next'; import type { Metadata } from 'next';
import { unstable_setRequestLocale } from 'next-intl/server'; // import { unstable_setRequestLocale } from 'next-intl/server';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { Experts } from '../../../components/Experts/Experts'; import { Experts } from '../../../components/Experts/Experts';
@ -10,7 +10,7 @@ export const metadata: Metadata = {
}; };
export default function ExpertsPage({ params: { locale } }: { params: { locale: string } }) { export default function ExpertsPage({ params: { locale } }: { params: { locale: string } }) {
unstable_setRequestLocale(locale); // unstable_setRequestLocale(locale);
const t = useTranslations('Experts'); const t = useTranslations('Experts');
return ( return (

View File

@ -1,6 +1,7 @@
import React, { ReactNode, Suspense } from 'react'; import React, { ReactNode, Suspense } from 'react';
import { Metadata } from 'next'; import { Metadata } from 'next';
import { unstable_setRequestLocale } from 'next-intl/server'; import { NextIntlClientProvider } from 'next-intl';
import { getMessages } from 'next-intl/server';
import { notFound } from 'next/navigation'; import { notFound } from 'next/navigation';
import { ConfigProvider } from 'antd'; import { ConfigProvider } from 'antd';
import { AntdRegistry } from '@ant-design/nextjs-registry'; import { AntdRegistry } from '@ant-design/nextjs-registry';
@ -8,6 +9,7 @@ import { GoogleOAuthProvider } from '@react-oauth/google';
import theme from '../../constants/theme'; import theme from '../../constants/theme';
import { ALLOWED_LOCALES } from '../../constants/locale'; import { ALLOWED_LOCALES } from '../../constants/locale';
import { Header, Footer, AppConfig } from '../../components/Page'; import { Header, Footer, AppConfig } from '../../components/Page';
import { routing } from '../../i18n/routing';
type LayoutProps = { type LayoutProps = {
children: ReactNode; children: ReactNode;
@ -22,12 +24,15 @@ export const metadata: Metadata = {
title: 'Bbuddy' title: 'Bbuddy'
}; };
export default function LocaleLayout({ children, params: { locale } }: LayoutProps) { export default async function LocaleLayout({ children, params: { locale } }: LayoutProps) {
if (!ALLOWED_LOCALES.includes(locale as any)) notFound(); if (!routing.locales.includes(locale as any)) {
notFound();
}
unstable_setRequestLocale(locale); const messages = await getMessages();
return ( return (
<NextIntlClientProvider messages={messages}>
<AntdRegistry> <AntdRegistry>
<GoogleOAuthProvider clientId={process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID || ''}> <GoogleOAuthProvider clientId={process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID || ''}>
<ConfigProvider theme={theme}> <ConfigProvider theme={theme}>
@ -44,5 +49,6 @@ export default function LocaleLayout({ children, params: { locale } }: LayoutPro
</ConfigProvider> </ConfigProvider>
</GoogleOAuthProvider> </GoogleOAuthProvider>
</AntdRegistry> </AntdRegistry>
</NextIntlClientProvider>
); );
} }

View File

@ -8,7 +8,7 @@ import { getLoginByApple } from '../../../../actions/auth';
import { getUserData } from '../../../../actions/profile'; import { getUserData } from '../../../../actions/profile';
import { AUTH_TOKEN_KEY, AUTH_USER } from '../../../../constants/common'; import { AUTH_TOKEN_KEY, AUTH_USER } from '../../../../constants/common';
import { useLocalStorage } from '../../../../hooks/useLocalStorage'; import { useLocalStorage } from '../../../../hooks/useLocalStorage';
import { useRouter } from '../../../../navigation'; import { useRouter } from '../../../../i18n/routing';
export default function AppleLoginPage({ params: { locale } }: { params: { locale: string } }) { export default function AppleLoginPage({ params: { locale } }: { params: { locale: string } }) {
const params = useSearchParams(); const params = useSearchParams();

View File

@ -8,7 +8,7 @@ import { getRegisterByApple } from '../../../../actions/auth';
import { getUserData } from '../../../../actions/profile'; import { getUserData } from '../../../../actions/profile';
import { AUTH_TOKEN_KEY, AUTH_USER } from '../../../../constants/common'; import { AUTH_TOKEN_KEY, AUTH_USER } from '../../../../constants/common';
import { useLocalStorage } from "../../../../hooks/useLocalStorage"; import { useLocalStorage } from "../../../../hooks/useLocalStorage";
import { useRouter } from '../../../../navigation'; import { useRouter } from '../../../../i18n/routing';
export default function AppleRegisterPage({ params: { locale } }: { params: { locale: string } }) { export default function AppleRegisterPage({ params: { locale } }: { params: { locale: string } }) {
const params = useSearchParams(); const params = useSearchParams();

View File

@ -1,14 +1,14 @@
'use client'; 'use client';
import { useEffect, useState } from 'react';
import { Button } from 'antd'; import { Button } from 'antd';
import { useSelectedLayoutSegment, usePathname } from 'next/navigation'; import { useSelectedLayoutSegment, usePathname } from 'next/navigation';
import { Link } from '../../navigation'; import { Link } from '../../i18n/routing';
import { AUTH_TOKEN_KEY, AUTH_USER } from '../../constants/common'; import { AUTH_TOKEN_KEY, AUTH_USER } from '../../constants/common';
import {deleteStorageKey, useLocalStorage} from '../../hooks/useLocalStorage'; import {deleteStorageKey, useLocalStorage} from '../../hooks/useLocalStorage';
import { i18nText } from '../../i18nKeys'; import { i18nText } from '../../i18nKeys';
import { getMenuConfig } from '../../utils/account'; import { getMenuConfig } from '../../utils/account';
import {useEffect, useState} from "react"; import { getChatList } from '../../actions/chat/groups';
import {getChatList} from "../../actions/chat/groups";
export const AccountMenu = ({ locale }: { locale: string }) => { export const AccountMenu = ({ locale }: { locale: string }) => {
const selectedLayoutSegment = useSelectedLayoutSegment(); const selectedLayoutSegment = useSelectedLayoutSegment();

View File

@ -5,7 +5,7 @@ import { Form, message, Upload } from 'antd';
import type { UploadFile } from 'antd'; import type { UploadFile } from 'antd';
import ImgCrop from 'antd-img-crop'; import ImgCrop from 'antd-img-crop';
import { CameraOutlined, DeleteOutlined } from '@ant-design/icons'; import { CameraOutlined, DeleteOutlined } from '@ant-design/icons';
import { useRouter } from '../../navigation'; import { useRouter } from '../../i18n/routing';
import { i18nText } from '../../i18nKeys'; import { i18nText } from '../../i18nKeys';
import { ProfileRequest } from '../../types/profile'; import { ProfileRequest } from '../../types/profile';
import { validateImage } from '../../utils/account'; import { validateImage } from '../../utils/account';

View File

@ -5,7 +5,7 @@ import { EditRoomForm } from './EditRoomForm';
import debounce from 'lodash/debounce'; import debounce from 'lodash/debounce';
import { createRoom } from '../../../actions/rooms'; import { createRoom } from '../../../actions/rooms';
import { Loader } from '../../view/Loader'; import { Loader } from '../../view/Loader';
import { useRouter } from '../../../navigation'; import { useRouter } from '../../../i18n/routing';
import { RoomsType } from '../../../types/rooms'; import { RoomsType } from '../../../types/rooms';

View File

@ -5,7 +5,7 @@ import { Button, notification, Tag } from 'antd';
import { DeleteOutlined, LeftOutlined } from '@ant-design/icons'; import { DeleteOutlined, LeftOutlined } from '@ant-design/icons';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import Image from 'next/image'; import Image from 'next/image';
import { useRouter } from '../../../navigation'; import { useRouter } from '../../../i18n/routing';
import { Report, Room, RoomsType } from '../../../types/rooms'; import { Report, Room, RoomsType } from '../../../types/rooms';
import { i18nText } from '../../../i18nKeys'; import { i18nText } from '../../../i18nKeys';
import { LinkButton } from '../../view/LinkButton'; import { LinkButton } from '../../view/LinkButton';

View File

@ -14,7 +14,7 @@ import { getRecentRooms, getUpcomingRooms } from '../../../actions/rooms';
import { Loader } from '../../view/Loader'; import { Loader } from '../../view/Loader';
import { useLocalStorage } from '../../../hooks/useLocalStorage'; import { useLocalStorage } from '../../../hooks/useLocalStorage';
import { AUTH_TOKEN_KEY } from '../../../constants/common'; import { AUTH_TOKEN_KEY } from '../../../constants/common';
import { usePathname, useRouter } from '../../../navigation'; import { usePathname, useRouter } from '../../../i18n/routing';
import { i18nText } from '../../../i18nKeys'; import { i18nText } from '../../../i18nKeys';
import { CreateRoom } from './CreateRoom'; import { CreateRoom } from './CreateRoom';

View File

@ -5,7 +5,7 @@ import { Button, Empty, notification, Tag } from 'antd';
import { LeftOutlined, PlusOutlined, RightOutlined } from '@ant-design/icons'; import { LeftOutlined, PlusOutlined, RightOutlined } from '@ant-design/icons';
import Image from 'next/image'; import Image from 'next/image';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { Link, useRouter } from '../../../navigation'; import { Link, useRouter } from '../../../i18n/routing';
import { i18nText } from '../../../i18nKeys'; import { i18nText } from '../../../i18nKeys';
import { getDuration, getPrice } from '../../../utils/expert'; import { getDuration, getPrice } from '../../../utils/expert';
import { PublicUser, Session, SessionState, SessionType } from '../../../types/sessions'; import { PublicUser, Session, SessionState, SessionType } from '../../../types/sessions';

View File

@ -14,7 +14,7 @@ import { useLocalStorage } from '../../../hooks/useLocalStorage';
import { AUTH_TOKEN_KEY, AUTH_USER } from '../../../constants/common'; import { AUTH_TOKEN_KEY, AUTH_USER } from '../../../constants/common';
import { getRecentSessions, getRequestedSessions, getUpcomingSessions } from '../../../actions/sessions'; import { getRecentSessions, getRequestedSessions, getUpcomingSessions } from '../../../actions/sessions';
import { Session, Sessions, SessionType } from '../../../types/sessions'; import { Session, Sessions, SessionType } from '../../../types/sessions';
import { useRouter, usePathname } from '../../../navigation'; import { useRouter, usePathname } from '../../../i18n/routing';
import { i18nText } from '../../../i18nKeys'; import { i18nText } from '../../../i18nKeys';
type SessionsTabsProps = { type SessionsTabsProps = {

View File

@ -10,7 +10,7 @@ type PostsProps = {
basePath: string; basePath: string;
locale: string; locale: string;
pageSize?: number; pageSize?: number;
currentCat: string; currentCat?: string;
page?: number page?: number
}; };

View File

@ -3,7 +3,7 @@ import React, {useEffect, useState} from 'react';
import {AUTH_TOKEN_KEY} from '../../constants/common'; import {AUTH_TOKEN_KEY} from '../../constants/common';
import {getChatList, getChatMessages} from "../../actions/chat/groups"; import {getChatList, getChatMessages} from "../../actions/chat/groups";
import {useLocalStorage} from "../../hooks/useLocalStorage"; import {useLocalStorage} from "../../hooks/useLocalStorage";
import {Link} from "../../navigation"; import { Link } from "../../i18n/routing";
import dayjs from "dayjs"; import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime"; import relativeTime from "dayjs/plugin/relativeTime";
import {message} from "antd"; import {message} from "antd";

View File

@ -20,7 +20,7 @@ type CompProps = {
export const ChatMessages = ({ locale, groupId }: CompProps) => { export const ChatMessages = ({ locale, groupId }: CompProps) => {
const [jwt] = useLocalStorage(AUTH_TOKEN_KEY, ''); const [jwt] = useLocalStorage(AUTH_TOKEN_KEY, '');
const { newMessage, joinChat, readMessages, addListener } = SignalrConnection({ jwt }); const { newMessage, joinChat, readMessages, addListener } = SignalrConnection({ jwt }) || {};
//const messages = await getChatMessages(locale, jwt, groupId) //const messages = await getChatMessages(locale, jwt, groupId)
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
const [text, setText] = useState(''); const [text, setText] = useState('');
@ -60,7 +60,7 @@ export const ChatMessages = ({ locale, groupId }: CompProps) => {
const onConnected = (flag: boolean) =>{ const onConnected = (flag: boolean) =>{
if (flag) { if (flag && joinChat) {
joinChat(groupId) joinChat(groupId)
readUreaded() readUreaded()
} }
@ -73,7 +73,7 @@ export const ChatMessages = ({ locale, groupId }: CompProps) => {
msgs.push(message.id) msgs.push(message.id)
} }
}) })
readMessages(msgs) readMessages && readMessages(msgs);
} }
const onReceiveMessage = (payload: any) => { const onReceiveMessage = (payload: any) => {
@ -103,7 +103,7 @@ export const ChatMessages = ({ locale, groupId }: CompProps) => {
} else { } else {
setMessages([msg, ..._messages]); setMessages([msg, ..._messages]);
} }
readMessages([msg.id]) readMessages && readMessages([msg.id]);
} }
@ -120,16 +120,18 @@ export const ChatMessages = ({ locale, groupId }: CompProps) => {
} }
useEffect(() => { useEffect(() => {
addListener('onConnected', onConnected) if (addListener) {
addListener('ReceiveMessage', onReceiveMessage) addListener('onConnected', onConnected);
addListener('MessageWasRead', onOpponentRead) addListener('ReceiveMessage', onReceiveMessage);
addListener('MessageWasRead', onOpponentRead);
}
}, [messages, me, setMessages]); }, [messages, me, setMessages]);
const handleSendMessages = () => { const handleSendMessages = () => {
newMessage({ newMessage && newMessage({
GroupId: groupId.toString(), GroupId: groupId.toString(),
CreatorId: me.id, CreatorId: me.id,
Content: text Content: text

View File

@ -3,7 +3,7 @@
import React, { useCallback, useEffect, useState } from 'react'; import React, { useCallback, useEffect, useState } from 'react';
import { useSearchParams } from 'next/navigation'; import { useSearchParams } from 'next/navigation';
import debounce from 'lodash/debounce'; import debounce from 'lodash/debounce';
import { useRouter } from '../../navigation'; import { useRouter } from '../../i18n/routing';
import { AdditionalFilter } from '../../types/experts'; import { AdditionalFilter } from '../../types/experts';
import { getObjectByFilter, getObjectByAdditionalFilter, getSearchParamsString } from '../../utils/filter'; import { getObjectByFilter, getObjectByAdditionalFilter, getSearchParamsString } from '../../utils/filter';
import { CustomInput } from '../view/CustomInput'; import { CustomInput } from '../view/CustomInput';

View File

@ -16,7 +16,7 @@ import { AUTH_TOKEN_KEY, SESSION_DATA } from '../../constants/common';
import { ScheduleModal } from '../Modals/ScheduleModal'; import { ScheduleModal } from '../Modals/ScheduleModal';
import { ScheduleModalResult } from '../Modals/ScheduleModalResult'; import { ScheduleModalResult } from '../Modals/ScheduleModalResult';
import SignalrConnection from '../../lib/signalr-connection'; import SignalrConnection from '../../lib/signalr-connection';
import { useRouter } from '../../navigation'; import { useRouter } from '../../i18n/routing';
import { useLocalStorage } from '../../hooks/useLocalStorage'; import { useLocalStorage } from '../../hooks/useLocalStorage';
type ExpertDetailsProps = { type ExpertDetailsProps = {
@ -38,7 +38,7 @@ export const ExpertCard: FC<ExpertDetailsProps> = ({ expert, locale, expertId })
const isRus = locale === Locale.ru; const isRus = locale === Locale.ru;
const { publicCoachDetails: { tags = [], sessionCost = 0, sessionDuration = 0, coachLanguages = [] , id, botUserId} } = expert || {}; const { publicCoachDetails: { tags = [], sessionCost = 0, sessionDuration = 0, coachLanguages = [] , id, botUserId} } = expert || {};
const [jwt] = useLocalStorage(AUTH_TOKEN_KEY, ''); const [jwt] = useLocalStorage(AUTH_TOKEN_KEY, '');
const { joinChatPerson, closeConnection } = SignalrConnection({ jwt }); const { joinChatPerson, closeConnection } = SignalrConnection({ jwt }) || {};
const router = useRouter(); const router = useRouter();
@ -46,13 +46,13 @@ export const ExpertCard: FC<ExpertDetailsProps> = ({ expert, locale, expertId })
document?.addEventListener('show_pay_form', handleShowPayForm); document?.addEventListener('show_pay_form', handleShowPayForm);
return () => { return () => {
closeConnection(); if (closeConnection) closeConnection();
document?.removeEventListener('show_pay_form', handleShowPayForm); document?.removeEventListener('show_pay_form', handleShowPayForm);
} }
}, []); }, []);
const handleJoinChat = (id?: number) => { const handleJoinChat = (id?: number) => {
if (id) { if (id && joinChatPerson) {
joinChatPerson(id).then((res: any) => { joinChatPerson(id).then((res: any) => {
router.push(`/account/messages/${res.id}` as string); router.push(`/account/messages/${res.id}` as string);
}) })

View File

@ -6,7 +6,7 @@ import { List, Tag } from 'antd';
import { RightOutlined } from '@ant-design/icons'; import { RightOutlined } from '@ant-design/icons';
import isEqual from 'lodash/isEqual'; import isEqual from 'lodash/isEqual';
import Image from 'next/image'; import Image from 'next/image';
import { Link, useRouter } from '../../navigation'; import { Link, useRouter } from '../../i18n/routing';
import { ExpertsData, Filter, GeneralFilter } from '../../types/experts'; import { ExpertsData, Filter, GeneralFilter } from '../../types/experts';
import { getObjectByFilter, getObjectByAdditionalFilter, getSearchParamsString } from '../../utils/filter'; import { getObjectByFilter, getObjectByAdditionalFilter, getSearchParamsString } from '../../utils/filter';
import { getDuration, getPrice } from '../../utils/expert'; import { getDuration, getPrice } from '../../utils/expert';

View File

@ -4,7 +4,7 @@ import React, { useCallback, useEffect, useState } from 'react';
import { Button, Collapse, List } from 'antd'; import { Button, Collapse, List } from 'antd';
import type { CollapseProps } from 'antd'; import type { CollapseProps } from 'antd';
import { useSearchParams } from 'next/navigation'; import { useSearchParams } from 'next/navigation';
import { useRouter } from '../../navigation'; import { useRouter } from '../../i18n/routing';
import { Filter } from '../../types/experts'; import { Filter } from '../../types/experts';
import { Languages, SearchData, Tag } from '../../types/tags'; import { Languages, SearchData, Tag } from '../../types/tags';
import { getObjectByFilter, getObjectByAdditionalFilter, getSearchParamsString } from '../../utils/filter'; import { getObjectByFilter, getObjectByAdditionalFilter, getSearchParamsString } from '../../utils/filter';

View File

@ -7,7 +7,7 @@ import { Modal, Form, notification } from 'antd';
import { CloseOutlined } from '@ant-design/icons'; import { CloseOutlined } from '@ant-design/icons';
import { RegisterContent, ResetContent, FinishContent, EnterContent } from './authModalContent'; import { RegisterContent, ResetContent, FinishContent, EnterContent } from './authModalContent';
import { i18nText } from '../../i18nKeys'; import { i18nText } from '../../i18nKeys';
import { useRouter } from '../../navigation'; import { useRouter } from '../../i18n/routing';
import { AUTH_USER} from '../../constants/common'; import { AUTH_USER} from '../../constants/common';
import { getRegisterByApple, getLoginByApple } from '../../actions/auth'; import { getRegisterByApple, getLoginByApple } from '../../actions/auth';
import { getUserData } from '../../actions/profile'; import { getUserData } from '../../actions/profile';

View File

@ -3,7 +3,8 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { Modal, Result } from 'antd'; import { Modal, Result } from 'antd';
import { CloseOutlined } from '@ant-design/icons'; import { CloseOutlined } from '@ant-design/icons';
import { useSearchParams, useRouter } from 'next/navigation'; import { useSearchParams } from 'next/navigation';
import { useRouter } from '../../i18n/routing';
import { Stripe } from 'stripe'; import { Stripe } from 'stripe';
import { getStripePaymentStatus } from '../../actions/stripe'; import { getStripePaymentStatus } from '../../actions/stripe';
import { sessionPaymentConfirm } from '../../actions/sessions'; import { sessionPaymentConfirm } from '../../actions/sessions';

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import Link from 'next/link'; import Link from 'next/link';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { Link as IntlLink } from '../../../navigation'; import { Link as IntlLink } from '../../../i18n/routing';
import { i18nText } from '../../../i18nKeys'; import { i18nText } from '../../../i18nKeys';
export const Footer = ({ locale }: { locale: string }) => { export const Footer = ({ locale }: { locale: string }) => {

View File

@ -3,7 +3,7 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { Button } from 'antd'; import { Button } from 'antd';
import { useSelectedLayoutSegment } from 'next/navigation'; import { useSelectedLayoutSegment } from 'next/navigation';
import { Link } from '../../../navigation'; import { Link } from '../../../i18n/routing';
import { AUTH_TOKEN_KEY } from '../../../constants/common'; import { AUTH_TOKEN_KEY } from '../../../constants/common';
import { useLocalStorage } from '../../../hooks/useLocalStorage'; import { useLocalStorage } from '../../../hooks/useLocalStorage';
import { AuthModal } from '../../Modals/AuthModal'; import { AuthModal } from '../../Modals/AuthModal';

View File

@ -3,7 +3,7 @@
import React from 'react'; import React from 'react';
import { useSelectedLayoutSegment } from 'next/navigation'; import { useSelectedLayoutSegment } from 'next/navigation';
import dynamic from 'next/dynamic'; import dynamic from 'next/dynamic';
import { Link } from '../../../navigation'; import { Link } from '../../../i18n/routing';
type HeaderMenuProps = { type HeaderMenuProps = {
locale: string; locale: string;

View File

@ -3,7 +3,7 @@
import React, { FC, useState } from 'react'; import React, { FC, useState } from 'react';
import dynamic from 'next/dynamic'; import dynamic from 'next/dynamic';
import { useSelectedLayoutSegment } from 'next/navigation'; import { useSelectedLayoutSegment } from 'next/navigation';
import { Link } from '../../../navigation'; import { Link } from '../../../i18n/routing';
type HeaderMenuMobileProps = { type HeaderMenuMobileProps = {
locale: string; locale: string;

View File

@ -4,7 +4,7 @@ import React, { useTransition, useState } from 'react';
import { Dropdown } from 'antd'; import { Dropdown } from 'antd';
import type { MenuProps } from 'antd'; import type { MenuProps } from 'antd';
import { CaretDownOutlined, CaretUpOutlined } from '@ant-design/icons'; import { CaretDownOutlined, CaretUpOutlined } from '@ant-design/icons';
import { useRouter, usePathname } from '../../../navigation'; import { useRouter, usePathname } from '../../../i18n/routing';
import { LOCALES } from '../../../constants/locale'; import { LOCALES } from '../../../constants/locale';
import { Locale } from '../../../types/locale'; import { Locale } from '../../../types/locale';

View File

@ -3,7 +3,7 @@ import { HeaderMenu } from './HeaderMenu';
import { LanguageSwitcher } from './LanguageSwitcher'; import { LanguageSwitcher } from './LanguageSwitcher';
import { HeaderMobileMenu } from './HeaderMobileMenu'; import { HeaderMobileMenu } from './HeaderMobileMenu';
import { HEAD_ROUTES } from '../../../constants/routes'; import { HEAD_ROUTES } from '../../../constants/routes';
import { Link } from '../../../navigation'; import { Link } from '../../../i18n/routing';
import { i18nText } from '../../../i18nKeys'; import { i18nText } from '../../../i18nKeys';
type HeaderProps = { type HeaderProps = {

View File

@ -81,7 +81,7 @@ export const CheckoutForm: FC<PaymentFormProps> = ({ amount, sessionId, locale }
elements, elements,
clientSecret, clientSecret,
confirmParams: { confirmParams: {
return_url: window.location.href, return_url: window?.location?.href || '',
payment_method_data: { payment_method_data: {
allow_redisplay: 'limited', allow_redisplay: 'limited',
// billing_details: { // billing_details: {

View File

@ -2,7 +2,6 @@ import { Locale } from '../types/locale';
export const DEFAULT_LOCALE = Locale.en; export const DEFAULT_LOCALE = Locale.en;
export const ALLOWED_LOCALES = [Locale.en, Locale.ru, Locale.de, Locale.it, Locale.es, Locale.fr] as const; export const ALLOWED_LOCALES = [Locale.en, Locale.ru, Locale.de, Locale.it, Locale.es, Locale.fr] as const;
export const LOCALE_PREFIX = undefined;
export const LOCALES = { export const LOCALES = {
[Locale.en]: 'En', [Locale.en]: 'En',

View File

@ -2,14 +2,14 @@ import { useState, useEffect } from 'react';
export function getStorageValue (key: string, defaultValue: any) { export function getStorageValue (key: string, defaultValue: any) {
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
const saved = localStorage.getItem(key); const saved = localStorage?.getItem(key);
return saved || defaultValue; return saved || defaultValue;
} }
}; };
export function deleteStorageKey (key: string) { export function deleteStorageKey (key: string) {
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
localStorage.removeItem(key); localStorage?.removeItem(key);
} }
}; };
@ -19,7 +19,7 @@ export const useLocalStorage = (key: string, defaultValue: any) => {
}); });
useEffect(() => { useEffect(() => {
localStorage.setItem(key, value); localStorage?.setItem(key, value);
}, [key, value]); }, [key, value]);
return [value, setValue]; return [value, setValue];

View File

@ -14,21 +14,21 @@ export const useOauthWindow = () => {
if (data.messageType === 'oAuth') { if (data.messageType === 'oAuth') {
messageHandler(event); messageHandler(event);
window.removeEventListener('message', handler); window?.removeEventListener('message', handler);
} }
} }
window.removeEventListener('message', handler); window?.removeEventListener('message', handler);
if (!oauthWindow || oauthWindow.closed) { if (!oauthWindow || oauthWindow.closed) {
// окно ещё не существует, либо было закрыто // окно ещё не существует, либо было закрыто
oauthWindow = window.open(url, name, params)!; oauthWindow = window?.open(url, name, params)!;
} else { } else {
// окно уже существует // окно уже существует
oauthWindow!.focus(); oauthWindow!.focus();
} }
window.addEventListener('message', handler); window?.addEventListener('message', handler);
} }
return { return {

15
src/i18n/request.ts Normal file
View File

@ -0,0 +1,15 @@
import { getRequestConfig } from 'next-intl/server';
import { routing } from './routing';
export default getRequestConfig(async ({ requestLocale }) => {
let locale = await requestLocale;
if (!locale || !routing.locales.includes(locale as any)) {
locale = routing.defaultLocale;
}
return {
locale,
messages: (await import(`../../messages/${locale}.json`)).default
};
});

10
src/i18n/routing.ts Normal file
View File

@ -0,0 +1,10 @@
import { defineRouting } from 'next-intl/routing';
import { createNavigation } from 'next-intl/navigation';
import { ALLOWED_LOCALES, DEFAULT_LOCALE } from '../constants/locale';
export const routing = defineRouting({
locales: ALLOWED_LOCALES,
defaultLocale: DEFAULT_LOCALE
});
export const { Link, redirect, usePathname, useRouter, getPathname } = createNavigation(routing);

View File

@ -25,7 +25,7 @@ const chatsReceiveMessageMethodName = 'ChatsMessageCreated';
class SignalConnector { class SignalConnector {
private connection: HubConnection; private connection: HubConnection;
private events = {} as any; private events = {} as any;
static instance: SignalConnector; static instance?: SignalConnector;
constructor({ jwt }: { jwt?: string}) { constructor({ jwt }: { jwt?: string}) {
const options = { const options = {
accessTokenFactory: () => jwt accessTokenFactory: () => jwt
@ -69,10 +69,17 @@ class SignalConnector {
this.connection.invoke(sendChatMessagesSeenMethodName, messagesId).then(x => console.log(sendChatMessagesSeenMethodName, x)) this.connection.invoke(sendChatMessagesSeenMethodName, messagesId).then(x => console.log(sendChatMessagesSeenMethodName, x))
} }
public static getInstance({ jwt }: { jwt?: string }): SignalConnector { public static getInstance({ jwt }: { jwt?: string }): SignalConnector | undefined {
if (!SignalConnector.instance) if (!SignalConnector.instance) {
if (jwt) {
SignalConnector.instance = new SignalConnector({ jwt }); SignalConnector.instance = new SignalConnector({ jwt });
return SignalConnector.instance; return SignalConnector.instance;
} else {
return undefined;
}
} else {
return SignalConnector.instance;
}
} }
} }

View File

@ -1,11 +1,7 @@
import createMiddleware from 'next-intl/middleware'; import createMiddleware from 'next-intl/middleware';
import { ALLOWED_LOCALES, DEFAULT_LOCALE, LOCALE_PREFIX } from './constants/locale'; import { routing } from './i18n/routing';
export default createMiddleware({ export default createMiddleware(routing);
locales: ALLOWED_LOCALES,
localePrefix: LOCALE_PREFIX,
defaultLocale: DEFAULT_LOCALE
});
export const config = { export const config = {
matcher: ['/', '/(en|ru|de|it|es|fr)/:path*'] matcher: ['/', '/(en|ru|de|it|es|fr)/:path*']

View File

@ -1,5 +1,5 @@
.b-slider { .b-slider {
margin-top: -105px; //margin-top: -105px;
h2 { h2 {
margin: 40px 0 20px; margin: 40px 0 20px;