Merge branch 'main' of https://github.com/VividTruthKeeper/hhm-client
This commit is contained in:
commit
66e31a672a
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -6,8 +6,8 @@
|
|||
<meta name="description" id="meta-description" content="" />
|
||||
<meta name="keywords" id="meta-keywords" content="" />
|
||||
<title>Türkmenistan Habarlar Portaly</title>
|
||||
<script type="module" crossorigin src="/assets/index-0b06df0a.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index-b26665aa.css">
|
||||
<script type="module" crossorigin src="/assets/index-4929d075.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index-06deb898.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -1,67 +1,39 @@
|
|||
// 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()}-${
|
||||
value.getDate().toString().length < 2
|
||||
? "0" + value.getDate()
|
||||
: value.getDate()
|
||||
const constructDateParam = (date: Date) => {
|
||||
return `${date.getFullYear()}-${
|
||||
(date.getMonth() + 1).toString().length < 2
|
||||
? "0" + (date.getMonth() + 1)
|
||||
: date.getMonth() + 1
|
||||
}-${
|
||||
(value.getMonth() + 1).toString().length < 2
|
||||
? "0" + (value.getMonth() + 1)
|
||||
: value.getMonth() + 1
|
||||
date.getDate().toString().length < 2
|
||||
? "0" + date.getDate()
|
||||
: date.getDate()
|
||||
}`;
|
||||
}, [valueMemo.value]);
|
||||
|
||||
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={(date) =>
|
||||
navigate(`/all?type=date&date=${constructDateParam(date)}`)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
@ -79,13 +90,36 @@ const AllPosts = () => {
|
|||
<main className="all">
|
||||
<div className="container">
|
||||
<div className="all-inner">
|
||||
{type === "video" ? <SectionTitle title={"Видео"} /> : null}
|
||||
{data ? (
|
||||
<CustomNewsScroll
|
||||
data={data}
|
||||
pagination={true}
|
||||
pageMemo={pageMemo}
|
||||
{type === "date" && date ? (
|
||||
<SectionTitle title={dateParse(date)} />
|
||||
) : null}
|
||||
{type === "video" ? (
|
||||
<SectionTitle
|
||||
title={
|
||||
language === "EN"
|
||||
? "Videos"
|
||||
: language === "RU"
|
||||
? "Видео"
|
||||
: "Videolar"
|
||||
}
|
||||
/>
|
||||
) : null}
|
||||
{data ? (
|
||||
data.data.length > 0 ? (
|
||||
<CustomNewsScroll
|
||||
data={data}
|
||||
pagination={true}
|
||||
pageMemo={pageMemo}
|
||||
/>
|
||||
) : (
|
||||
<span className="empty">
|
||||
{language === "EN"
|
||||
? "No news for the selected date"
|
||||
: language === "RU"
|
||||
? "Нет новостей для выбранной даты"
|
||||
: "Saýlanan sene üçin habar ýok"}
|
||||
</span>
|
||||
)
|
||||
) : (
|
||||
<Loader />
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
.all-inner {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 3.2rem;
|
||||
min-height: 50vh;
|
||||
padding: 5.6rem 0;
|
||||
display: flex;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue