calendar and pagination

This commit is contained in:
VividTruthKeeper 2023-03-14 22:39:18 +05:00
parent fa54a83ca8
commit 0b6e6dabb2
10 changed files with 133 additions and 88 deletions

View File

@ -1,21 +1,19 @@
// Modules
import { v4 as uuidv4 } from 'uuid';
import { useState, useEffect } from 'react';
import { url } from '../../url';
import { Api } from '../../api/Api';
import { asideParams } from '../../api/params';
import { v4 as uuidv4 } from "uuid";
import { useState, useEffect } from "react";
import { url } from "../../url";
import { Api } from "../../api/Api";
import { asideParams } from "../../api/params";
// Components
import SectionTitle from '../global/SectionTitle';
import AsideNews from './AsideNews';
import Calendar from './Calendar';
import { IPostsData } from '../../types/data.types';
import Loader from '../global/Loader';
import { dateParse } from '../../helpers/dateParser';
import SectionTitle from "../global/SectionTitle";
import AsideNews from "./AsideNews";
import Calendar from "./Calendar";
import { IPostsData } from "../../types/data.types";
import Loader from "../global/Loader";
interface Props {
type: 'latest' | 'popular';
type: "latest" | "popular";
}
interface IData {
@ -23,7 +21,10 @@ interface IData {
}
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 [data, setData] = useState<IData>();
@ -37,25 +38,25 @@ const Aside = ({ type }: Props) => {
<div className="aside-wrapper">
<SectionTitle
title={
type === 'latest'
type === "latest"
? `${
language === 'EN'
? 'Latest news'
: language === 'RU'
? 'Последние новости'
: 'Soňky habarlar'
language === "EN"
? "Latest news"
: language === "RU"
? "Последние новости"
: "Soňky habarlar"
}`
: `${
language === 'EN'
? 'Most read'
: language === 'RU'
? 'Самое читаемое'
: 'Köp okalýar'
language === "EN"
? "Most read"
: language === "RU"
? "Самое читаемое"
: "Köp okalýar"
}`
}
/>
<div className="aside-inner">
{type === 'popular' ? (
{type === "popular" ? (
data ? (
(data as any).data.map((el: any) => {
return (

View File

@ -1,14 +1,14 @@
// Modules
import { Link } from 'react-router-dom';
import { LazyLoadImage } from 'react-lazy-load-image-component';
import ReactPlayer from 'react-player';
import { dateParse } from '../../helpers/dateParser';
import { Link } from "react-router-dom";
import { LazyLoadImage } from "react-lazy-load-image-component";
import ReactPlayer from "react-player";
// 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
import NewsCategory from '../global/NewsCategory';
import NewsDate from '../global/NewsDate';
import NewsCategory from "../global/NewsCategory";
import NewsDate from "../global/NewsDate";
interface Props {
title: string;
@ -25,7 +25,13 @@ const AsideNews = ({ title, date, img, category, id, video }: Props) => {
<div className="aside-news-wrapper">
<div className="aside-news-image">
{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
src={img}

View File

@ -1,23 +1,17 @@
// Modules
import { useState, useEffect, useCallback, useMemo } from "react";
import { useState, useCallback, useMemo } from "react";
import { Calendar as ReactCalendar } from "react-calendar";
import { LazyLoadComponent } from "react-lazy-load-image-component";
import { v4 as uuiv4 } from "uuid";
import { useNavigate } from "react-router-dom";
//
import { Api } from "../../api/Api";
import { url } from "../../url";
import { IPostData } from "../../types/store.types";
import Loader from "../global/Loader";
import { Link } from "react-router-dom";
const Calendar = () => {
const navigate = useNavigate();
const [value, onChange] = useState(new Date());
const [data, setData] = useState<any>();
const valueMemo = useMemo(() => ({ value, onChange }), [value, onChange]);
const dataMemo = useMemo(() => ({ data, setData }), [data, setData]);
const constructDateParam = useCallback(() => {
return `${value.getFullYear()}-${
@ -34,34 +28,16 @@ const Calendar = () => {
const api = new Api(url + `/posts`, [
{ name: "date", value: constructDateParam() },
]);
useEffect(() => {
api.get(dataMemo.data, dataMemo.setData);
}, [value]);
return (
<div className="calendar">
<LazyLoadComponent useIntersectionObserver>
<ReactCalendar value={value} onChange={valueMemo.onChange} />
</LazyLoadComponent>
<div className={"calendar-popup"}>
{data ? (
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>
<ReactCalendar
value={valueMemo.value}
onChange={valueMemo.onChange}
onClickDay={() =>
navigate(`/all?type=date&date=${constructDateParam()}`)
}
/>
</div>
);
};

View File

@ -7,7 +7,6 @@ import Pagination from "./Pagination";
// Types
import { INewPostsData } from "../../types/posts.types";
import Loader from "./Loader";
interface IProps {
data: INewPostsData;
@ -27,7 +26,6 @@ const CustomNewsScroll = ({
pageMemo,
avoidFirst,
}: IProps) => {
console.log(data);
return (
<div className="news-scroll">
<div className="news-scroll-wrapper">
@ -71,9 +69,11 @@ const CustomNewsScroll = ({
{pagination ? (
data ? (
<Pagination
pages={data?.meta.total}
next={data?.links.next}
prev={data?.links.prev}
activePage={pageMemo.activePage}
setActivePage={pageMemo.setActivePage}
total={data?.meta.total}
/>
) : null
) : null}

View File

@ -1,14 +1,26 @@
// Icons
import { Dispatch, SetStateAction } from 'react';
import { ReactComponent as Arr } from '../../assets/icons/pagintaion-arr.svg';
import { Dispatch, SetStateAction } from "react";
import { ReactComponent as Arr } from "../../assets/icons/pagintaion-arr.svg";
// Api
import { Api } from "../../api/Api";
interface IProps {
pages: number;
next: string | null;
prev: string | null;
activePage: 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) => {
setActivePage(page);
};
@ -16,8 +28,9 @@ const Pagination = ({ pages, activePage, setActivePage }: IProps) => {
<div className="pagination-wrapper">
<button
type="button"
disabled={activePage - 1 < 1}
onClick={() => handleOnClick(activePage - 1)}>
disabled={!prev ? true : false}
onClick={() => handleOnClick(activePage - 1)}
>
<Arr className="pagination-arr pagination-arr-left" />
</button>
<div className="pagination-nums">
@ -25,10 +38,15 @@ const Pagination = ({ pages, activePage, setActivePage }: IProps) => {
</div>
<button
type="button"
disabled={activePage + 1 >= pages}
onClick={() => handleOnClick(activePage + 1)}>
disabled={!next ? true : false}
onClick={() => handleOnClick(activePage + 1)}
>
<Arr className="pagination-arr pagination-arr-right" />
</button>
<span className="pagination-total">
{Math.ceil(total / 10)}{" "}
{language === "EN" ? "pages" : language === "RU" ? "страниц" : "sahypa"}
</span>
</div>
);
};

View File

@ -1,8 +1,6 @@
export const dateParse = (date: string) => {
try {
const splitArr = date.split(' ');
const dateYear = splitArr[0];
const dateYearSplit = dateYear.split('-');
const dateYearSplit = date.split("-");
const finalDate = `${dateYearSplit[2]}.${dateYearSplit[1]}.${dateYearSplit[0]}`;
return finalDate;
} catch (err) {

View File

@ -14,6 +14,7 @@ import Loader from "../components/global/Loader";
import { IurlParamAdder } from "../types/api.types";
import SectionTitle from "../components/global/SectionTitle";
import { INewPostsData } from "../types/posts.types";
import { dateParse } from "../helpers/dateParser";
const AllPosts = () => {
const [searchParams] = useSearchParams();
@ -23,6 +24,7 @@ const AllPosts = () => {
[activePage, setActivePage]
);
const type = searchParams.get("type") || null;
const date = searchParams.get("date") || null;
const [params, setParams] = useState<IurlParamAdder[]>(
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;
@ -68,6 +79,7 @@ const AllPosts = () => {
api.get(data, setData);
}, [params]);
console.log(pageMemo.activePage);
useEffect(() => {
if (language !== lastLanguage) {
api.get(data, setData);
@ -79,7 +91,20 @@ const AllPosts = () => {
<main className="all">
<div className="container">
<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 ? (
<CustomNewsScroll
data={data}

View File

@ -1,4 +1,7 @@
.all-inner {
display: flex;
flex-direction: column;
gap: 3.2rem;
min-height: 50vh;
padding: 5.6rem 0;
.loader {

View File

@ -73,6 +73,10 @@ h6 {
column-gap: 1.8rem;
}
button:disabled {
opacity: 0.4;
}
@media screen and (max-width: 900px) {
.container {
padding: 0 1.5rem;

View File

@ -1,6 +1,17 @@
.pagination-wrapper {
display: flex;
align-items: center;
gap: 4rem;
button {
width: 3.2rem;
height: 3.2rem;
svg {
width: 3.2rem;
height: 3.2rem;
}
}
}
.pagination-nums {
@ -14,9 +25,7 @@
align-items: center;
justify-content: center;
cursor: pointer;
// border: 0.1rem solid $main;
// background: $main;
color: $main;
color: $black;
font-size: 1.8rem;
pointer-events: none;
}
@ -32,3 +41,8 @@
.pagination-arr-left {
transform: rotateY(180deg);
}
.pagination-total {
font-size: 1.8rem;
color: $main;
}