video section

This commit is contained in:
Kakabay 2023-02-28 15:28:51 +05:00
parent 7b1b8e9d79
commit 318e13074b
14 changed files with 266 additions and 241 deletions

View File

@ -8,34 +8,35 @@ import {
IPostDataAction,
ISearchResult,
ISearchResultAction,
} from "../types/store.types";
IVideoData,
IVideoDataAction,
} from '../types/store.types';
// NewsScroll
export const setNewsScroll = (
data: INewsScroll["data"]
): INewsScrollAction => ({
type: "SET_NEWS_SCROLL",
export const setNewsScroll = (data: INewsScroll['data']): INewsScrollAction => ({
type: 'SET_NEWS_SCROLL',
payload: data,
});
export const setSearchResult = (
data: ISearchResult["data"]
): ISearchResultAction => ({
type: "SET_SEARCH_DATA",
export const setSearchResult = (data: ISearchResult['data']): ISearchResultAction => ({
type: 'SET_SEARCH_DATA',
payload: data,
});
// Post
export const setPost = (data: IPostData["data"]): IPostDataAction => ({
type: "SET_POST",
export const setPost = (data: IPostData['data']): IPostDataAction => ({
type: 'SET_POST',
payload: data,
});
export const setFeatured = (
data: IFeaturedData["data"]
): IFeaturedDataAction => ({
type: "SET_FEATURED",
export const setVideo = (data: IVideoData['data']): IVideoDataAction => ({
type: 'SET_VIDEO',
payload: data,
});
export const setFeatured = (data: IFeaturedData['data']): IFeaturedDataAction => ({
type: 'SET_FEATURED',
payload: data,
});

View File

@ -1,38 +1,53 @@
import { IurlParamAdder } from "../types/api.types";
import { IurlParamAdder } from '../types/api.types';
export const newsScrollParams: IurlParamAdder[] = [
{
name: "count",
name: 'count',
value: 5,
},
{
name: "page",
name: 'page',
value: 1,
},
];
export const categoriesParams: IurlParamAdder[] = [
{
name: "count",
name: 'count',
value: 100,
},
{
name: "page",
name: 'page',
value: 1,
},
];
export const featuredParams: IurlParamAdder[] = [
{
name: "count",
name: 'count',
value: 5,
},
{
name: "page",
name: 'page',
value: 1,
},
{
name: "featured",
value: "true",
name: 'featured',
value: 'true',
},
];
export const videoParams: IurlParamAdder[] = [
{
name: 'count',
value: 5,
},
{
name: 'page',
value: 1,
},
{
name: 'type',
value: 'video',
},
];

View File

@ -0,0 +1,7 @@
import React from 'react';
const AsideLast = () => {
return <div>AsideLast</div>;
};
export default AsideLast;

View File

@ -1,5 +1,5 @@
// Modules
import { Link } from "react-router-dom";
// import { Link } from "react-router-dom";
interface Props {
title: string;

View File

@ -1,24 +1,24 @@
// Modules
import { useEffect, useState } from "react";
import { v4 as uuidv4 } from "uuid";
import { useSelector, useDispatch } from "react-redux";
import { useEffect, useState } from 'react';
import { v4 as uuidv4 } from 'uuid';
import { useSelector, useDispatch } from 'react-redux';
// Components
import News from "../news/News";
import SectionTitle from "./SectionTitle";
import Loader from "./Loader";
import News from '../news/News';
import SectionTitle from './SectionTitle';
import Loader from './Loader';
// Api
import { url } from "../../url";
import { Api } from "../../api/Api";
import { newsScrollParams } from "../../api/params";
import { url } from '../../url';
import { Api } from '../../api/Api';
import { newsScrollParams } from '../../api/params';
// Types
import { IPostsData } from "../../types/data.types";
import { RootState } from "../../types/store.types";
import { IPostsData } from '../../types/data.types';
import { RootState } from '../../types/store.types';
// Actions
import { setNewsScroll } from "../../actions/setData";
import { setNewsScroll } from '../../actions/setData';
interface Props {
title: boolean;
@ -27,15 +27,15 @@ interface Props {
const NewsScroll = ({ title, category }: Props) => {
const params = newsScrollParams.slice();
category ? params.push({ name: "category", value: category }) : null;
category ? params.push({ name: 'category', value: category }) : null;
const api = new Api(url + "/posts", params);
const api = new Api(url + '/posts', params);
const language = api.language;
const [lastLanguage, setLastLanguage] = useState<string>(language);
// redux
const rawData = useSelector<RootState, RootState["newsScroll"]["data"]>(
(state) => state.newsScroll.data
const rawData = useSelector<RootState, RootState['newsScroll']['data']>(
(state) => state.newsScroll.data,
);
const dispatch = useDispatch();
@ -46,12 +46,8 @@ const NewsScroll = ({ title, category }: Props) => {
useEffect(() => {
if (rawData.length > 0) {
if (
!((rawData as IPostsData[])[0].id > -1 && lastLanguage === language)
) {
api.get(rawData, (rawData: IPostsData[]) =>
dispatch(setNewsScroll(rawData))
);
if (!((rawData as IPostsData[])[0].id > -1 && lastLanguage === language)) {
api.get(rawData, (rawData: IPostsData[]) => dispatch(setNewsScroll(rawData)));
setLastLanguage(language);
}
}
@ -61,7 +57,7 @@ const NewsScroll = ({ title, category }: Props) => {
useEffect(() => {
const filtered = rawData.filter((el, index) => {
if (index > 0) {
if (index >= 0) {
return el;
}
});
@ -74,7 +70,7 @@ const NewsScroll = ({ title, category }: Props) => {
{title === true ? (
<SectionTitle
title="Лента новостей"
linkData={{ link: "/all/null", title: "Посмотреть все" }}
linkData={{ link: '/all/null', title: 'Посмотреть все' }}
/>
) : null}
<div className="news-scroll-inner">
@ -89,11 +85,7 @@ const NewsScroll = ({ title, category }: Props) => {
text={dataEl.excerpt}
date={dataEl.published_at}
categories={dataEl.categories}
img={
dataEl.featured_images[0]
? dataEl.featured_images[0].path
: ""
}
img={dataEl.featured_images[0] ? dataEl.featured_images[0].path : ''}
/>
);
})

View File

@ -1,58 +1,61 @@
// Modules
// import { v4 as uuiv4 } from "uuid";
import { useEffect, useState } from 'react';
import { v4 as uuiv4 } from 'uuid';
import { useSelector, useDispatch } from 'react-redux';
// Components
import SectionTitle from "../global/SectionTitle";
// import VideosItem from "./VideosItem";
// // Videos
// import VideoPlaceholder from "../../assets/videos/placeholder.mp4";
import SectionTitle from '../global/SectionTitle';
import VideosItem from './VideosItem';
// Types
// import { videosDataType } from "../../types/videos.types";
import { RootState } from '../../types/store.types';
// const videosData: videosDataType[] = [
// {
// placeholder: Placeholder,
// url: VideoPlaceholder,
// },
// {
// placeholder: Placeholder,
// url: VideoPlaceholder,
// },
// {
// placeholder: Placeholder,
// url: VideoPlaceholder,
// },
// {
// placeholder: Placeholder,
// url: VideoPlaceholder,
// },
// ];
// Api
import { Api } from '../../api/Api';
import { url } from '../../url';
import { videoParams } from '../../api/params';
// Actions
import { setVideo } from '../../actions/setData';
const Videos = () => {
const data = useSelector<RootState, RootState['video']['data']>((state) => state.video.data);
const api = new Api(url + '/posts', videoParams);
const language = api.language;
const dispatch = useDispatch();
const [lastLanguage, setLastLanguage] = useState<typeof language>(language);
useEffect(() => {
if (!(lastLanguage === language && data[0].id > -1)) {
api.get(data, (data) => dispatch(setVideo(data)));
setLastLanguage(language);
}
}, [lastLanguage, language]);
return (
<section className="videos">
{/* <div className="container"> */}
<div className="videos-inner">
<SectionTitle
title="Видео"
givenClass="videos"
linkData={{ link: "/", title: "Посмотреть все" }}
linkData={{ link: '/', title: 'Посмотреть все' }}
/>
<div className="videos-items">
{/* {videosData.map((videosDataItem: videosDataType) => {
{data.map((videosDataItem) => {
return (
<VideosItem
key={uuiv4()}
url={videosDataItem.url}
placeholder={videosDataItem.placeholder}
url={videosDataItem.video || ''}
placeholder={
videosDataItem.featured_images[0] ? videosDataItem.featured_images[0].path : ''
}
date={videosDataItem.published_at}
excerpt={videosDataItem.excerpt}
/>
);
})} */}
})}
</div>
</div>
{/* </div> */}
</section>
);
};

View File

@ -1,26 +1,20 @@
// Modules
import ReactPlayer from "react-player";
import { LazyLoadComponent } from "react-lazy-load-image-component";
import ReactPlayer from 'react-player';
import { LazyLoadComponent } from 'react-lazy-load-image-component';
// Types
import { videosDataType } from "../../types/videos.types";
import { videosDataType } from '../../types/videos.types';
const VideosItem = ({ url, placeholder }: videosDataType) => {
const VideosItem = ({ url, placeholder, date, excerpt }: videosDataType) => {
return (
<div className="videos-item">
<LazyLoadComponent useIntersectionObserver>
<div className="videos-item-video">
<ReactPlayer
url={url}
controls
light={placeholder}
width="100%"
height="100%"
/>
<ReactPlayer url={url} controls light={placeholder} width="100%" height="100%" />
</div>
<div className="videos-item-data">
<span>11.01.2023</span>
<p>В Туркменистане отметили Новый год</p>
<span>{date}</span>
<p>{excerpt}</p>
</div>
</LazyLoadComponent>
</div>

View File

@ -1,11 +1,11 @@
// Modules
import { motion } from "framer-motion";
import { motion } from 'framer-motion';
// Components
import Aside from "../components/aside/Aside";
import NewsScroll from "../components/global/NewsScroll";
// import Videos from "../components/videos/Videos";
import MainContent from "../components/main/MainContent";
import Aside from '../components/aside/Aside';
import NewsScroll from '../components/global/NewsScroll';
import Videos from '../components/videos/Videos';
import MainContent from '../components/main/MainContent';
const Main = () => {
return (
@ -13,9 +13,8 @@ const Main = () => {
className="main"
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1, transition: { duration: 0.15 } }}
exit={{ opacity: 0, scale: 0.8, transition: { duration: 0.15 } }}
>
<h1 style={{ display: "none" }}>Туркменистан новостной портал</h1>
exit={{ opacity: 0, scale: 0.8, transition: { duration: 0.15 } }}>
<h1 style={{ display: 'none' }}>Туркменистан новостной портал</h1>
<div className="news-section">
<div className="container">
<div className="news-inner">
@ -24,7 +23,7 @@ const Main = () => {
<NewsScroll title={true} />
<Aside />
</div>
{/* <Videos /> */}
<Videos />
</div>
</div>
</div>

View File

@ -1,29 +1,29 @@
// Modules
import { Link, useParams } from "react-router-dom";
import { useEffect, useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { v4 as uuidv4 } from "uuid";
import { motion } from "framer-motion";
import { Link, useParams } from 'react-router-dom';
import { useEffect, useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { v4 as uuidv4 } from 'uuid';
import { motion } from 'framer-motion';
// Components
import Aside from "../components/aside/Aside";
import NewsArticleSlider from "../components/news/NewsArticleSlider";
import Loader from "../components/global/Loader";
import VideosItem from "../components/videos/VideosItem";
import Aside from '../components/aside/Aside';
import NewsArticleSlider from '../components/news/NewsArticleSlider';
import Loader from '../components/global/Loader';
// import VideosItem from "../components/videos/VideosItem";
// Icons
import { ReactComponent as Share } from "../assets/icons/share.svg";
import { ReactComponent as Share } from '../assets/icons/share.svg';
// Types
import { RootState } from "../types/store.types";
import { IPostData } from "../types/store.types";
import { RootState } from '../types/store.types';
import { IPostData } from '../types/store.types';
// Actions
import { setPost } from "../actions/setData";
import { setPost } from '../actions/setData';
// Api
import { Api } from "../api/Api";
import { url } from "../url";
import { Api } from '../api/Api';
import { url } from '../url';
const NewsArticle = () => {
const { id } = useParams();
@ -35,27 +35,21 @@ const NewsArticle = () => {
const [lastLanguage, setLastLanguage] = useState<string>(language);
// redux
const data = useSelector<RootState, RootState["post"]["data"]>(
(state) => state.post.data
);
const data = useSelector<RootState, RootState['post']['data']>((state) => state.post.data);
const dispatch = useDispatch();
useEffect(() => {
if (
!(data.data.id === parseInt(id as string) && lastLanguage === language)
) {
api.get(data, (data: IPostData["data"]) => dispatch(setPost(data)));
if (!(data.data.id === parseInt(id as string) && lastLanguage === language)) {
api.get(data, (data: IPostData['data']) => dispatch(setPost(data)));
setLastLanguage(language);
}
}, [language, lastLanguage]);
// SEO
useEffect(() => {
const metaDescription: any = document.querySelector(
"meta#meta-description"
);
const metaKeywords: any = document.querySelector("meta#meta-keywords");
const title: any = document.querySelector("title");
const metaDescription: any = document.querySelector('meta#meta-description');
const metaKeywords: any = document.querySelector('meta#meta-keywords');
const title: any = document.querySelector('title');
try {
title.innerText = data.data.powerseo_title;
metaDescription.content = data.data.powerseo_description;
@ -70,8 +64,7 @@ const NewsArticle = () => {
className="news-article"
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1, transition: { duration: 0.15 } }}
exit={{ opacity: 0, scale: 0.8, transition: { duration: 0.15 } }}
>
exit={{ opacity: 0, scale: 0.8, transition: { duration: 0.15 } }}>
<div className="container">
<div className="news-article-inner">
{data.data.id > -1 ? (
@ -83,16 +76,13 @@ const NewsArticle = () => {
<Link
key={uuidv4()}
to={`/category/${category.id}`}
className="news-article-category"
>
className="news-article-category">
{category.name}
</Link>
))}
</div>
<div className="news-article-right">
<h3 className="news-article-date">
{data.data.published_at}
</h3>
<h3 className="news-article-date">{data.data.published_at}</h3>
</div>
</div>
<h2 className="news-article-title">{data.data.title}</h2>
@ -114,8 +104,7 @@ const NewsArticle = () => {
</div>
<p
className="news-article-text"
dangerouslySetInnerHTML={{ __html: data.data.content_html }}
></p>
dangerouslySetInnerHTML={{ __html: data.data.content_html }}></p>
<button className="share-btn">
<Share /> <span>Поделиться</span>
</button>

View File

@ -8,7 +8,9 @@ import {
IPostDataAction,
ISearchResult,
ISearchResultAction,
} from "../types/store.types";
IVideoData,
IVideoDataAction,
} from '../types/store.types';
// NewsScroll
@ -16,54 +18,54 @@ export const newsScrollInitialState = {
data: [
{
id: -1,
title: "",
slug: "",
excerpt: "",
published_at: "",
title: '',
slug: '',
excerpt: '',
published_at: '',
featured_images: [
{
id: -1,
disk_name: "",
file_name: "",
path: "",
extension: "",
disk_name: '',
file_name: '',
path: '',
extension: '',
},
{
id: -1,
disk_name: "",
file_name: "",
path: "",
extension: "",
disk_name: '',
file_name: '',
path: '',
extension: '',
},
{
id: -1,
disk_name: "",
file_name: "",
path: "",
extension: "",
disk_name: '',
file_name: '',
path: '',
extension: '',
},
],
content_html: "",
content_html: '',
categories: [
{
id: -1,
name: "",
name: '',
},
],
video: null,
powerseo_title: "",
powerseo_description: "",
powerseo_keywords: "",
powerseo_title: '',
powerseo_description: '',
powerseo_keywords: '',
},
],
};
export const newsScrollReducer = (
state: INewsScroll = newsScrollInitialState,
action: INewsScrollAction
action: INewsScrollAction,
) => {
switch (action.type) {
case "SET_NEWS_SCROLL": {
case 'SET_NEWS_SCROLL': {
return { ...state, data: action.payload };
}
default: {
@ -78,54 +80,51 @@ export const postInitialState = {
data: {
data: {
id: -1,
title: "",
slug: "",
excerpt: "",
published_at: "",
title: '',
slug: '',
excerpt: '',
published_at: '',
video: null,
featured_images: [
{
id: -1,
disk_name: "",
file_name: "",
path: "",
extension: "",
disk_name: '',
file_name: '',
path: '',
extension: '',
},
{
id: -1,
disk_name: "",
file_name: "",
path: "",
extension: "",
disk_name: '',
file_name: '',
path: '',
extension: '',
},
{
id: -1,
disk_name: "",
file_name: "",
path: "",
extension: "",
disk_name: '',
file_name: '',
path: '',
extension: '',
},
],
content_html: "",
content_html: '',
categories: [
{
id: -1,
name: "",
name: '',
},
],
powerseo_title: "",
powerseo_description: "",
powerseo_keywords: "",
powerseo_title: '',
powerseo_description: '',
powerseo_keywords: '',
},
},
};
export const postReducer = (
state: IPostData = postInitialState,
action: IPostDataAction
) => {
export const postReducer = (state: IPostData = postInitialState, action: IPostDataAction) => {
switch (action.type) {
case "SET_POST": {
case 'SET_POST': {
return { ...state, data: action.payload };
}
default: {
@ -138,54 +137,54 @@ export const featuredInitialState = {
data: [
{
id: -1,
title: "",
slug: "",
excerpt: "",
published_at: "",
title: '',
slug: '',
excerpt: '',
published_at: '',
video: null,
featured_images: [
{
id: -1,
disk_name: "",
file_name: "",
path: "",
extension: "",
disk_name: '',
file_name: '',
path: '',
extension: '',
},
{
id: -1,
disk_name: "",
file_name: "",
path: "",
extension: "",
disk_name: '',
file_name: '',
path: '',
extension: '',
},
{
id: -1,
disk_name: "",
file_name: "",
path: "",
extension: "",
disk_name: '',
file_name: '',
path: '',
extension: '',
},
],
content_html: "",
content_html: '',
categories: [
{
id: -1,
name: "",
name: '',
},
],
powerseo_title: "",
powerseo_description: "",
powerseo_keywords: "",
powerseo_title: '',
powerseo_description: '',
powerseo_keywords: '',
},
],
};
export const featuredReducer = (
state: IFeaturedData = featuredInitialState,
action: IFeaturedDataAction
action: IFeaturedDataAction,
) => {
switch (action.type) {
case "SET_FEATURED": {
case 'SET_FEATURED': {
return { ...state, data: action.payload };
}
default: {
@ -196,10 +195,10 @@ export const featuredReducer = (
export const searchDataReducer = (
state: ISearchResult = newsScrollInitialState,
action: ISearchResultAction
action: ISearchResultAction,
) => {
switch (action.type) {
case "SET_SEARCH_DATA": {
case 'SET_SEARCH_DATA': {
return { data: action.payload };
}
default: {
@ -207,3 +206,17 @@ export const searchDataReducer = (
}
}
};
export const videoReducer = (
state: IVideoData = newsScrollInitialState,
action: IVideoDataAction,
) => {
switch (action.type) {
case 'SET_VIDEO': {
return { ...state, data: action.payload };
}
default: {
return state;
}
}
};

View File

@ -1,16 +1,17 @@
// Modules
import { combineReducers, configureStore } from "@reduxjs/toolkit";
import { combineReducers, configureStore } from '@reduxjs/toolkit';
// Reducers
import { activeLinkReducer } from "../reducers/activeLink.reducer";
import { languageReducer } from "../reducers/language.reducer";
import { activeLinkReducer } from '../reducers/activeLink.reducer';
import { languageReducer } from '../reducers/language.reducer';
import {
newsScrollReducer,
postReducer,
searchDataReducer,
featuredReducer,
} from "../reducers/dataReducer";
import { searchReducer } from "../reducers/searchReducer";
videoReducer,
} from '../reducers/dataReducer';
import { searchReducer } from '../reducers/searchReducer';
export const allReducers = combineReducers({
activeLink: activeLinkReducer,
@ -20,6 +21,7 @@ export const allReducers = combineReducers({
search: searchReducer,
searchData: searchDataReducer,
featured: featuredReducer,
video: videoReducer,
});
export const functionalityStore = configureStore({

View File

@ -1,7 +1,7 @@
.news-wrapper {
display: grid;
grid-template-columns: 32rem 1fr;
grid-template-rows: 20rem;
grid-template-rows: 22rem;
gap: 1.6rem;
.loader {

View File

@ -1,26 +1,26 @@
// Reducers
import { allReducers } from "../store/functionality";
import { allReducers } from '../store/functionality';
// Types
import { IPostsData } from "./data.types";
import { IPostsData } from './data.types';
// NavLink
export interface ActiveLinkType {
active: number;
}
export interface ActiveLinkActionType {
type: "SET_ACTIVE_LINK";
type: 'SET_ACTIVE_LINK';
payload: number;
}
// Language
export interface ILanguage {
title: "RU" | "EN" | "TM";
title: 'RU' | 'EN' | 'TM';
}
export interface ILanguageAction {
type: "SET_LANGUAGE";
payload: "RU" | "EN" | "TM";
type: 'SET_LANGUAGE';
payload: 'RU' | 'EN' | 'TM';
}
// NewsScroll
@ -29,8 +29,8 @@ export interface INewsScroll {
data: IPostsData[];
}
export interface INewsScrollAction {
type: "SET_NEWS_SCROLL";
payload: INewsScroll["data"];
type: 'SET_NEWS_SCROLL';
payload: INewsScroll['data'];
}
// Post
@ -42,16 +42,24 @@ export interface IPostData {
}
export interface IPostDataAction {
type: "SET_POST";
payload: IPostData["data"];
type: 'SET_POST';
payload: IPostData['data'];
}
export interface IVideoData {
data: IPostsData[];
}
export interface IVideoDataAction {
type: 'SET_VIDEO';
payload: INewsScroll['data'];
}
export interface IFeaturedData {
data: IPostsData[];
}
export interface IFeaturedDataAction {
type: "SET_FEATURED";
payload: IFeaturedData["data"];
type: 'SET_FEATURED';
payload: IFeaturedData['data'];
}
//
@ -60,16 +68,16 @@ export interface ISearchData {
value: string;
}
export interface ISearchDataAction {
type: "SET_SEARCH";
payload: ISearchData["value"];
type: 'SET_SEARCH';
payload: ISearchData['value'];
}
export interface ISearchResult {
data: IPostsData[];
}
export interface ISearchResultAction {
type: "SET_SEARCH_DATA";
payload: ISearchResult["data"];
type: 'SET_SEARCH_DATA';
payload: ISearchResult['data'];
}
// ALL TYPES BEFORE THIS LINE ==================

View File

@ -1,4 +1,6 @@
export interface videosDataType {
url: string;
placeholder: string;
date: string;
excerpt: string;
}