Add news page

This commit is contained in:
ariari04 2024-09-05 12:08:57 +06:00
parent 3b510b6d42
commit d601659289
6 changed files with 181 additions and 2 deletions

View File

@ -6,8 +6,8 @@ const nextConfig = {
images: {
remotePatterns: [
{
protocol: "https",
hostname: "**",
protocol: "http",
hostname: "***",
},
],
},

View File

@ -0,0 +1,22 @@
import { Container, Title } from "@/shared/ui";
import NewsList from "@/widgets/NewsList/NewsList";
import React from "react";
const News = ({
searchParams,
}: {
searchParams: {
["страница-новостей"]: string;
};
}) => {
return (
<div className="flex flex-col bg-[#FAFCFF]">
<Container>
<Title text="Новости" className="mb-[40px]" />
<NewsList searchParams={searchParams} />
</Container>
</div>
);
};
export default News;

50
src/entities/NewsCard.tsx Normal file
View File

@ -0,0 +1,50 @@
import { Title } from "@/shared/ui";
import Image, { StaticImageData } from "next/image";
interface INewsCard {
id: number;
image: StaticImageData | string;
title: string;
content: string;
date: string;
}
const NewsCard = ({ id, image, title, content, date }: INewsCard) => {
const sliceTitle = (title: string) => {
if (title.length > 35) {
return `${title.slice(0, 35)}...`;
}
return title;
};
const sliceDescription = (content: string) => {
if (content.length > 65) {
return `${content.slice(0, 65)}...`;
}
return content;
};
const sliceDate = (date: string) => {
return `${date.slice(8, 10)}/${date.slice(5, 7)}/${date.slice(0, 4)}`;
};
return (
<div className="w-[393px] h-[508px] bg-white shadow-sm p-6 flex flex-col">
<Image
src={image}
alt="Card image"
width={345}
height={240}
className="mb-[32px]"
/>
<Title
text={sliceTitle(title)}
className="text-[24px] font-semibold mb-[12px]"
/>
<p className="leading-6 text-gray-600 mb-[46px]">
{sliceDescription(content)}
</p>
<p className="text-[14px] text-gray-600">{sliceDate(date)}</p>
</div>
);
};
export default NewsCard;

View File

@ -0,0 +1,13 @@
import { IList } from "./list-type";
export interface INews {
id: number;
title: string;
content: string;
image: string;
created_at: string;
}
export interface INewsList extends IList {
results: INews[];
}

View File

@ -0,0 +1,56 @@
"use client";
import { useEffect, useState } from "react";
import { useNewsStore } from "./newsStore";
import NewsCard from "@/entities/NewsCard";
import Pagination from "@/features/Pagination/Pagination";
interface INewsListProps {
searchParams: {
["страница-новостей"]: string;
};
}
const NewsList: React.FC<INewsListProps> = ({
searchParams,
}: INewsListProps) => {
const [activePage, setActivePage] = useState<number>(
+searchParams["страница-новостей"] || 1
);
const { data: news, getNews, isLoading, error } = useNewsStore();
useEffect(() => {
getNews(activePage);
}, []);
return (
<div className="flex flex-col gap-4">
<ul className="flex gap-[30px] flex-wrap mb-[96px]">
{news.results.map((news) => (
<li key={news.id}>
<NewsCard
id={news.id}
title={news.title}
content={news.content}
image={news.image}
date={news.created_at}
/>
</li>
))}
</ul>
<hr></hr>
<div className="mx-auto mb-[96px]">
<Pagination
activePage={activePage}
setActivePage={setActivePage}
prev={news.previous}
next={news.next}
count={news.count as number}
current_count={news.results.length}
limit={20}
/>
</div>
</div>
);
};
export default NewsList;

View File

@ -0,0 +1,38 @@
import { apiInstance } from "@/shared/config/apiConfig";
import { IFetch } from "@/shared/types/fetch-type";
import { INewsList } from "@/shared/types/news-type";
import { AxiosError } from "axios";
import { create } from "zustand";
interface useNewsStore extends IFetch {
data: INewsList;
getNews: (page: number) => void;
}
export const useNewsStore = create<useNewsStore>((set) => ({
data: {
count: 0,
previous: null,
next: null,
results: [],
},
error: "",
isLoading: false,
getNews: async (page: number) => {
try {
set({ isLoading: true });
const res = await apiInstance.get(`/news/`);
set({ data: res.data });
} catch (error: unknown) {
if (error instanceof AxiosError) {
set({ error: error.message });
} else {
set({ error: "An error ocured" });
}
} finally {
set({ isLoading: false });
}
},
}));