From 3c739247d228005d7b2fab8202630c791a780ec3 Mon Sep 17 00:00:00 2001 From: filantrop <filantrop83@gmail.com> Date: Mon, 17 Oct 2022 12:17:14 +0300 Subject: [PATCH 1/8] added filter (beta version) --- src/components/Badge.tsx | 20 +++- src/components/Checkbox.tsx | 12 +- src/components/Disclosure.tsx | 55 +++++++++ src/components/Filters/AppiledFilters.tsx | 64 ++++++++++ src/components/Filters/Filter.tsx | 109 +++++++++++++++++ src/components/Filters/IProdutct.ts | 23 ++++ src/components/Filters/SearchFilterBar.tsx | 117 +++++++++++++++++++ src/components/Filters/functions/debounce.ts | 11 ++ src/components/Filters/svg/chest.svg | 4 + src/components/Filters/svg/searchIcon.svg | 3 + src/pages/SearchResultsPage.tsx | 3 +- 11 files changed, 408 insertions(+), 13 deletions(-) create mode 100644 src/components/Disclosure.tsx create mode 100644 src/components/Filters/AppiledFilters.tsx create mode 100644 src/components/Filters/Filter.tsx create mode 100644 src/components/Filters/IProdutct.ts create mode 100644 src/components/Filters/SearchFilterBar.tsx create mode 100644 src/components/Filters/functions/debounce.ts create mode 100644 src/components/Filters/svg/chest.svg create mode 100644 src/components/Filters/svg/searchIcon.svg diff --git a/src/components/Badge.tsx b/src/components/Badge.tsx index 34974eb..75afd11 100755 --- a/src/components/Badge.tsx +++ b/src/components/Badge.tsx @@ -5,6 +5,7 @@ import classNames from "classnames"; import { StyleType } from "core/_variants"; import React from "react"; +import {ReactComponent as DeleteIcon} from "./Filters/svg/chest.svg" /* -------------------------------------------------------------------------- */ /* Component props */ @@ -15,7 +16,8 @@ type Props = { children: React.ReactNode; className?: string; iconed?: boolean; - onClick?: () => void; + onClick?: (element: any) => void; + closeOption?: Boolean; } & Omit<React.MouseEventHandler<HTMLSpanElement>, "">; /* -------------------------------------------------------------------------- */ @@ -27,17 +29,18 @@ function Badge({ children, onClick, emphasis = "low", + closeOption = false, ...props }: Props): JSX.Element { return ( + <> <span - onClick={onClick} className={classNames( - "border p-2 rounded-sm text-xs text-center", + "border-none p-2 rounded-md text-xs text-center", { "cursor-pointer": onClick, "border-transparent": emphasis == "low", - "bg-blue-400 text-white": emphasis == "high", + "bg-blue-400 text-white rounded-xs": emphasis == "high", "border-gray-400 background-gray-200": emphasis == "medium", }, className @@ -45,7 +48,16 @@ function Badge({ {...props} > {children} + {closeOption && ( + <button + onClick={onClick} + className=" text-white pr-1 pl-3 py-1" + > + <div><DeleteIcon className="h-[9px] w-[9px]" /></div> + </button> + )} </span> + </> ); } export default Badge; diff --git a/src/components/Checkbox.tsx b/src/components/Checkbox.tsx index d13b86b..913ceb0 100755 --- a/src/components/Checkbox.tsx +++ b/src/components/Checkbox.tsx @@ -1,12 +1,12 @@ import React from "react"; import classNames from "classnames"; -import { ReactComponent as Checkmark } from "assets/svg/check.svg"; +import { ReactComponent as Checkmark } from "../assets/svg/arrow-down.svg"; export type Props = { /** * Control the state of checkbox */ - isChecked: boolean; + isChecked?: boolean; /** * An Element next to the checkbox */ @@ -33,12 +33,8 @@ const Checkbox = ({ children, className, isChecked, ...props }: Props) => { checked={isChecked} {...props} /> - <div // - className=" w-4 h-3 leading-[0] absolute top-1.5 left-1 opacity-0 - pointer-events-none focus:pointer-events-auto flex items-center justify-center - fill-white peer-disabled:fill-gray-500 " - > - <Checkmark className="fill-inherit" /> + <div className="h-2 w-2 absolute top-0 left-0"> + <Checkmark className="h-6 w-6 fill-white hover:fill-white stroke-white" /> </div> </div> {children} diff --git a/src/components/Disclosure.tsx b/src/components/Disclosure.tsx new file mode 100644 index 0000000..e17f290 --- /dev/null +++ b/src/components/Disclosure.tsx @@ -0,0 +1,55 @@ +/* -------------------------------------------------------------------------- */ +/* Imports */ +/* -------------------------------------------------------------------------- */ +import React from "react"; +import { Disclosure as Disclose } from "@headlessui/react"; +import { ReactComponent as SelectIcon } from "../assets/svg/arrow-down.svg"; +import classNames from "classnames"; +/* -------------------------------------------------------------------------- */ +/* Component props */ +/* -------------------------------------------------------------------------- */ +type Props = { + children?: React.ReactNode; + className?: string; + caption?: string; +}; +/* -------------------------------------------------------------------------- */ +/* styles */ +/* -------------------------------------------------------------------------- */ +const ButtonStyle = ` +flex w-full +justify-between +items-center +py-2 text-left +text-base +font-medium +text-black-400 +`; +/* -------------------------------------------------------------------------- */ +/* Component implementation */ +/* -------------------------------------------------------------------------- */ +export default function Disclosure({ children, className, caption }: Props) { + return ( + <div className={classNames("top-16 ", className)}> + <div className="mx-auto w-full bg-white py-2"> + <Disclose as="div"> + {({ open }) => ( + <> + <Disclose.Button className={`${ButtonStyle}`}> + <span>{caption}</span> + <SelectIcon + className={`${ + open ? "rotate-180 transform" : "" + } h-4 w-5 fill-black hover:fill-black stroke-black`} + /> + </Disclose.Button> + <Disclose.Panel className="py-2 text-sm text-gray-500 "> + {children} + </Disclose.Panel> + </> + )} + </Disclose> + </div> + </div> + ); +} diff --git a/src/components/Filters/AppiledFilters.tsx b/src/components/Filters/AppiledFilters.tsx new file mode 100644 index 0000000..570382f --- /dev/null +++ b/src/components/Filters/AppiledFilters.tsx @@ -0,0 +1,64 @@ +/* -------------------------------------------------------------------------- */ +/* Imports */ +/* -------------------------------------------------------------------------- */ +import React from "react"; +import Badge from "components/Badge"; +import { IProduct } from "./IProdutct"; +import classNames from "classnames"; +/* -------------------------------------------------------------------------- */ +/* Component props */ +/* -------------------------------------------------------------------------- */ +type Props = { + hints?: IProduct[]; + delFilter: (element: IProduct) => void; + clearAll: () => void; + className?: string; +}; +/* -------------------------------------------------------------------------- */ +/* Component implementation */ +/* -------------------------------------------------------------------------- */ +export default function AppiledFilters({ + hints, + delFilter, + clearAll, + className, +}: Props) { + return ( + <> + <div + className={classNames( + "w-full py-3 h-36 max-h-36 overflow-hidden ", + className + )} + > + <div className="flex flex-row items-center justify-between space-x-3 "> + <div className="font-medium">Фильтры</div> + <div> + <button + onClick={clearAll} + className="font-normal text-sm text-gray-400" + > + Очистить всё + </button> + </div> + </div> + <ul className="list-none mt-2 h-24 max-h-32 overflow-auto"> + {hints && + hints.length > 0 && + hints.map((item: IProduct) => ( + <li className="mt-1" key={item.id}> + <Badge + className="py-1 cursor-default" + emphasis="high" + closeOption={true} + onClick={() => delFilter(item)} + > + {item.brand} + </Badge> + </li> + ))} + </ul> + </div> + </> + ); +} diff --git a/src/components/Filters/Filter.tsx b/src/components/Filters/Filter.tsx new file mode 100644 index 0000000..384b37d --- /dev/null +++ b/src/components/Filters/Filter.tsx @@ -0,0 +1,109 @@ +import React from "react"; +import Disclosure from "components/Disclosure"; +import AppiledFilters from "./AppiledFilters"; +import SearchFilterBar from "./SearchFilterBar"; +import axios from "axios"; +import { useDebounce } from "./functions/debounce"; +import { IProduct } from "./IProdutct"; + +type Props = { + className?: string; +}; + +export default function Fiter({ className }: Props) { + const [checkedId, setCheckedId] = React.useState<Array<number>>([]); + const [activeFilter, setActiveFilter] = React.useState<Array<IProduct>>([]); + + /* -------------------------------------------------------------------------- */ + /* Test request to demonstrate the basic functionality of the filter */ + /* -------------------------------------------------------------------------- */ + + const [query, setQuery] = React.useState(""); + const [hints, setHints] = React.useState<Array<IProduct>>([]); + + const onChange = (e: React.ChangeEvent<HTMLInputElement>) => { + setQuery(e.target.value); + }; + const debounced = useDebounce(query); + + async function fetchProducts() { + const response = await axios.get( + `https://dummyjson.com/products/search?q=${debounced}` + ); + setHints(response.data.products); + } + React.useEffect(() => { + fetchProducts(); + }, [debounced, query]); + + const isChecked = (item: number) => (checkedId.includes(item) ? true : false); + + const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { + const selectedId = parseInt(e.target.value); + + /* ------------- Check if "checkedId" contains "selectedIds" ------------- */ + /* -------------- If true, this checkbox is already checked -------------- */ + + if (checkedId.includes(selectedId)) { + setCheckedId(checkedId.filter((id) => id !== selectedId)); + setActiveFilter(activeFilter.filter((item) => item.id !== selectedId)); + } else { + const newId = [...checkedId]; + newId.push(selectedId); + setCheckedId(newId); + + /* --------------- Adding checked filters to AppliedFilters component -------------- */ + + hints.forEach((hint) => { + if (hint.id === selectedId) + activeFilter.push({ id: selectedId, brand: hint.brand }); + setActiveFilter(activeFilter); + }); + } + }; + + /* ------------- Delete filter from AppliedFilters component ------------- */ + + const DelFilter = (e: IProduct) => { + setActiveFilter(activeFilter.filter((item) => item.id !== e.id)); + setCheckedId(checkedId.filter((id) => id !== e.id)); + }; + const clearAll = () => { + setActiveFilter([]); + setCheckedId([]); + setQuery(""); + }; + //console.log(activeFilter) + return ( + <> + <div className="pl-2"> + <div className="max-w-[268px] mx-auto divide-y divide-solid"> + <AppiledFilters + hints={activeFilter} + delFilter={DelFilter} + clearAll={clearAll} + ></AppiledFilters> + <Disclosure caption="Авторы"> + <SearchFilterBar + hints={hints} + isChecked={isChecked} + handleChange={handleChange} + onChange={onChange} + query={query} + placeHolder={"Введите имя автора"} + /> + </Disclosure> + <Disclosure caption="Публикации"> + <p>контент...</p> + </Disclosure> + <Disclosure caption="Тип издания"> + <p>контент...</p> + </Disclosure> + <Disclosure caption="Тематика публикаций"> + <p>контент...</p> + </Disclosure> + </div> + </div> + </> + ); +} diff --git a/src/components/Filters/IProdutct.ts b/src/components/Filters/IProdutct.ts new file mode 100644 index 0000000..9101267 --- /dev/null +++ b/src/components/Filters/IProdutct.ts @@ -0,0 +1,23 @@ + export interface IProduct { + id?: number; + title?: string; + description?: string; + price?: number; + discountPercentage?: number; + rating?: number; + stock?: number; + brand?: string; + category?: string; + thumbnail?: string; + images?: string[]; + } + + export interface serverResponse<T> { + products: T[]; + total: number; + skip: number; + limit: number; + } + + + diff --git a/src/components/Filters/SearchFilterBar.tsx b/src/components/Filters/SearchFilterBar.tsx new file mode 100644 index 0000000..f9e6362 --- /dev/null +++ b/src/components/Filters/SearchFilterBar.tsx @@ -0,0 +1,117 @@ +import { useState, useCallback, Fragment } from "react"; +import { Combobox, Transition } from "@headlessui/react"; +import { IProduct } from "./IProdutct"; +import Checkbox from "components/Checkbox"; +import { ReactComponent as SearchIcon } from "./svg/searchIcon.svg"; +import classNames from "classnames"; + +type Props = { + hints: IProduct[]; + handleChange: (e: React.ChangeEvent<HTMLInputElement>) => void; + isChecked: (item: number) => boolean; + className?: string; + onChange: (e: React.ChangeEvent<HTMLInputElement>) => void; + placeHolder: string; + query: string; +}; + +export default function SearchFilterBar({ + hints, + isChecked, + handleChange, + className, + onChange, + placeHolder, + query, +}: Props): JSX.Element { + const [checkList, setCheckList] = useState(hints); + const [showFilters, SetShowFilters] = useState(false); + + const ShowAllFilters = useCallback(() => { + SetShowFilters((prev) => !prev); + }, [SetShowFilters]); + + return ( + <> + <Combobox value={checkList} onChange={setCheckList}> + {({ open }) => ( + <div> + <div + className={classNames( + "flex flex-row w-full items-center border border-solid rounded border-gray-200", + className + )} + > + <div className="basis-6 "> + <Combobox.Button> + <div className="pl-1 pt-1"> + <SearchIcon /> + </div> + </Combobox.Button> + </div> + <div className="grow"> + <Combobox.Input + onChange={onChange} + placeholder={placeHolder} + className="w-full text-sm py-1 focus:outline-none" + /> + </div> + </div> + <div className="mt-4"> + <Transition + as={Fragment} + leave="transition ease-in duration-100" + leaveFrom="opacity-100" + leaveTo="opacity-0" + > + <Combobox.Options static={true}> + {open && ( + <ul + className={classNames([ + "w-[276px] relative h-40 top-0 right-2", + [ + { + "max-h-60 h-60 overflow-auto": showFilters === true, + "max-h-40 h-40 overflow-hidden": + showFilters === false, + }, + ], + ])} + > + <li className=""> + {hints.length >= 5 && query !== "" && ( + <button + onClick={ShowAllFilters} + className="text-right text-blue-500 pl-2 text-sm font-medium" + > + Показать всё({hints.length}) + </button> + )} + </li> + {hints.length > 0 ? ( + hints.map((item) => ( + <li key={item.id} className="mt-1 pl-2"> + <Checkbox + className="z-10 mt-1 w-full max-h-56" + value={item.id} + isChecked={item.id ? isChecked(item.id) : false} + onChange={handleChange} + > + <p>{item.brand}</p> + </Checkbox> + </li> + )) + ) : ( + <p className="text-blue-300 pl-2">Nothing Found</p> + )} + </ul> + )} + </Combobox.Options> + </Transition> + </div> + </div> + )} + </Combobox> + </> + ); +} diff --git a/src/components/Filters/functions/debounce.ts b/src/components/Filters/functions/debounce.ts new file mode 100644 index 0000000..7d7bc78 --- /dev/null +++ b/src/components/Filters/functions/debounce.ts @@ -0,0 +1,11 @@ +import React from "react"; + +export function useDebounce(value: string, delay: number = 300) { + const [debounced, setDebouced] = React.useState(value); + React.useEffect(() => { + const handler = setTimeout(() => setDebouced(value), delay); + return () => clearTimeout(handler); + }, [value, delay]); + + return debounced; +} diff --git a/src/components/Filters/svg/chest.svg b/src/components/Filters/svg/chest.svg new file mode 100644 index 0000000..3b1d9ff --- /dev/null +++ b/src/components/Filters/svg/chest.svg @@ -0,0 +1,4 @@ +<svg width="12" height="13" viewBox="0 0 12 13" fill="white" xmlns="http://www.w3.org/2000/svg"> +<path d="M10.9497 11.4498L1.05026 1.55027" stroke="white" stroke-width="2" stroke-linecap="round"/> +<path d="M10.9497 1.55029L1.05025 11.4498" stroke="white" stroke-width="2" stroke-linecap="round"/> +</svg> diff --git a/src/components/Filters/svg/searchIcon.svg b/src/components/Filters/svg/searchIcon.svg new file mode 100644 index 0000000..dba33fe --- /dev/null +++ b/src/components/Filters/svg/searchIcon.svg @@ -0,0 +1,3 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M15.1003 14.1184L10.4628 9.48086C11.1824 8.55051 11.5717 7.41301 11.5717 6.21658C11.5717 4.78444 11.0128 3.44158 10.0021 2.42908C8.99135 1.41658 7.64492 0.859436 6.21456 0.859436C4.78421 0.859436 3.43778 1.41836 2.42706 2.42908C1.41456 3.43979 0.857422 4.78444 0.857422 6.21658C0.857422 7.64694 1.41635 8.99336 2.42706 10.0041C3.43778 11.0166 4.78242 11.5737 6.21456 11.5737C7.41099 11.5737 8.54671 11.1844 9.47707 10.4666L14.1146 15.1023C14.1282 15.1159 14.1443 15.1267 14.1621 15.1341C14.1799 15.1414 14.1989 15.1452 14.2181 15.1452C14.2374 15.1452 14.2564 15.1414 14.2742 15.1341C14.292 15.1267 14.3081 15.1159 14.3217 15.1023L15.1003 14.3255C15.1139 14.3119 15.1247 14.2958 15.132 14.278C15.1394 14.2602 15.1432 14.2412 15.1432 14.2219C15.1432 14.2027 15.1394 14.1837 15.132 14.1659C15.1247 14.1481 15.1139 14.132 15.1003 14.1184ZM9.04314 9.04515C8.28599 9.80051 7.28242 10.2166 6.21456 10.2166C5.14671 10.2166 4.14314 9.80051 3.38599 9.04515C2.63064 8.28801 2.21456 7.28444 2.21456 6.21658C2.21456 5.14872 2.63064 4.14336 3.38599 3.38801C4.14314 2.63265 5.14671 2.21658 6.21456 2.21658C7.28242 2.21658 8.28778 2.63086 9.04314 3.38801C9.79849 4.14515 10.2146 5.14872 10.2146 6.21658C10.2146 7.28444 9.79849 8.28979 9.04314 9.04515Z" fill="#8C8C8C"/> +</svg> diff --git a/src/pages/SearchResultsPage.tsx b/src/pages/SearchResultsPage.tsx index ca4e486..94217a7 100644 --- a/src/pages/SearchResultsPage.tsx +++ b/src/pages/SearchResultsPage.tsx @@ -6,6 +6,7 @@ import { SearchResultSection } from "components/SearchResultsSection"; import { useSearchStoreImplementation } from "searchResults/data/searchStoreImplementation"; import { useSearchViewModel } from "searchResults/controller/searchResultsViewModel"; import { Loader } from "components/Loader/Loader"; +import Fiter from "components/Filters/Filter"; export const SearchResultsPage = () => { return ( @@ -13,7 +14,7 @@ export const SearchResultsPage = () => { <SearchSection /> <ColumnLayout> <ColumnLayout.Left> - <div className="h-98 bg-blue-200 w-[300px]">left bar</div> + <div className="w-[300px] border rounded my-5"><Fiter/></div> </ColumnLayout.Left> <ColumnLayout.Main> <SearchResultSection /> From b390ae7a2ec56c30f97f27d8a84fe85bcda8bf27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CSalar?= <“salar.sali97@gmail.com”> Date: Mon, 17 Oct 2022 12:26:23 +0300 Subject: [PATCH 2/8] resolve not found page --- src/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/index.tsx b/src/index.tsx index 7e200b3..9f61062 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -42,7 +42,8 @@ root.render( <Route path="/account"> <Route path="settings" element={<AccountSettings />} /> </Route> - <Route path="/search-results" element={<SearchResultsPage />}></Route> + <Route path="/search-results" element={<SearchResultsPage />} /> + <Route path="/*" element={<NotFound />}></Route> </Routes> </BrowserRouter> </React.StrictMode> From 9154b1fb96f6a181ec308f42de9da4331647dee0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CSalar?= <“salar.sali97@gmail.com”> Date: Mon, 17 Oct 2022 12:41:10 +0300 Subject: [PATCH 3/8] resolve padding of featured authors --- src/components/MainPage/sections/FeaturedAuthorsCards.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/MainPage/sections/FeaturedAuthorsCards.tsx b/src/components/MainPage/sections/FeaturedAuthorsCards.tsx index 965a243..87fff9c 100755 --- a/src/components/MainPage/sections/FeaturedAuthorsCards.tsx +++ b/src/components/MainPage/sections/FeaturedAuthorsCards.tsx @@ -75,10 +75,12 @@ export default function FeaturedAuthorsCards(): JSX.Element { return ( <div> {/* The Title of Featured Authors section */} - <Heading className="text-center my-8 text-3xl font-semibold">{t("mainPage.featuredAuthors")}</Heading> + <Heading className="text-center my-8 text-3xl font-semibold"> + {t("mainPage.featuredAuthors")} + </Heading> {/* Featured Authors section */} - <div className="slider-wrapper Authors"> + <div className="slider-wrapper Authors px-8"> <Swiper slidesPerView={1.25} slidesPerGroup={1} @@ -133,7 +135,7 @@ export default function FeaturedAuthorsCards(): JSX.Element { <Card.CardAction href={card.Link}> <Link className="text-blue-500 font-bold" to="*"> - {t('mainPage.more')} + {t("mainPage.more")} </Link> <SVGCaretRight className="fill-blue-500 w-4 h-4" /> </Card.CardAction> From 3cac7c7d045bf6749875468f5c66e71c8eb934ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CSalar?= <“salar.sali97@gmail.com”> Date: Mon, 17 Oct 2022 12:49:21 +0300 Subject: [PATCH 4/8] the padding of featured articles cards has been resolved --- src/components/MainPage/sections/FeaturedArticlesCards.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/MainPage/sections/FeaturedArticlesCards.tsx b/src/components/MainPage/sections/FeaturedArticlesCards.tsx index bfb2a07..78f10f9 100755 --- a/src/components/MainPage/sections/FeaturedArticlesCards.tsx +++ b/src/components/MainPage/sections/FeaturedArticlesCards.tsx @@ -98,10 +98,10 @@ const FeaturedArticlesCards = () => { const navigationPrevRef = useRef(null); const navigationNextRef = useRef(null); const paginationRef = useRef(null); - const [t, i18next] = useTranslation() + const [t, i18next] = useTranslation(); return ( - <div className="slider-wrapper articles"> + <div className="slider-wrapper articles px-8"> <div className="flex justify-end gap-2 my-2"> <div className="prev inline-flex justify-center items-center From 64a6e6ab20e2781f42dedfdcb7c1d2ea4c82a730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CSalar?= <“salar.sali97@gmail.com”> Date: Mon, 17 Oct 2022 13:08:24 +0300 Subject: [PATCH 5/8] resolve the margin of topic in the article info and article content pages --- src/components/fetchAnArticle/AnArticle.tsx | 17 +++++------------ src/components/fetchAnArticle/AnArticleBody.tsx | 4 ++-- .../fetchAnArticle/AskeletonArticle.tsx | 2 +- 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/components/fetchAnArticle/AnArticle.tsx b/src/components/fetchAnArticle/AnArticle.tsx index 11c8d26..73a8f91 100644 --- a/src/components/fetchAnArticle/AnArticle.tsx +++ b/src/components/fetchAnArticle/AnArticle.tsx @@ -33,7 +33,7 @@ const AnArticle = () => { <AskeletonArticle /> ) : ( <> - <ArticlePart.Article.Breadcumbs> + <ArticlePart.Article.Breadcumbs className="py-4"> {article?.topic} </ArticlePart.Article.Breadcumbs> <div className="flex flex-col gap-4 pb-4"> @@ -52,25 +52,18 @@ const AnArticle = () => { /> {article?.tags && ( <div className="keywords my-10 flex flex-col gap-2"> - <Typography - className="text-2xl" - fontWeightVariant="semibold" - > - {t('articlePage.keywords')} + <Typography className="text-2xl" fontWeightVariant="semibold"> + {t("articlePage.keywords")} </Typography> - <ArticlePart.Article.Keywords className="transition ease-in-out delay-50"> {article?.tags} </ArticlePart.Article.Keywords> </div> )} <div className="abstract my-10 flex flex-col gap-2"> - <Typography - className="text-2xl" - fontWeightVariant="semibold" - > - {t('articlePage.abstract')} + <Typography className="text-2xl" fontWeightVariant="semibold"> + {t("articlePage.abstract")} </Typography> <ArticlePart.Article.Description> {article?.summary !== undefined ? ( diff --git a/src/components/fetchAnArticle/AnArticleBody.tsx b/src/components/fetchAnArticle/AnArticleBody.tsx index 55d7f95..0329981 100644 --- a/src/components/fetchAnArticle/AnArticleBody.tsx +++ b/src/components/fetchAnArticle/AnArticleBody.tsx @@ -27,7 +27,7 @@ const AnArticleBody = () => { <Container variant="straight"> {shouldShowLoading ? ( <> - <Skeleton count={1} /> + <Skeleton count={1} className="my-4" /> <div className="gap-4 py-12 px-20"> <Skeleton count={1} @@ -39,7 +39,7 @@ const AnArticleBody = () => { </> ) : ( <> - <ArticlePart.Article.Breadcumbs> + <ArticlePart.Article.Breadcumbs className="py-4"> {article?.topic} </ArticlePart.Article.Breadcumbs> <div className="gap-4 py-12 px-20"> diff --git a/src/components/fetchAnArticle/AskeletonArticle.tsx b/src/components/fetchAnArticle/AskeletonArticle.tsx index f0b9702..d8bdcfc 100644 --- a/src/components/fetchAnArticle/AskeletonArticle.tsx +++ b/src/components/fetchAnArticle/AskeletonArticle.tsx @@ -3,7 +3,7 @@ import "react-loading-skeleton/dist/skeleton.css"; const AskeletonArticle = () => { return ( <> - <Skeleton count={1} /> + <Skeleton count={1} className="my-4" /> <div className="flex flex-col gap-4 pb-4"> <Skeleton count={1} containerClassName="title w-3/4 text-2xl" /> <Skeleton count={1} containerClassName="authors w-1/4" /> From 705ae6471f91463d006dd7a1f777adce2d53b4ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CSalar?= <“salar.sali97@gmail.com”> Date: Mon, 17 Oct 2022 14:15:13 +0300 Subject: [PATCH 6/8] English localization --- public/locales/en/translation.json | 103 +++++++++++++++++++++++------ 1 file changed, 84 insertions(+), 19 deletions(-) diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 133ea55..56f2981 100755 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -1,7 +1,7 @@ { "serv": { - "goHome": "Home", - "noSuchPath": "We don't have this page" + "goHome": "Home page", + "noSuchPath": "We don't have such a page" }, "sidemenu": { "dashboard": "Dashboard", @@ -19,45 +19,110 @@ "hellousr": "Hello, {{username}}", "edit": "Edit", "language": "Language", - "selectLanguage": "Select language", + "selectLanguage": "Select a language", "save": "Save", "cancel": "Cancel", "account": { - "info": "Personal information", + "info": "Personal Information", "mail": "Mail", - "connect": "Add account", - "connectedAccounts_one": "Connected account", - "connectedAccounts_other": "Connected accounts", - "settings": "Account settings" + "connect": "Add Account", + "connectedAccounts_one": "Linked Account", + "connectedAccounts_other": "Linked Accounts", + "settings": "Account Settings" }, "security": { "password": { "caption": "Password", - "twoFactor": "Two factor authentication (2FA)", - "description": "Keep your account secure by enabling 2FA via SMS or using a temporary one-time passcode (TOTP) from an authenticator app." + "twoFactor": "Two-factor authentication (2FA)", + "description": "Protect your account by enabling 2FA via SMS or using a temporary one-time password (OTP) from the authentication app." }, "activity": { "caption": "Device activity" } }, "search": { - "label": "Search for something.." + "label": "We will find something.." }, "subscriptions": { - "subscribed": "Service have been connected" + "subscribed": "The service is attached to the account" }, "viewHistory": "View history", - "logOutEverywhere": "log out from all devices", + "logOutEverywhere": "Log out from all devices", "back": "Back", - "logOut": "Log out", + "logOut": "Exit", "failures": { "subscriptions": { - "failure": "Failed to connect service", - "exists": "Service have already been connected", - "confirmation": "Invalid confirmation information provided" + "failure": "Failed to attach the service to your account", + "exists": "The service was already attached to your account earlier", + "confirmation": "Invalid password" }, "services": { - "fork": "Failed to authenticate in service" + "fork": "Failed to perform authorization in the service" } + }, + "articlePage": { + "abstract": "Abstract", + "keywords": "Keywords" + }, + "navbar": { + "createNew": "Create an article", + "about": { + "navTitle": "About the project", + "aboutProject": "About Scipaper", + "contacts": "Contacts", + "help": "Help" + }, + "library": { + "navTitle": "My library", + "publications": "Publications", + "favorites": "Favorites", + "collections": "Collections", + "recentViewed": "History" + }, + "auth": { + "signIn": "Sign In", + "signUp": "Sign Up" + } + }, + "footer": { + "accountSettings": "Account Settings", + "about": "About Scipaper", + "help": "Help", + "contactUs": "Contacts", + "allRightsReserved": "All rights reserved", + "termsOfUse": "Terms of Use", + "privacyPolicy": "Privacy Policy", + "coockiesPolicy": "coockies Usage Policy", + "supportedBy": "Created" + }, + "mainPage": { + "title": "Scientific Library with free access", + "search": "Search", + "article_one": "Articles", + "article_few": "Articles", + "article_many": "Articles", + "advancedSearch": "Advanced search", + "featuredArticles": { + "title": "Popular articles", + "descriptionPart1": "Choose the one you are interested in", + "descriptionPart2": "Scientific category", + "categories": { + "Medical": "Medical", + "TechnicsAndTechlonogies": "Technics and Technology", + "Fundamental": "Fundamental", + "Humanitarian": "Humanitarian", + "Agricultural": "Agricultural", + "Social": "Social" + } + }, + "featuredAuthors": "Popular authors", + "more": "More", + "showAll": "Show all" + }, + "searchResults": { + "title": "Search results", + "totalResults":"Total results", + "nothingFound": "Nothing found" } -} \ No newline at end of file + +} From 8a075e926e0729f2c32921d454980d55032bef46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CSalar?= <“salar.sali97@gmail.com”> Date: Mon, 17 Oct 2022 14:47:21 +0300 Subject: [PATCH 7/8] resolve the style of link --- src/components/typography/Link.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/typography/Link.tsx b/src/components/typography/Link.tsx index c01bb6b..8b55a57 100755 --- a/src/components/typography/Link.tsx +++ b/src/components/typography/Link.tsx @@ -51,6 +51,7 @@ export default function Link({ : style } aria-disabled={disabled} + className="flex items-center" {...props} > {children} From bee5499816a6987cb22560f9bd9c585b26ec8198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CSalar?= <“salar.sali97@gmail.com”> Date: Mon, 17 Oct 2022 15:27:28 +0300 Subject: [PATCH 8/8] bold style for the link resolved --- src/components/MainPage/sections/FeaturedArticlesCards.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/MainPage/sections/FeaturedArticlesCards.tsx b/src/components/MainPage/sections/FeaturedArticlesCards.tsx index 78f10f9..78f0289 100755 --- a/src/components/MainPage/sections/FeaturedArticlesCards.tsx +++ b/src/components/MainPage/sections/FeaturedArticlesCards.tsx @@ -169,7 +169,10 @@ const FeaturedArticlesCards = () => { <Card.CardAction href={Articale.Link}> <Link to="*"> - <Typography className="text-blue-500 font-bold"> + <Typography + className="text-blue-500 font-bold" + fontWeightVariant="bold" + > {t("mainPage.more")} </Typography> </Link>