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 // 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 (

View File

@ -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}

View File

@ -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>
); );
}; };

View File

@ -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}

View File

@ -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>
); );
}; };

View File

@ -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) {

View File

@ -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}

View File

@ -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 {

View File

@ -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;

View File

@ -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;
}