calendar and pagination
This commit is contained in:
parent
fa54a83ca8
commit
0b6e6dabb2
|
|
@ -1,21 +1,19 @@
|
||||||
// Modules
|
// Modules
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from "uuid";
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from "react";
|
||||||
import { url } from '../../url';
|
import { url } from "../../url";
|
||||||
import { Api } from '../../api/Api';
|
import { Api } from "../../api/Api";
|
||||||
import { asideParams } from '../../api/params';
|
import { asideParams } from "../../api/params";
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import SectionTitle from '../global/SectionTitle';
|
import SectionTitle from "../global/SectionTitle";
|
||||||
import AsideNews from './AsideNews';
|
import AsideNews from "./AsideNews";
|
||||||
import Calendar from './Calendar';
|
import Calendar from "./Calendar";
|
||||||
import { IPostsData } from '../../types/data.types';
|
import { IPostsData } from "../../types/data.types";
|
||||||
import Loader from '../global/Loader';
|
import Loader from "../global/Loader";
|
||||||
|
|
||||||
import { dateParse } from '../../helpers/dateParser';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
type: 'latest' | 'popular';
|
type: "latest" | "popular";
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IData {
|
interface IData {
|
||||||
|
|
@ -23,7 +21,10 @@ interface IData {
|
||||||
}
|
}
|
||||||
|
|
||||||
const Aside = ({ type }: Props) => {
|
const Aside = ({ type }: Props) => {
|
||||||
const api = new Api(url + `${type === 'popular' ? '/popular' : ''}/posts`, asideParams);
|
const api = new Api(
|
||||||
|
url + `${type === "popular" ? "/popular" : ""}/posts`,
|
||||||
|
asideParams
|
||||||
|
);
|
||||||
const language = api.language;
|
const language = api.language;
|
||||||
|
|
||||||
const [data, setData] = useState<IData>();
|
const [data, setData] = useState<IData>();
|
||||||
|
|
@ -37,25 +38,25 @@ const Aside = ({ type }: Props) => {
|
||||||
<div className="aside-wrapper">
|
<div className="aside-wrapper">
|
||||||
<SectionTitle
|
<SectionTitle
|
||||||
title={
|
title={
|
||||||
type === 'latest'
|
type === "latest"
|
||||||
? `${
|
? `${
|
||||||
language === 'EN'
|
language === "EN"
|
||||||
? 'Latest news'
|
? "Latest news"
|
||||||
: language === 'RU'
|
: language === "RU"
|
||||||
? 'Последние новости'
|
? "Последние новости"
|
||||||
: 'Soňky habarlar'
|
: "Soňky habarlar"
|
||||||
}`
|
}`
|
||||||
: `${
|
: `${
|
||||||
language === 'EN'
|
language === "EN"
|
||||||
? 'Most read'
|
? "Most read"
|
||||||
: language === 'RU'
|
: language === "RU"
|
||||||
? 'Самое читаемое'
|
? "Самое читаемое"
|
||||||
: 'Köp okalýar'
|
: "Köp okalýar"
|
||||||
}`
|
}`
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<div className="aside-inner">
|
<div className="aside-inner">
|
||||||
{type === 'popular' ? (
|
{type === "popular" ? (
|
||||||
data ? (
|
data ? (
|
||||||
(data as any).data.map((el: any) => {
|
(data as any).data.map((el: any) => {
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
// Modules
|
// Modules
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from "react-router-dom";
|
||||||
import { LazyLoadImage } from 'react-lazy-load-image-component';
|
import { LazyLoadImage } from "react-lazy-load-image-component";
|
||||||
import ReactPlayer from 'react-player';
|
import ReactPlayer from "react-player";
|
||||||
import { dateParse } from '../../helpers/dateParser';
|
|
||||||
// Images
|
// Images
|
||||||
// import { ReactComponent as ArrRight } from "../../assets/icons/arrow-right.svg";
|
import placeholder from "../../assets/images/placeholder.webp";
|
||||||
import placeholder from '../../assets/images/placeholder.webp';
|
|
||||||
// Components
|
// Components
|
||||||
import NewsCategory from '../global/NewsCategory';
|
import NewsCategory from "../global/NewsCategory";
|
||||||
import NewsDate from '../global/NewsDate';
|
import NewsDate from "../global/NewsDate";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
title: string;
|
title: string;
|
||||||
|
|
@ -25,7 +25,13 @@ const AsideNews = ({ title, date, img, category, id, video }: Props) => {
|
||||||
<div className="aside-news-wrapper">
|
<div className="aside-news-wrapper">
|
||||||
<div className="aside-news-image">
|
<div className="aside-news-image">
|
||||||
{video && video.length > 53 ? (
|
{video && video.length > 53 ? (
|
||||||
<ReactPlayer url={video} controls light={img} width="100%" height="100%" />
|
<ReactPlayer
|
||||||
|
url={video}
|
||||||
|
controls
|
||||||
|
light={img}
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
<LazyLoadImage
|
<LazyLoadImage
|
||||||
src={img}
|
src={img}
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,17 @@
|
||||||
// Modules
|
// Modules
|
||||||
import { useState, useEffect, useCallback, useMemo } from "react";
|
import { useState, useCallback, useMemo } from "react";
|
||||||
import { Calendar as ReactCalendar } from "react-calendar";
|
import { Calendar as ReactCalendar } from "react-calendar";
|
||||||
import { LazyLoadComponent } from "react-lazy-load-image-component";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { v4 as uuiv4 } from "uuid";
|
|
||||||
|
|
||||||
//
|
//
|
||||||
import { Api } from "../../api/Api";
|
import { Api } from "../../api/Api";
|
||||||
import { url } from "../../url";
|
import { url } from "../../url";
|
||||||
import { IPostData } from "../../types/store.types";
|
|
||||||
import Loader from "../global/Loader";
|
|
||||||
import { Link } from "react-router-dom";
|
|
||||||
|
|
||||||
const Calendar = () => {
|
const Calendar = () => {
|
||||||
|
const navigate = useNavigate();
|
||||||
const [value, onChange] = useState(new Date());
|
const [value, onChange] = useState(new Date());
|
||||||
|
|
||||||
const [data, setData] = useState<any>();
|
|
||||||
|
|
||||||
const valueMemo = useMemo(() => ({ value, onChange }), [value, onChange]);
|
const valueMemo = useMemo(() => ({ value, onChange }), [value, onChange]);
|
||||||
const dataMemo = useMemo(() => ({ data, setData }), [data, setData]);
|
|
||||||
|
|
||||||
const constructDateParam = useCallback(() => {
|
const constructDateParam = useCallback(() => {
|
||||||
return `${value.getFullYear()}-${
|
return `${value.getFullYear()}-${
|
||||||
|
|
@ -34,34 +28,16 @@ const Calendar = () => {
|
||||||
const api = new Api(url + `/posts`, [
|
const api = new Api(url + `/posts`, [
|
||||||
{ name: "date", value: constructDateParam() },
|
{ name: "date", value: constructDateParam() },
|
||||||
]);
|
]);
|
||||||
useEffect(() => {
|
|
||||||
api.get(dataMemo.data, dataMemo.setData);
|
|
||||||
}, [value]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="calendar">
|
<div className="calendar">
|
||||||
<LazyLoadComponent useIntersectionObserver>
|
<ReactCalendar
|
||||||
<ReactCalendar value={value} onChange={valueMemo.onChange} />
|
value={valueMemo.value}
|
||||||
</LazyLoadComponent>
|
onChange={valueMemo.onChange}
|
||||||
<div className={"calendar-popup"}>
|
onClickDay={() =>
|
||||||
{data ? (
|
navigate(`/all?type=date&date=${constructDateParam()}`)
|
||||||
data[0] ? (
|
}
|
||||||
<Link
|
/>
|
||||||
to={`/news/${data[0].id}`}
|
|
||||||
className="calendar-popup-item"
|
|
||||||
key={uuiv4()}
|
|
||||||
>
|
|
||||||
<p>{data[0].title}</p>
|
|
||||||
</Link>
|
|
||||||
) : (
|
|
||||||
<div className="calendar-popup-item" key={uuiv4()}>
|
|
||||||
<p>Нет событий</p>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
) : (
|
|
||||||
<Loader />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ import Pagination from "./Pagination";
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import { INewPostsData } from "../../types/posts.types";
|
import { INewPostsData } from "../../types/posts.types";
|
||||||
import Loader from "./Loader";
|
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
data: INewPostsData;
|
data: INewPostsData;
|
||||||
|
|
@ -27,7 +26,6 @@ const CustomNewsScroll = ({
|
||||||
pageMemo,
|
pageMemo,
|
||||||
avoidFirst,
|
avoidFirst,
|
||||||
}: IProps) => {
|
}: IProps) => {
|
||||||
console.log(data);
|
|
||||||
return (
|
return (
|
||||||
<div className="news-scroll">
|
<div className="news-scroll">
|
||||||
<div className="news-scroll-wrapper">
|
<div className="news-scroll-wrapper">
|
||||||
|
|
@ -71,9 +69,11 @@ const CustomNewsScroll = ({
|
||||||
{pagination ? (
|
{pagination ? (
|
||||||
data ? (
|
data ? (
|
||||||
<Pagination
|
<Pagination
|
||||||
pages={data?.meta.total}
|
next={data?.links.next}
|
||||||
|
prev={data?.links.prev}
|
||||||
activePage={pageMemo.activePage}
|
activePage={pageMemo.activePage}
|
||||||
setActivePage={pageMemo.setActivePage}
|
setActivePage={pageMemo.setActivePage}
|
||||||
|
total={data?.meta.total}
|
||||||
/>
|
/>
|
||||||
) : null
|
) : null
|
||||||
) : null}
|
) : null}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,26 @@
|
||||||
// Icons
|
// Icons
|
||||||
import { Dispatch, SetStateAction } from 'react';
|
import { Dispatch, SetStateAction } from "react";
|
||||||
import { ReactComponent as Arr } from '../../assets/icons/pagintaion-arr.svg';
|
import { ReactComponent as Arr } from "../../assets/icons/pagintaion-arr.svg";
|
||||||
|
|
||||||
|
// Api
|
||||||
|
import { Api } from "../../api/Api";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
pages: number;
|
next: string | null;
|
||||||
|
prev: string | null;
|
||||||
activePage: number;
|
activePage: number;
|
||||||
setActivePage: Dispatch<SetStateAction<number>>;
|
setActivePage: Dispatch<SetStateAction<number>>;
|
||||||
|
total: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Pagination = ({ pages, activePage, setActivePage }: IProps) => {
|
const Pagination = ({
|
||||||
|
next,
|
||||||
|
prev,
|
||||||
|
activePage,
|
||||||
|
setActivePage,
|
||||||
|
total,
|
||||||
|
}: IProps) => {
|
||||||
|
const language = new Api("").language;
|
||||||
const handleOnClick = (page: number) => {
|
const handleOnClick = (page: number) => {
|
||||||
setActivePage(page);
|
setActivePage(page);
|
||||||
};
|
};
|
||||||
|
|
@ -16,8 +28,9 @@ const Pagination = ({ pages, activePage, setActivePage }: IProps) => {
|
||||||
<div className="pagination-wrapper">
|
<div className="pagination-wrapper">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
disabled={activePage - 1 < 1}
|
disabled={!prev ? true : false}
|
||||||
onClick={() => handleOnClick(activePage - 1)}>
|
onClick={() => handleOnClick(activePage - 1)}
|
||||||
|
>
|
||||||
<Arr className="pagination-arr pagination-arr-left" />
|
<Arr className="pagination-arr pagination-arr-left" />
|
||||||
</button>
|
</button>
|
||||||
<div className="pagination-nums">
|
<div className="pagination-nums">
|
||||||
|
|
@ -25,10 +38,15 @@ const Pagination = ({ pages, activePage, setActivePage }: IProps) => {
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
disabled={activePage + 1 >= pages}
|
disabled={!next ? true : false}
|
||||||
onClick={() => handleOnClick(activePage + 1)}>
|
onClick={() => handleOnClick(activePage + 1)}
|
||||||
|
>
|
||||||
<Arr className="pagination-arr pagination-arr-right" />
|
<Arr className="pagination-arr pagination-arr-right" />
|
||||||
</button>
|
</button>
|
||||||
|
<span className="pagination-total">
|
||||||
|
{Math.ceil(total / 10)}{" "}
|
||||||
|
{language === "EN" ? "pages" : language === "RU" ? "страниц" : "sahypa"}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
export const dateParse = (date: string) => {
|
export const dateParse = (date: string) => {
|
||||||
try {
|
try {
|
||||||
const splitArr = date.split(' ');
|
const dateYearSplit = date.split("-");
|
||||||
const dateYear = splitArr[0];
|
|
||||||
const dateYearSplit = dateYear.split('-');
|
|
||||||
const finalDate = `${dateYearSplit[2]}.${dateYearSplit[1]}.${dateYearSplit[0]}`;
|
const finalDate = `${dateYearSplit[2]}.${dateYearSplit[1]}.${dateYearSplit[0]}`;
|
||||||
return finalDate;
|
return finalDate;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import Loader from "../components/global/Loader";
|
||||||
import { IurlParamAdder } from "../types/api.types";
|
import { IurlParamAdder } from "../types/api.types";
|
||||||
import SectionTitle from "../components/global/SectionTitle";
|
import SectionTitle from "../components/global/SectionTitle";
|
||||||
import { INewPostsData } from "../types/posts.types";
|
import { INewPostsData } from "../types/posts.types";
|
||||||
|
import { dateParse } from "../helpers/dateParser";
|
||||||
|
|
||||||
const AllPosts = () => {
|
const AllPosts = () => {
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
|
|
@ -23,6 +24,7 @@ const AllPosts = () => {
|
||||||
[activePage, setActivePage]
|
[activePage, setActivePage]
|
||||||
);
|
);
|
||||||
const type = searchParams.get("type") || null;
|
const type = searchParams.get("type") || null;
|
||||||
|
const date = searchParams.get("date") || null;
|
||||||
|
|
||||||
const [params, setParams] = useState<IurlParamAdder[]>(
|
const [params, setParams] = useState<IurlParamAdder[]>(
|
||||||
type !== null
|
type !== null
|
||||||
|
|
@ -51,7 +53,16 @@ const AllPosts = () => {
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
const api = new Api(url + "/pagination/new/posts", params);
|
const api = new Api(
|
||||||
|
url + "/pagination/new/posts",
|
||||||
|
type === "date" && date
|
||||||
|
? [
|
||||||
|
{ name: "date", value: date },
|
||||||
|
{ name: "count", value: 10 },
|
||||||
|
{ name: "page", value: pageMemo.activePage },
|
||||||
|
]
|
||||||
|
: params
|
||||||
|
);
|
||||||
|
|
||||||
const language = api.language;
|
const language = api.language;
|
||||||
|
|
||||||
|
|
@ -68,6 +79,7 @@ const AllPosts = () => {
|
||||||
api.get(data, setData);
|
api.get(data, setData);
|
||||||
}, [params]);
|
}, [params]);
|
||||||
|
|
||||||
|
console.log(pageMemo.activePage);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (language !== lastLanguage) {
|
if (language !== lastLanguage) {
|
||||||
api.get(data, setData);
|
api.get(data, setData);
|
||||||
|
|
@ -79,7 +91,20 @@ const AllPosts = () => {
|
||||||
<main className="all">
|
<main className="all">
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<div className="all-inner">
|
<div className="all-inner">
|
||||||
{type === "video" ? <SectionTitle title={"Видео"} /> : null}
|
{type === "date" && date ? (
|
||||||
|
<SectionTitle title={dateParse(date)} />
|
||||||
|
) : null}
|
||||||
|
{type === "video" ? (
|
||||||
|
<SectionTitle
|
||||||
|
title={
|
||||||
|
language === "EN"
|
||||||
|
? "Videos"
|
||||||
|
: language === "RU"
|
||||||
|
? "Видео"
|
||||||
|
: "Videolar"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
{data ? (
|
{data ? (
|
||||||
<CustomNewsScroll
|
<CustomNewsScroll
|
||||||
data={data}
|
data={data}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
.all-inner {
|
.all-inner {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 3.2rem;
|
||||||
min-height: 50vh;
|
min-height: 50vh;
|
||||||
padding: 5.6rem 0;
|
padding: 5.6rem 0;
|
||||||
.loader {
|
.loader {
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,10 @@ h6 {
|
||||||
column-gap: 1.8rem;
|
column-gap: 1.8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button:disabled {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 900px) {
|
@media screen and (max-width: 900px) {
|
||||||
.container {
|
.container {
|
||||||
padding: 0 1.5rem;
|
padding: 0 1.5rem;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,17 @@
|
||||||
.pagination-wrapper {
|
.pagination-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
gap: 4rem;
|
gap: 4rem;
|
||||||
|
|
||||||
|
button {
|
||||||
|
width: 3.2rem;
|
||||||
|
height: 3.2rem;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 3.2rem;
|
||||||
|
height: 3.2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination-nums {
|
.pagination-nums {
|
||||||
|
|
@ -14,9 +25,7 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
// border: 0.1rem solid $main;
|
color: $black;
|
||||||
// background: $main;
|
|
||||||
color: $main;
|
|
||||||
font-size: 1.8rem;
|
font-size: 1.8rem;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
@ -32,3 +41,8 @@
|
||||||
.pagination-arr-left {
|
.pagination-arr-left {
|
||||||
transform: rotateY(180deg);
|
transform: rotateY(180deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pagination-total {
|
||||||
|
font-size: 1.8rem;
|
||||||
|
color: $main;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue