Merge pull request 'feature/russian-localization' (#145) from feature/russian-localization into develop
Reviewed-on: http://85.143.176.51:3000/free-land/front-end/pulls/145
This commit is contained in:
commit
49d15e538b
@ -59,5 +59,70 @@
|
|||||||
"services": {
|
"services": {
|
||||||
"fork": "Не удалось выполнить авторизацию в сервисе"
|
"fork": "Не удалось выполнить авторизацию в сервисе"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"articlePage": {
|
||||||
|
"abstract": "Введение",
|
||||||
|
"keywords": "Ключевые слова"
|
||||||
|
},
|
||||||
|
"navbar": {
|
||||||
|
"createNew": "Создать статью",
|
||||||
|
"about": {
|
||||||
|
"navTitle": "О проекте",
|
||||||
|
"aboutProject": "О Scipaper",
|
||||||
|
"contacts": "Контакты",
|
||||||
|
"help": "Помощь"
|
||||||
|
},
|
||||||
|
"library": {
|
||||||
|
"navTitle": "Моя библиотека",
|
||||||
|
"publications": "Публикации",
|
||||||
|
"favorites": "Избранное",
|
||||||
|
"collections": "Коллекции",
|
||||||
|
"recentViewed": "История"
|
||||||
|
},
|
||||||
|
"auth": {
|
||||||
|
"signIn": "Вход",
|
||||||
|
"signUp": "Регистрация"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"footer": {
|
||||||
|
"accountSettings": "Настройки аккаунта",
|
||||||
|
"about": "О scipaper",
|
||||||
|
"help": "Помощь",
|
||||||
|
"contactUs": "Контакты",
|
||||||
|
"allRightsReserved": "Все права защищены",
|
||||||
|
"termsOfUse": "Правила использования",
|
||||||
|
"privacyPolicy": "Политика конфиденциальности",
|
||||||
|
"coockiesPolicy": "Политика использования coockies",
|
||||||
|
"supportedBy": "Создано"
|
||||||
|
},
|
||||||
|
"mainPage": {
|
||||||
|
"title": "Библиотека научных статей с бесплатным доступом",
|
||||||
|
"search": "Поиск",
|
||||||
|
"article_one": "статьи",
|
||||||
|
"article_few": "статей",
|
||||||
|
"article_many": "статей",
|
||||||
|
"advancedSearch": "Расширенный поиск",
|
||||||
|
"featuredArticles": {
|
||||||
|
"title": "Популярные статьи",
|
||||||
|
"descriptionPart1": "Выберете интересующую вас ",
|
||||||
|
"descriptionPart2": "научную категорию",
|
||||||
|
"categories": {
|
||||||
|
"Medical": "Медицина",
|
||||||
|
"TechnicsAndTechlonogies": "Техника и технологии",
|
||||||
|
"Fundamental": "Естественые",
|
||||||
|
"Humanitarian": "Гуманитарные",
|
||||||
|
"Agricultural": "Аuрокультурa",
|
||||||
|
"Social": "Социальные"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"featuredAuthors": "Популярные авторы",
|
||||||
|
"more": "Больше",
|
||||||
|
"showAll": "Показать все"
|
||||||
|
},
|
||||||
|
"searchResults": {
|
||||||
|
"title": "Результаты поиска",
|
||||||
|
"totalResults":"Всего найдено",
|
||||||
|
"nothingFound": "Ничего не найдено"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -37,7 +37,7 @@ export const ArticleSearchResult = ({ searchItem }: Props) => {
|
|||||||
<Article.SubscriptionsButtons />
|
<Article.SubscriptionsButtons />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Article.Title linkTo={searchItem.id} className="text-2xl">
|
<Article.Title linkTo={`/article/${searchItem.id}`} className="text-2xl">
|
||||||
{searchItem.title}
|
{searchItem.title}
|
||||||
</Article.Title>
|
</Article.Title>
|
||||||
<Article.Authors emphasis="low" className="flex flex-wrap flex-row">
|
<Article.Authors emphasis="low" className="flex flex-wrap flex-row">
|
||||||
|
@ -3,7 +3,7 @@ import { SVGMedicine } from "../icons";
|
|||||||
import Typography from "components/typography/Typography";
|
import Typography from "components/typography/Typography";
|
||||||
import { Button } from "components/Button/Button";
|
import { Button } from "components/Button/Button";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { JsxElement } from "typescript";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
count?: number;
|
count?: number;
|
||||||
@ -13,6 +13,7 @@ type Props = {
|
|||||||
} & Omit<React.ComponentPropsWithoutRef<"div">, "">;
|
} & Omit<React.ComponentPropsWithoutRef<"div">, "">;
|
||||||
|
|
||||||
function CategoryCard({ count, title, iconChild, className, ...props }: Props) {
|
function CategoryCard({ count, title, iconChild, className, ...props }: Props) {
|
||||||
|
const [t, i18next] = useTranslation()
|
||||||
const iconChildStyle =
|
const iconChildStyle =
|
||||||
"h-7 fill-gray-500 stroke-gray-500 group-focus:fill-blue-600 group-active:fill-blue-600 group-focus:stroke-blue-600 group-active:stroke-blue-600";
|
"h-7 fill-gray-500 stroke-gray-500 group-focus:fill-blue-600 group-active:fill-blue-600 group-focus:stroke-blue-600 group-active:stroke-blue-600";
|
||||||
|
|
||||||
@ -34,7 +35,7 @@ function CategoryCard({ count, title, iconChild, className, ...props }: Props) {
|
|||||||
fontWeightVariant="bold"
|
fontWeightVariant="bold"
|
||||||
className="text-sm leading-6 min-w-max group-active:text-blue-600 group-focus:text-blue-600"
|
className="text-sm leading-6 min-w-max group-active:text-blue-600 group-focus:text-blue-600"
|
||||||
>
|
>
|
||||||
{title}
|
{t(title)}
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
<div className="max-w-max ">
|
<div className="max-w-max ">
|
||||||
@ -42,7 +43,7 @@ function CategoryCard({ count, title, iconChild, className, ...props }: Props) {
|
|||||||
fontWeightVariant="normal"
|
fontWeightVariant="normal"
|
||||||
className="text-xs text-gray-500 group-active:text-blue-600 group-focus:text-blue-600"
|
className="text-xs text-gray-500 group-active:text-blue-600 group-focus:text-blue-600"
|
||||||
>
|
>
|
||||||
{count} Items
|
{count} {t("mainPage.article", {count: count}).toString()}
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -31,6 +31,7 @@ import "swiper/css/pagination";
|
|||||||
import "swiper/css/navigation";
|
import "swiper/css/navigation";
|
||||||
// import "./styles.css";
|
// import "./styles.css";
|
||||||
import "swiper/css";
|
import "swiper/css";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* Article mock data */
|
/* Article mock data */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
@ -97,6 +98,7 @@ const FeaturedArticlesCards = () => {
|
|||||||
const navigationPrevRef = useRef(null);
|
const navigationPrevRef = useRef(null);
|
||||||
const navigationNextRef = useRef(null);
|
const navigationNextRef = useRef(null);
|
||||||
const paginationRef = useRef(null);
|
const paginationRef = useRef(null);
|
||||||
|
const [t, i18next] = useTranslation()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="slider-wrapper articles">
|
<div className="slider-wrapper articles">
|
||||||
@ -168,7 +170,7 @@ const FeaturedArticlesCards = () => {
|
|||||||
<Card.CardAction href={Articale.Link}>
|
<Card.CardAction href={Articale.Link}>
|
||||||
<Link to="*">
|
<Link to="*">
|
||||||
<Typography className="text-blue-500 font-bold">
|
<Typography className="text-blue-500 font-bold">
|
||||||
Read More
|
{t("mainPage.more")}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Link>
|
</Link>
|
||||||
<SVGCaretRight className="fill-blue-500 w-4 h-4" />
|
<SVGCaretRight className="fill-blue-500 w-4 h-4" />
|
||||||
|
@ -9,22 +9,25 @@ import {
|
|||||||
SVGTechnicsAndTechology,
|
SVGTechnicsAndTechology,
|
||||||
SVGFundamental,
|
SVGFundamental,
|
||||||
} from "components/icons";
|
} from "components/icons";
|
||||||
|
import { useTranslation} from "react-i18next";
|
||||||
|
|
||||||
const categories = [
|
const categories = [
|
||||||
{ id: 1, title: "Medical", count: 5617813, icon: <SVGMedicine /> },
|
{ id: 1, title: "mainPage.featuredArticles.categories.Medical", count: 5617813, icon: <SVGMedicine /> },
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
title: "Technics and Technology",
|
title: "mainPage.featuredArticles.categories.TechnicsAndTechlonogies",
|
||||||
count: 5617813,
|
count: 5617813,
|
||||||
icon: <SVGTechnicsAndTechology />,
|
icon: <SVGTechnicsAndTechology />,
|
||||||
},
|
},
|
||||||
{ id: 3, title: "Fundamental", count: 5617813, icon: <SVGFundamental /> },
|
{ id: 3, title: "mainPage.featuredArticles.categories.Fundamental", count: 5617813, icon: <SVGFundamental /> },
|
||||||
{ id: 4, title: "Humanitarian", count: 5617813, icon: <SVGHumanitarian /> },
|
{ id: 4, title: "mainPage.featuredArticles.categories.Humanitarian", count: 5617813, icon: <SVGHumanitarian /> },
|
||||||
{ id: 5, title: "Agricultural", count: 5617813, icon: <SVGAgricultural /> },
|
{ id: 5, title: "mainPage.featuredArticles.categories.Agricultural", count: 5617813, icon: <SVGAgricultural /> },
|
||||||
{ id: 6, title: "Social", count: 5617813, icon: <SVGSocials /> },
|
{ id: 6, title: "mainPage.featuredArticles.categories.Social", count: 5617813, icon: <SVGSocials /> },
|
||||||
];
|
];
|
||||||
|
|
||||||
export function FeaturedArticlesCategories() {
|
export function FeaturedArticlesCategories() {
|
||||||
|
const [t, i18next] = useTranslation();
|
||||||
|
|
||||||
const categoryCards = useMemo(
|
const categoryCards = useMemo(
|
||||||
() =>
|
() =>
|
||||||
categories.map((category) => (
|
categories.map((category) => (
|
||||||
@ -45,11 +48,11 @@ export function FeaturedArticlesCategories() {
|
|||||||
fontWeightVariant="semibold"
|
fontWeightVariant="semibold"
|
||||||
className="text-3xl mb-2"
|
className="text-3xl mb-2"
|
||||||
>
|
>
|
||||||
Featured articles
|
{t("mainPage.featuredArticles.title")}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography htmlTag="h2" className="text-base text-gray-500">
|
<Typography htmlTag="h2" className="text-base text-gray-500">
|
||||||
Select the category of science <br className="visible sm:hidden" />
|
{t("mainPage.featuredArticles.descriptionPart1")}<br className="visible sm:hidden" />
|
||||||
you are interested in
|
{t("mainPage.featuredArticles.descriptionPart2")}
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
<div className="py-8 px-10 flex md:flex justify-start md:justify-center md:flex-wrap overflow-x-scroll md:overflow-hidden snap-x scroll-smooth overscroll-x-contain">
|
<div className="py-8 px-10 flex md:flex justify-start md:justify-center md:flex-wrap overflow-x-scroll md:overflow-hidden snap-x scroll-smooth overscroll-x-contain">
|
||||||
|
@ -17,12 +17,9 @@ import "swiper/css/navigation";
|
|||||||
// import "./styles.css";
|
// import "./styles.css";
|
||||||
import "swiper/css";
|
import "swiper/css";
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
/* Icons */
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
import { ReactComponent as SVGCaretRight } from "assets/svg/caret-right.svg";
|
import { ReactComponent as SVGCaretRight } from "assets/svg/caret-right.svg";
|
||||||
import Link from "../../typography/Link";
|
import Link from "../../typography/Link";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* Variables */
|
/* Variables */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
@ -73,10 +70,12 @@ if (authors.length == 2) {
|
|||||||
* Featured authors component to display ...
|
* Featured authors component to display ...
|
||||||
*/
|
*/
|
||||||
export default function FeaturedAuthorsCards(): JSX.Element {
|
export default function FeaturedAuthorsCards(): JSX.Element {
|
||||||
|
const [t, i18next] = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{/* The Title of Featured Authors section */}
|
{/* The Title of Featured Authors section */}
|
||||||
<Heading className="text-center my-8">Featured Authors</Heading>
|
<Heading className="text-center my-8 text-3xl font-semibold">{t("mainPage.featuredAuthors")}</Heading>
|
||||||
|
|
||||||
{/* Featured Authors section */}
|
{/* Featured Authors section */}
|
||||||
<div className="slider-wrapper Authors">
|
<div className="slider-wrapper Authors">
|
||||||
@ -134,7 +133,7 @@ export default function FeaturedAuthorsCards(): JSX.Element {
|
|||||||
|
|
||||||
<Card.CardAction href={card.Link}>
|
<Card.CardAction href={card.Link}>
|
||||||
<Link className="text-blue-500 font-bold" to="*">
|
<Link className="text-blue-500 font-bold" to="*">
|
||||||
See More
|
{t('mainPage.more')}
|
||||||
</Link>
|
</Link>
|
||||||
<SVGCaretRight className="fill-blue-500 w-4 h-4" />
|
<SVGCaretRight className="fill-blue-500 w-4 h-4" />
|
||||||
</Card.CardAction>
|
</Card.CardAction>
|
||||||
@ -188,7 +187,7 @@ export default function FeaturedAuthorsCards(): JSX.Element {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Button emphasis="high" className="font-bold m-auto my-8">
|
<Button emphasis="high" className="font-bold m-auto my-8">
|
||||||
Show All
|
{t("mainPage.showAll")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -2,24 +2,32 @@
|
|||||||
/* Imports */
|
/* Imports */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import {t as nextT} from "i18next";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
import { SearchBar } from "../../search/SearchBar";
|
import { SearchBar } from "../../search/SearchBar";
|
||||||
|
import { formatNumber } from "core/helpers";
|
||||||
|
|
||||||
export default function MainSection() {
|
export default function MainSection() {
|
||||||
|
const { t, i18n } = useTranslation();
|
||||||
|
const amountArticles = 4202020
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="bg-main bg-center bg-cover bg-origin-border bg-no-repeat min-h-[100vh] py-32 px-2 sm:px-6 md:px-6 lg:px-0 items-center flex justify-center ">
|
<section className="bg-main bg-center bg-cover bg-origin-border bg-no-repeat min-h-[100vh] py-32 px-2 sm:px-6 md:px-6 lg:px-0 items-center flex justify-center ">
|
||||||
<div className="flex-col">
|
<div className="flex-col">
|
||||||
<div className="m-auto text-center font-bold text-4xl ">
|
<div className="m-auto text-center font-bold text-4xl ">
|
||||||
Scientific Library with Free Access
|
{t("mainPage.title")}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row items-center justify-center space-x-3 pt-2">
|
<div className="flex flex-row items-center justify-center space-x-3 pt-2">
|
||||||
<div className=" text-2xl text-gray-400">Search</div>
|
<div className=" text-2xl text-gray-400">{t("mainPage.search")}</div>
|
||||||
<div className=" text-3xl text-blue-500">320 455</div>
|
<div className=" text-3xl text-blue-500">{formatNumber(amountArticles)}</div>
|
||||||
<div className=" text-2xl text-gray-400">Items</div>
|
<div className=" text-2xl text-gray-400">{nextT("mainPage.article", {count: amountArticles}).toString()}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="max-w-xl m-auto pt-16 ">
|
<div className="max-w-xl m-auto pt-16 ">
|
||||||
<SearchBar />
|
<SearchBar />
|
||||||
<div className="mt-7 pr-1 text-right font-semibold text-sm">
|
<div className="mt-7 pr-1 text-right font-semibold text-sm">
|
||||||
Advanced Search
|
{t("mainPage.advancedSearch")}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,10 +4,12 @@ import { useSearchStoreImplementation } from "searchResults/data/searchStoreImpl
|
|||||||
import { useSearchViewModel } from "../searchResults/controller/searchResultsViewModel";
|
import { useSearchViewModel } from "../searchResults/controller/searchResultsViewModel";
|
||||||
import { ArticleSearchResult } from "./ArticleSearchResult";
|
import { ArticleSearchResult } from "./ArticleSearchResult";
|
||||||
import { Loader } from "./Loader/Loader";
|
import { Loader } from "./Loader/Loader";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
export const SearchResultSection = () => {
|
export const SearchResultSection = () => {
|
||||||
const store = useSearchStoreImplementation();
|
const store = useSearchStoreImplementation();
|
||||||
const { searchResults, isLoading } = useSearchViewModel(store);
|
const { searchResults, isLoading } = useSearchViewModel(store);
|
||||||
|
const [t, i18next] = useTranslation()
|
||||||
|
|
||||||
function getResults() {
|
function getResults() {
|
||||||
if (searchResults === undefined || searchResults?.data.length === 0) {
|
if (searchResults === undefined || searchResults?.data.length === 0) {
|
||||||
@ -16,7 +18,7 @@ export const SearchResultSection = () => {
|
|||||||
fontWeightVariant="semibold"
|
fontWeightVariant="semibold"
|
||||||
className="text-xl w-full text-center items-center py-3"
|
className="text-xl w-full text-center items-center py-3"
|
||||||
>
|
>
|
||||||
Nothing found.
|
{t("searchResults.nothingFound")}.
|
||||||
</Typography>
|
</Typography>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -31,10 +33,10 @@ export const SearchResultSection = () => {
|
|||||||
<div className="p-4 md:px-6 md:py-8">
|
<div className="p-4 md:px-6 md:py-8">
|
||||||
<div className="pb-2">
|
<div className="pb-2">
|
||||||
<Typography fontWeightVariant="semibold" className="text-3xl">
|
<Typography fontWeightVariant="semibold" className="text-3xl">
|
||||||
Search Results
|
{t("searchResults.title")}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography className="text-gray-300 text-sm">
|
<Typography className="text-gray-300 text-sm">
|
||||||
Total results: {searchResults?.meta.total}
|
{t("searchResults.totalResults")}: {searchResults?.meta.total}
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
<hr className="w-full border-gray-100" />
|
<hr className="w-full border-gray-100" />
|
||||||
|
@ -8,10 +8,13 @@ import Container from "components/Container";
|
|||||||
import NotFound from "./NotFound";
|
import NotFound from "./NotFound";
|
||||||
import { SVGSearch } from "components/icons";
|
import { SVGSearch } from "components/icons";
|
||||||
import BaseLayout from "components/BaseLayout";
|
import BaseLayout from "components/BaseLayout";
|
||||||
|
import Typography from "components/typography/Typography";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const AnArticle = () => {
|
const AnArticle = () => {
|
||||||
const store = useArticleStore();
|
const store = useArticleStore();
|
||||||
const { article, hasError, shouldShowLoading } = useArticleViewModel(store);
|
const { article, hasError, shouldShowLoading } = useArticleViewModel(store);
|
||||||
|
const { i18n, t } = useTranslation();
|
||||||
|
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const newId = `${id}`;
|
const newId = `${id}`;
|
||||||
@ -46,9 +49,13 @@ const AnArticle = () => {
|
|||||||
<ArticlePart.Article.InteractionButtons emphasis="high" />
|
<ArticlePart.Article.InteractionButtons emphasis="high" />
|
||||||
{article?.tags && (
|
{article?.tags && (
|
||||||
<div className="keywords my-10 flex flex-col gap-2">
|
<div className="keywords my-10 flex flex-col gap-2">
|
||||||
<ArticlePart.Article.Title className="text-2xl">
|
<Typography
|
||||||
Keywords
|
className="text-2xl"
|
||||||
</ArticlePart.Article.Title>
|
fontWeightVariant="semibold"
|
||||||
|
>
|
||||||
|
{t('articlePage.keywords')}
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
|
||||||
<ArticlePart.Article.Keywords className="transition ease-in-out delay-50">
|
<ArticlePart.Article.Keywords className="transition ease-in-out delay-50">
|
||||||
{article?.tags}
|
{article?.tags}
|
||||||
@ -56,9 +63,12 @@ const AnArticle = () => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="abstract my-10 flex flex-col gap-2">
|
<div className="abstract my-10 flex flex-col gap-2">
|
||||||
<ArticlePart.Article.Title className="text-2xl">
|
<Typography
|
||||||
Abstract
|
className="text-2xl"
|
||||||
</ArticlePart.Article.Title>
|
fontWeightVariant="semibold"
|
||||||
|
>
|
||||||
|
{t('articlePage.abstract')}
|
||||||
|
</Typography>
|
||||||
<ArticlePart.Article.Description>
|
<ArticlePart.Article.Description>
|
||||||
{article?.summary !== undefined ? (
|
{article?.summary !== undefined ? (
|
||||||
article?.summary
|
article?.summary
|
||||||
|
@ -6,29 +6,29 @@ import Typography from "components/typography/Typography";
|
|||||||
import { SVGFacebook, SVGInstagram, SVGCircle } from "components/icons";
|
import { SVGFacebook, SVGInstagram, SVGCircle } from "components/icons";
|
||||||
import { RouterLink } from "components/typography/RouterLink";
|
import { RouterLink } from "components/typography/RouterLink";
|
||||||
import Link from "components/typography/Link";
|
import Link from "components/typography/Link";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* Define consts */
|
/* Define consts */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
const mainLinks = [
|
const mainLinks = [
|
||||||
{ label: "account settings", url: "/account/settings", disabled: false },
|
{ label: "footer.accountSettings", url: "/account/settings", disabled: false },
|
||||||
{ label: "about freeland", url: "/about", disabled: false },
|
{ label: "footer.about", url: "/about", disabled: false },
|
||||||
{ label: "help", url: "/help", disabled: false },
|
{ label: "footer.help", url: "/help", disabled: false },
|
||||||
{ label: "contact us", url: "/contact-us", disabled: false },
|
{ label: "footer.contactUs", url: "/contact-us", disabled: false },
|
||||||
];
|
];
|
||||||
|
|
||||||
const secondaryLinks = [
|
const secondaryLinks = [
|
||||||
{ index: 1, label: "Terms of Use", url: "/terms-of-use", disabled: false },
|
{ index: 1, label: "footer.termsOfUse", url: "/terms-of-use", disabled: false },
|
||||||
{
|
{
|
||||||
index: 2,
|
index: 2,
|
||||||
label: "Privacy Policy",
|
label: "footer.privacyPolicy",
|
||||||
url: "/privacy-policy",
|
url: "/privacy-policy",
|
||||||
disabled: false,
|
disabled: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
index: 3,
|
index: 3,
|
||||||
label: "Cookies Policy",
|
label: "footer.coockiesPolicy",
|
||||||
url: "/cookies-policy",
|
url: "/cookies-policy",
|
||||||
disabled: false,
|
disabled: false,
|
||||||
},
|
},
|
||||||
@ -48,6 +48,8 @@ const circleDivider = (
|
|||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
export function Footer() {
|
export function Footer() {
|
||||||
|
|
||||||
|
const { t, i18n } = useTranslation();
|
||||||
/* -------------------------- Part with main links -------------------------- */
|
/* -------------------------- Part with main links -------------------------- */
|
||||||
const mainLinksPart = useMemo(
|
const mainLinksPart = useMemo(
|
||||||
() =>
|
() =>
|
||||||
@ -59,7 +61,7 @@ export function Footer() {
|
|||||||
to={link.url}
|
to={link.url}
|
||||||
>
|
>
|
||||||
<Typography className="" fontWeightVariant="semibold" htmlTag="p">
|
<Typography className="" fontWeightVariant="semibold" htmlTag="p">
|
||||||
{link.label.toUpperCase()}
|
{t(link.label).toUpperCase()}
|
||||||
</Typography>
|
</Typography>
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
)),
|
)),
|
||||||
@ -72,7 +74,7 @@ export function Footer() {
|
|||||||
<div className="flex flex-row items-center">
|
<div className="flex flex-row items-center">
|
||||||
{link.index != 1 && circleDivider}
|
{link.index != 1 && circleDivider}
|
||||||
<Link key={link.url} disabled={link.disabled} to={link.url}>
|
<Link key={link.url} disabled={link.disabled} to={link.url}>
|
||||||
{link.label}
|
{t(link.label) }
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
)),
|
)),
|
||||||
@ -88,7 +90,7 @@ export function Footer() {
|
|||||||
<div className="sm:col-span-1">
|
<div className="sm:col-span-1">
|
||||||
<Link to="*">
|
<Link to="*">
|
||||||
<Typography className="text-2xl" fontWeightVariant="semibold">
|
<Typography className="text-2xl" fontWeightVariant="semibold">
|
||||||
Freeland
|
Scipaper
|
||||||
</Typography>
|
</Typography>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
@ -108,13 +110,13 @@ export function Footer() {
|
|||||||
<section className="w-full flex flex-col md:flex-row text-gray-500 text-xs justify-between">
|
<section className="w-full flex flex-col md:flex-row text-gray-500 text-xs justify-between">
|
||||||
<div className="flex flex-col md:flex-row justify-center items-center">
|
<div className="flex flex-col md:flex-row justify-center items-center">
|
||||||
<Typography>
|
<Typography>
|
||||||
@ Copyright 2022 Freeland - All rights reserved
|
@ Copyright 2022 Freeland - {t("footer.allRightsReserved")}
|
||||||
</Typography>
|
</Typography>
|
||||||
<div className="hidden md:flex">{circleDivider}</div>
|
<div className="hidden md:flex">{circleDivider}</div>
|
||||||
<div className="flex flex-row items-center">{secondaryLinksPart}</div>
|
<div className="flex flex-row items-center">{secondaryLinksPart}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row justify-center md:justify-end">
|
<div className="flex flex-row justify-center md:justify-end">
|
||||||
Supported by
|
{t("footer.supportedBy")}
|
||||||
<Typography className="ml-1 lg:ml-2" fontWeightVariant="bold">
|
<Typography className="ml-1 lg:ml-2" fontWeightVariant="bold">
|
||||||
Comfortel
|
Comfortel
|
||||||
</Typography>
|
</Typography>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { useState } from "react";
|
import { useState, useTransition } from "react";
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* Components */
|
/* Components */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
@ -23,11 +23,14 @@ import {
|
|||||||
SVGFile,
|
SVGFile,
|
||||||
SVGEye,
|
SVGEye,
|
||||||
} from "components/icons";
|
} from "components/icons";
|
||||||
|
import i18n from "localization/i18n";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const Header = () => {
|
const Header = () => {
|
||||||
const [authenticated, setAuthenticated] = useState(false);
|
const [authenticated, setAuthenticated] = useState(false);
|
||||||
const onClick = () => setAuthenticated(true);
|
const onClick = () => setAuthenticated(true);
|
||||||
const [notification, setNotification] = useState(false);
|
const [notification, setNotification] = useState(false);
|
||||||
|
const { t, i18n } = useTranslation();
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* Implement Header Component */
|
/* Implement Header Component */
|
||||||
@ -66,36 +69,36 @@ const Header = () => {
|
|||||||
className="text-blue-500 px-4 font-bold uppercase"
|
className="text-blue-500 px-4 font-bold uppercase"
|
||||||
to="/create-new"
|
to="/create-new"
|
||||||
>
|
>
|
||||||
Create new
|
{t('navbar.createNew')}
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
{/* Link Create now - end - */}
|
{/* Link Create now - end - */}
|
||||||
|
|
||||||
{/* Dropdown Menu My library - start - */}
|
{/* Dropdown Menu My library - start - */}
|
||||||
<ContextMenu
|
<ContextMenu
|
||||||
emphasis="high"
|
emphasis="high"
|
||||||
button="My library"
|
button={t('navbar.library.navTitle')}
|
||||||
className="border-none uppercase"
|
className="border-none uppercase"
|
||||||
>
|
>
|
||||||
<ContextMenuAction
|
<ContextMenuAction
|
||||||
caption="My Publications"
|
caption={t('navbar.library.publications')}
|
||||||
action={() => console.log("My publications")}
|
action={() => console.log("My publications")}
|
||||||
icon={<SVGFile className="stroke-black " />}
|
icon={<SVGFile className="stroke-black " />}
|
||||||
></ContextMenuAction>
|
></ContextMenuAction>
|
||||||
|
|
||||||
<ContextMenuAction
|
<ContextMenuAction
|
||||||
caption="My Favorites"
|
caption={t('navbar.library.favorites')}
|
||||||
action={() => console.log("My Favorites")}
|
action={() => console.log("My Favorites")}
|
||||||
icon={<SVGFavoriteOutlined className="stroke-black" />}
|
icon={<SVGFavoriteOutlined className="stroke-black" />}
|
||||||
></ContextMenuAction>
|
></ContextMenuAction>
|
||||||
|
|
||||||
<ContextMenuAction
|
<ContextMenuAction
|
||||||
caption="My Collections"
|
caption={t('navbar.library.collections')}
|
||||||
action={() => console.log("My Collections")}
|
action={() => console.log("My Collections")}
|
||||||
icon={<SVGFolder className="stroke-black fill-black" />}
|
icon={<SVGFolder className="stroke-black fill-black" />}
|
||||||
></ContextMenuAction>
|
></ContextMenuAction>
|
||||||
|
|
||||||
<ContextMenuAction
|
<ContextMenuAction
|
||||||
caption="Recent Viewed"
|
caption={t('navbar.library.recentViewed')}
|
||||||
action={() => console.log("Recent Viewed")}
|
action={() => console.log("Recent Viewed")}
|
||||||
icon={<SVGEye className="stroke-black " />}
|
icon={<SVGEye className="stroke-black " />}
|
||||||
></ContextMenuAction>
|
></ContextMenuAction>
|
||||||
@ -105,21 +108,21 @@ const Header = () => {
|
|||||||
{/* Dropdown Menu About - start - */}
|
{/* Dropdown Menu About - start - */}
|
||||||
<ContextMenu
|
<ContextMenu
|
||||||
emphasis="high"
|
emphasis="high"
|
||||||
button="About"
|
button={t('navbar.about.navTitle')}
|
||||||
className="border-none uppercase"
|
className="border-none uppercase"
|
||||||
>
|
>
|
||||||
<ContextMenuAction
|
<ContextMenuAction
|
||||||
caption="About Freeland"
|
caption={t('navbar.about.aboutProject')}
|
||||||
action={() => console.log("About Freeland")}
|
action={() => console.log("About Freeland")}
|
||||||
></ContextMenuAction>
|
></ContextMenuAction>
|
||||||
|
|
||||||
<ContextMenuAction
|
<ContextMenuAction
|
||||||
caption="Contact Us"
|
caption={t('navbar.about.contacts')}
|
||||||
action={() => console.log("Contact Us")}
|
action={() => console.log("Contact Us")}
|
||||||
></ContextMenuAction>
|
></ContextMenuAction>
|
||||||
|
|
||||||
<ContextMenuAction
|
<ContextMenuAction
|
||||||
caption="Help"
|
caption={t('navbar.about.help')}
|
||||||
action={() => console.log("Help")}
|
action={() => console.log("Help")}
|
||||||
></ContextMenuAction>
|
></ContextMenuAction>
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
@ -132,38 +135,38 @@ const Header = () => {
|
|||||||
<div className="flex items-center font-bold text-sm gap-1 md:gap-2 ">
|
<div className="flex items-center font-bold text-sm gap-1 md:gap-2 ">
|
||||||
{!authenticated
|
{!authenticated
|
||||||
? [
|
? [
|
||||||
<Button
|
<Button
|
||||||
emphasis="low"
|
emphasis="low"
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
className="text-xs sm:px-4 sm:text-sm "
|
className="text-xs sm:px-4 sm:text-sm "
|
||||||
>
|
>
|
||||||
Sign in
|
{t('navbar.auth.signIn')}
|
||||||
</Button>,
|
</Button>,
|
||||||
<Button
|
<Button
|
||||||
emphasis="medium"
|
emphasis="medium"
|
||||||
className="hidden md:flex"
|
className="hidden md:flex"
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
>
|
>
|
||||||
Sign up
|
{t('navbar.auth.signUp')}
|
||||||
</Button>,
|
</Button>,
|
||||||
]
|
]
|
||||||
: [
|
: [
|
||||||
<Button emphasis="low">
|
<Button emphasis="low">
|
||||||
<Button.Icon>
|
<Button.Icon>
|
||||||
{!notification ? (
|
{!notification ? (
|
||||||
<SVGBell className="h-6 w-6 fill-gray-900 stroke-gray-900" />
|
<SVGBell className="h-6 w-6 fill-gray-900 stroke-gray-900" />
|
||||||
) : (
|
) : (
|
||||||
<SVGBellNotification className="h-6 w-6 fill-gray-900 stroke-gray-900" />
|
<SVGBellNotification className="h-6 w-6 fill-gray-900 stroke-gray-900" />
|
||||||
)}
|
)}
|
||||||
</Button.Icon>
|
</Button.Icon>
|
||||||
</Button>,
|
</Button>,
|
||||||
|
|
||||||
<Button emphasis="low" className="hidden lg:flex">
|
<Button emphasis="low" className="hidden lg:flex">
|
||||||
<Button.Icon>
|
<Button.Icon>
|
||||||
<Avatar className="bg-[rgb(255,122,69)] text-white">K</Avatar>
|
<Avatar className="bg-[rgb(255,122,69)] text-white">K</Avatar>
|
||||||
</Button.Icon>
|
</Button.Icon>
|
||||||
</Button>,
|
</Button>,
|
||||||
]}
|
]}
|
||||||
{/* Burger component will be shown for the small screens */}
|
{/* Burger component will be shown for the small screens */}
|
||||||
<Navbar className="block lg:hidden" />
|
<Navbar className="block lg:hidden" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,6 +4,7 @@ import SearchInput from "./SearchInput";
|
|||||||
import { Button } from "components/Button/Button";
|
import { Button } from "components/Button/Button";
|
||||||
import { SVGSearch } from "components/icons";
|
import { SVGSearch } from "components/icons";
|
||||||
import Link from "components/typography/Link";
|
import Link from "components/typography/Link";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -15,6 +16,8 @@ type Props = {
|
|||||||
|
|
||||||
export function SearchBar({ className }: Props) {
|
export function SearchBar({ className }: Props) {
|
||||||
const [onSelected, setOnSelected] = useState(""); // Selected item from response list
|
const [onSelected, setOnSelected] = useState(""); // Selected item from response list
|
||||||
|
const { t, i18n } = useTranslation();
|
||||||
|
|
||||||
|
|
||||||
const searchResolver = (item: any) => {
|
const searchResolver = (item: any) => {
|
||||||
setOnSelected(item.caption);
|
setOnSelected(item.caption);
|
||||||
@ -31,6 +34,7 @@ export function SearchBar({ className }: Props) {
|
|||||||
onSelected={searchResolver}
|
onSelected={searchResolver}
|
||||||
className="w-full"
|
className="w-full"
|
||||||
inGroup={true}
|
inGroup={true}
|
||||||
|
placeHolder={t("mainPage.search") + "..."}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -11,3 +11,7 @@ export const handleScrollTo = (e: React.MouseEvent<HTMLAnchorElement>) => {
|
|||||||
export function capitalization (str: string) {
|
export function capitalization (str: string) {
|
||||||
return str.substring(0,1).toUpperCase() + str.substring(1);
|
return str.substring(0,1).toUpperCase() + str.substring(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function formatNumber(num: number) {
|
||||||
|
return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1 ');
|
||||||
|
}
|
@ -16,6 +16,7 @@ import AccountSettings from "pages/Information/AccountSettings";
|
|||||||
import { store } from "store/store";
|
import { store } from "store/store";
|
||||||
import { Provider } from "react-redux";
|
import { Provider } from "react-redux";
|
||||||
import { SearchResultsPage } from "pages/SearchResultsPage";
|
import { SearchResultsPage } from "pages/SearchResultsPage";
|
||||||
|
import AnArticle from "components/fetchAnArticle/AnArticle";
|
||||||
|
|
||||||
const rootElement = document.getElementById("root");
|
const rootElement = document.getElementById("root");
|
||||||
if (!rootElement) throw new Error("Failed to find the root element");
|
if (!rootElement) throw new Error("Failed to find the root element");
|
||||||
@ -32,6 +33,7 @@ root.render(
|
|||||||
<Route path="/terms-of-use" element={<TermsOfUse />} />
|
<Route path="/terms-of-use" element={<TermsOfUse />} />
|
||||||
<Route path="/privacy-policy" element={<PrivacyPolicy />} />
|
<Route path="/privacy-policy" element={<PrivacyPolicy />} />
|
||||||
<Route path="/cookies-policy" element={<CookiesPolicy />} />
|
<Route path="/cookies-policy" element={<CookiesPolicy />} />
|
||||||
|
<Route path="/article/:id" element={<AnArticle />} />
|
||||||
<Route path="/account">
|
<Route path="/account">
|
||||||
<Route path="settings" element={<AccountSettings />} />
|
<Route path="settings" element={<AccountSettings />} />
|
||||||
</Route>
|
</Route>
|
||||||
|
@ -18,11 +18,11 @@ export const languages: Record<Langs, Lang> = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
export const popularLangKeys = ["ru", "en"];
|
export const popularLangKeys = ["ru", "en"];
|
||||||
const fallbackLng: Langs = "en";
|
const fallbackLng: Langs = "ru";
|
||||||
|
|
||||||
i18n
|
i18n
|
||||||
.use(Backend)
|
.use(Backend)
|
||||||
.use(LanguageDetector)
|
// .use(LanguageDetector)
|
||||||
.use(initReactI18next)
|
.use(initReactI18next)
|
||||||
.init({
|
.init({
|
||||||
debug: process.env.NODE_ENV === "development" ? true : false,
|
debug: process.env.NODE_ENV === "development" ? true : false,
|
||||||
|
@ -20,7 +20,6 @@ export default function MainPage({ className }: Props) {
|
|||||||
<FeaturedArticlesCategories></FeaturedArticlesCategories>
|
<FeaturedArticlesCategories></FeaturedArticlesCategories>
|
||||||
<FeaturedArticlesCards></FeaturedArticlesCards>
|
<FeaturedArticlesCards></FeaturedArticlesCards>
|
||||||
<FeaturedAuthorsCards></FeaturedAuthorsCards>
|
<FeaturedAuthorsCards></FeaturedAuthorsCards>
|
||||||
<BottomBarAcceptCookies></BottomBarAcceptCookies>
|
|
||||||
</BaseLayout>
|
</BaseLayout>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -19,7 +19,7 @@ export const SearchResultsPage = () => {
|
|||||||
<SearchResultSection />
|
<SearchResultSection />
|
||||||
</ColumnLayout.Main>
|
</ColumnLayout.Main>
|
||||||
<ColumnLayout.Right>
|
<ColumnLayout.Right>
|
||||||
<div className="h-98 bg-blue-200 w-[300px]">right bar</div>
|
<div className="w-[300px]"></div>
|
||||||
</ColumnLayout.Right>
|
</ColumnLayout.Right>
|
||||||
</ColumnLayout>
|
</ColumnLayout>
|
||||||
</BaseLayout>
|
</BaseLayout>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user