fix: view count func

This commit is contained in:
Atash03 2025-06-23 14:15:10 +05:00
parent a02b738012
commit a8c5dc79f0
5 changed files with 87 additions and 80 deletions

View File

@ -90,7 +90,9 @@ export class Queries {
} }
public static async getVideo(id: number): Promise<VideoModel> { public static async getVideo(id: number): Promise<VideoModel> {
return await fetch(`${baseUrl.MATERIALS_SRC}${routes.video(id)}`).then( return await fetch(`${baseUrl.MATERIALS_SRC}${routes.video(id)}`, {
cache: "no-store",
}).then(
(res) => res.json().then((res) => res as VideoModel) (res) => res.json().then((res) => res as VideoModel)
); );
} }

View File

@ -6,6 +6,8 @@ import { Queries } from '@/api/queries';
import Hydrate from '@/utils/HydrateClient'; import Hydrate from '@/utils/HydrateClient';
import { dehydrate, useMutation } from '@tanstack/react-query'; import { dehydrate, useMutation } from '@tanstack/react-query';
import SectionTitle from '@/components/SectionTitle'; import SectionTitle from '@/components/SectionTitle';
import { Suspense } from 'react';
import Loader from '@/components/Loader';
interface IParams { interface IParams {
params: { params: {
@ -32,12 +34,12 @@ const VideoItem = async ({ params }: IParams) => {
queryFn: ({ pageParam = 1 }) => queryFn: ({ pageParam = 1 }) =>
Queries.getVideos( Queries.getVideos(
'?' + '?' +
String( String(
new URLSearchParams({ new URLSearchParams({
page: pageParam, page: pageParam,
per_page: '8', per_page: '8',
}), }),
), ),
), ),
}); });
const dehydratedState = dehydrate(queryClient); const dehydratedState = dehydrate(queryClient);
@ -48,7 +50,13 @@ const VideoItem = async ({ params }: IParams) => {
<Hydrate state={dehydratedState}> <Hydrate state={dehydratedState}>
<div className="video-item-inner"> <div className="video-item-inner">
<div className="video-item-wrapper flex flex-col gap-10 relative pb-14"> <div className="video-item-wrapper flex flex-col gap-10 relative pb-14">
<InfoBlock video_id={params.video_id} /> <Suspense fallback={
<div className="w-full h-[500px] sm:h-[667px] md:h-[600px] lg:h-[700px] flex items-center justify-center">
<Loader height={700} />
</div>
}>
<InfoBlock video_id={params.video_id} />
</Suspense>
<div className="video-item-inner w-full flex flex-col gap-4"> <div className="video-item-inner w-full flex flex-col gap-4">
<SectionTitle title={'Beylekiler'} /> <SectionTitle title={'Beylekiler'} />

View File

@ -1,69 +1,25 @@
"use client";
// NextJs components // NextJs components
import Image from "next/image"; import Image from "next/image";
import Link from "next/link"; import Link from "next/link";
// React query // React query
import { useQuery } from "@tanstack/react-query";
import { Queries } from "@/api/queries"; import { Queries } from "@/api/queries";
// Components // Components
import Loader from "./Loader";
import VideoPlayer from "./VideoPlayer"; import VideoPlayer from "./VideoPlayer";
import SectionTitle from "./SectionTitle"; import SectionTitle from "./SectionTitle";
// Images and cions // Images and cions
import { SlEye } from "react-icons/sl";
import aydym from "@/public/aydym-com.webp"; import aydym from "@/public/aydym-com.webp";
import horjun from "@/public/horjun.png"; import horjun from "@/public/horjun.png";
import belet from "@/public/belet.jpg"; import belet from "@/public/belet.jpg";
import ReactionsBlock from "./treasury/ReactionsBlock"; import ReactionsBlock from "./treasury/ReactionsBlock";
import { useCallback, useEffect, useState } from "react"; import ViewCount from "./view-count";
import axios from "axios";
interface IProps { interface IProps {
video_id: number; video_id: number;
} }
const InfoBlock = ({ video_id }: IProps) => { const InfoBlock = async ({ video_id }: IProps) => {
const { data, isFetching, error } = useQuery({ const {data} = await Queries.getVideo(video_id);
queryKey: ["video", `video:${video_id}`],
queryFn: () => Queries.getVideo(video_id),
});
const [view, setView] = useState(data?.data?.view || 0);
const addView = useCallback(async () => {
const materials = localStorage.getItem('MHB_MATERIALS_ID');
if (materials) {
const materialsArray = materials.split(',');
if (!materialsArray.includes(video_id.toString())) {
const res = await axios.post(`https://turkmentv.gov.tm/v2/api/material/${video_id}/views/increment`);
if (res.status === 200) {
materialsArray.push(video_id.toString());
setView(res.data.view);
}
}
localStorage.setItem('MHB_MATERIALS_ID', materialsArray.join(','));
} else {
const res = await axios.post(`https://turkmentv.gov.tm/v2/api/material/${video_id}/views/increment`);
if (res.status === 200) {
localStorage.setItem('MHB_MATERIALS_ID', [video_id.toString()].join(','));
setView(res.data.view);
}
}
}, [video_id])
useEffect(() => {
addView();
}, []);
if (isFetching)
return (
<div className="w-full h-[500px] sm:h-[667px] md:h-[600px] l flex items-center justify-center">
<Loader height={700} />
</div>
);
if (error) return <h1>{JSON.stringify(error)}</h1>;
return ( return (
<div className="flex gap-6 max-w-[1220px] w-full justify-between h-full"> <div className="flex gap-6 max-w-[1220px] w-full justify-between h-full">
@ -71,20 +27,8 @@ const InfoBlock = ({ video_id }: IProps) => {
<div className="flex justify-between gap-[32px] w-full h-full"> <div className="flex justify-between gap-[32px] w-full h-full">
<div className="w-full flex flex-col gap-6 h-full"> <div className="w-full flex flex-col gap-6 h-full">
<div className=" flex flex-col gap-2"> <div className=" flex flex-col gap-2">
<SectionTitle title={data!.data.title} /> <SectionTitle title={data.title} />
<div className="flex gap-2 items-center"> <ViewCount video_id={video_id} viewCount={data.view} />
<SlEye
style={{
transition: "150ms all cubic-bezier(0.4, 0, 0.2, 1)",
}}
width={30}
height={18}
className="w-[30px] h-[18px]"
/>
<span className="font-roboto text-lg font-normal text-[#494949] transition-all dark:text-white">
{view}
</span>
</div>
</div> </div>
<div className="flex flex-col gap-[40px] h-full w-full"> <div className="flex flex-col gap-[40px] h-full w-full">
<div className="flex gap-[40px] md:flex-row flex-col h-full w-full"> <div className="flex gap-[40px] md:flex-row flex-col h-full w-full">
@ -97,25 +41,25 @@ const InfoBlock = ({ video_id }: IProps) => {
</div> </div>
<div className="flex flex-col gap-6"> <div className="flex flex-col gap-6">
{data?.data.desc ? ( {data.desc ? (
<p className="font-roboto text-lg w-full text-black"> <p className="font-roboto text-lg w-full text-black">
{data!.data.desc} {data.desc}
</p> </p>
) : null} ) : null}
<ReactionsBlock video_id={video_id} /> <ReactionsBlock video_id={video_id} />
{data?.data.aydym_com_url || {data.aydym_com_url ||
data?.data.horjun_content_url || data.horjun_content_url ||
data?.data.belet_url ? ( data.belet_url ? (
<div className="flex flex-col gap-6"> <div className="flex flex-col gap-6">
<h2 className="text-2xl font-semibold"> <h2 className="text-2xl font-semibold">
Beýleki platformalarda seret: Beýleki platformalarda seret:
</h2> </h2>
<div className="flex gap-11 items-center"> <div className="flex gap-11 items-center">
{data?.data.aydym_com_url ? ( {data.aydym_com_url ? (
<Link <Link
href={data?.data.aydym_com_url} href={data.aydym_com_url}
target="_blank" target="_blank"
className="flex flex-col items-center justify-center gap-2" className="flex flex-col items-center justify-center gap-2"
> >
@ -129,9 +73,9 @@ const InfoBlock = ({ video_id }: IProps) => {
<h3>Aydym.com</h3> <h3>Aydym.com</h3>
</Link> </Link>
) : null} ) : null}
{data?.data.horjun_content_url ? ( {data.horjun_content_url ? (
<Link <Link
href={data?.data.horjun_content_url} href={data.horjun_content_url}
target="_blank" target="_blank"
className="flex flex-col items-center justify-center gap-2" className="flex flex-col items-center justify-center gap-2"
> >
@ -145,9 +89,9 @@ const InfoBlock = ({ video_id }: IProps) => {
<h3>HorjunTv</h3> <h3>HorjunTv</h3>
</Link> </Link>
) : null} ) : null}
{data?.data.belet_url ? ( {data.belet_url ? (
<Link <Link
href={data.data.belet_url} href={data.belet_url}
target="_blank" target="_blank"
className="flex flex-col items-center justify-center gap-2" className="flex flex-col items-center justify-center gap-2"
> >

View File

@ -1,3 +1,4 @@
'use client';
import { Queries } from '@/api/queries'; import { Queries } from '@/api/queries';
import { useMutation, useQuery } from '@tanstack/react-query'; import { useMutation, useQuery } from '@tanstack/react-query';
import axios from 'axios'; import axios from 'axios';

52
components/view-count.tsx Normal file
View File

@ -0,0 +1,52 @@
'use client';
import axios from 'axios';
import React, { useCallback, useEffect, useState } from 'react'
import { SlEye } from 'react-icons/sl'
function ViewCount({ video_id, viewCount }: { video_id: number, viewCount: number }) {
const [view, setView] = useState(viewCount);
const addView = useCallback(async () => {
const materials = localStorage.getItem('MHB_MATERIALS_ID');
if (materials) {
const materialsArray = materials.split(',');
if (!materialsArray.includes(video_id.toString())) {
const res = await axios.post(`https://turkmentv.gov.tm/v2/api/material/${video_id}/views/increment`);
if (res.status === 200) {
materialsArray.push(video_id.toString());
setView(res.data.view);
}
}
localStorage.setItem('MHB_MATERIALS_ID', materialsArray.join(','));
} else {
const res = await axios.post(`https://turkmentv.gov.tm/v2/api/material/${video_id}/views/increment`);
if (res.status === 200) {
localStorage.setItem('MHB_MATERIALS_ID', [video_id.toString()].join(','));
setView(res.data.view);
}
}
}, [video_id])
useEffect(() => {
addView();
}, []);
return (
<div className="flex gap-2 items-center">
<SlEye
style={{
transition: "150ms all cubic-bezier(0.4, 0, 0.2, 1)",
}}
width={30}
height={18}
className="w-[30px] h-[18px]"
/>
<span className="font-roboto text-lg font-normal text-[#494949] transition-all dark:text-white">
{view}
</span>
</div>
)
}
export default ViewCount