Add tender details page

This commit is contained in:
ariari04 2024-09-03 23:37:54 +06:00
parent 7eedb5ec39
commit 1d68743bc8
8 changed files with 206 additions and 21 deletions

View File

@ -0,0 +1,144 @@
import { apiInstance } from "@/shared/config/apiConfig";
import { ITenders } from "@/shared/types/tenders-type";
import { Container, Title } from "@/shared/ui";
const TenderDetails = async ({
params,
}: {
params: { id: string; новость: string };
}) => {
const getTendersById = async () => {
const response = await apiInstance.get<ITenders>(
`/procurements/${params.id}/`
);
return response.data;
};
const data = await getTendersById();
const formatNumber = (number: number | string): string => {
if (typeof number === "string") {
number = parseFloat(number);
}
if (isNaN(number)) return "";
return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, " ");
};
const months: Record<string, string> = {
"01": "Январь",
"02": "Февраль",
"03": "Март",
"04": "Апрель",
"05": "Май",
"06": "Июнь",
"07": "Июль",
"08": "Август",
"09": "Сентябрь",
"10": "Октябрь",
"11": "Ноябрь",
"12": "Декабрь",
};
return (
<Container>
<Title
text={`${data.id_of_card}`}
size="lg"
className="font-bold text-[24px] mb-[30px]"
/>
<div className="flex flex-col gap-[27px] w-full mb-[83px]">
<div className="flex gap-[108px]">
<Title
text="Наименование закупки"
className="text-[18px] text-gray-500 w-[242px]"
/>
<Title
text={data.name_of_buy}
className="text-light-blue text-[20px] leading-8 font-semibold"
/>
</div>
<div className="flex gap-[108px]">
<Title
text="Закупающая организация"
className="text-[18px] text-gray-500 w-[242px]"
/>
<Title
text={data.name_of_organization}
className="text-light-blue text-[20px] leading-8 font-semibold"
/>
</div>
<div className="flex gap-[108px]">
<Title
text="Планируемая сумма"
className="text-[18px] text-gray-500 w-[242px]"
/>
<Title
text={formatNumber(data.plan_summ)}
className="text-light-blue text-[20px] leading-8 font-semibold"
/>
</div>
<div className="flex gap-[108px]">
<Title
text="Статус"
className="text-[18px] text-gray-50 w-[242px] "
/>
<Title text={"Статус"} className=" text-[20px] leading-8" />
</div>
<div className="flex gap-[108px]">
<Title
text="Дата публикации"
className="text-[18px] text-gray-500 w-[242px]"
/>
<p className="text-[20px] leading-8">
{data.date_of_publication_datetime.slice(8, 10)}{" "}
{months[data.date_of_publication_datetime.slice(5, 7)]}{" "}
{data.date_of_publication_datetime.slice(0, 4)}
</p>
{months[data.date_of_publication_datetime.slice(0, 5)]}
</div>
<div className="flex gap-[108px]">
<Title
text="Окончание приема заявок"
className="text-[18px] text-gray-500 w-[242px]"
/>
<p className="text-[20px] leading-8">
{data.date_of_publication_datetime.slice(8, 10)}{" "}
{months[data.date_of_publication_datetime.slice(5, 7)]}{" "}
{data.date_of_publication_datetime.slice(0, 4)}
</p>
</div>
<div className="flex gap-[108px]">
<Title
text="Рабочий телефон"
className="text-[18px] text-gray-500 w-[242px]"
/>
<Title text={data.tel_number} className="text-[20px] leading-8" />
</div>
<div className="flex gap-[108px]">
<Title
text="Больше информации"
className="text-[18px] text-gray-500 w-[242px]"
/>
<Title text={data.more_info_url} className="text-[20px] leading-8" />
</div>
<div className="flex gap-[108px]">
<Title
text="Больше информации в PDF"
className="text-[18px] text-gray-500 w-[242px]"
/>
<Title text={data.more_info_pdf} className="text-[20px] leading-8" />
</div>
</div>
<Title
text={"Лоты"}
size="lg"
className="font-bold text-[24px] mb-[30px]"
/>
</Container>
);
};
export default TenderDetails;

View File

@ -2,7 +2,13 @@ import { Container, Title } from "@/shared/ui";
import TendersList from "@/widgets/TendersList/TendersList"; import TendersList from "@/widgets/TendersList/TendersList";
import React from "react"; import React from "react";
const Tenders = () => { const Tenders = ({
searchParams,
}: {
searchParams: {
["страница-тендеров"]: string;
};
}) => {
return ( return (
<div className="bg-[#FAFCFF]"> <div className="bg-[#FAFCFF]">
<Container> <Container>
@ -11,7 +17,7 @@ const Tenders = () => {
size="md" size="md"
className="text-lg font-bold mb-[39px] pt-[101px]" className="text-lg font-bold mb-[39px] pt-[101px]"
/> />
<TendersList /> <TendersList searchParams={searchParams} />
</Container> </Container>
</div> </div>
); );

View File

@ -1,3 +1,4 @@
import { Link } from "@/shared/config/navigation";
import { Title } from "@/shared/ui"; import { Title } from "@/shared/ui";
import React from "react"; import React from "react";
@ -30,9 +31,13 @@ const TenderCard: React.FC<Props> = ({
text={`${id_of_card}`} text={`${id_of_card}`}
className="font-bold text-[24px] mb-[48px]" className="font-bold text-[24px] mb-[48px]"
/> />
<h2 className="mb-6 text-[18px] font-semibold leading-6 text-blue"> <Link
{name_of_buy} href={{ pathname: `/tenders/${id}`, query: { тендер: name_of_buy } }}
</h2> >
<h2 className="mb-6 text-[18px] font-semibold leading-6 text-blue">
{name_of_buy}
</h2>
</Link>
<h2 className="text-[18px] leading-6 font-normal "> <h2 className="text-[18px] leading-6 font-normal ">
{name_of_organization} {name_of_organization}
</h2> </h2>

View File

@ -37,12 +37,12 @@
} }
&__page_active { &__page_active {
background-color: rgb(249, 250, 251) !important; background-color: rgb(236, 243, 250) !important;
} }
&__page:hover, &__page:hover,
&__prev:hover, &__prev:hover,
&__next:hover { &__next:hover {
background-color: rgb(249, 250, 251); background-color: rgb(229, 230, 230);
} }
} }

View File

@ -4,11 +4,24 @@ import Image from "next/image";
import search from "./icons/search.svg"; import search from "./icons/search.svg";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
const SearchForm = () => { interface ISearchFormProps extends React.InputHTMLAttributes<HTMLInputElement> {
handleSubmit: (e: React.MouseEvent<HTMLFormElement>) => void;
}
const SearchForm: React.FC<ISearchFormProps> = ({
handleSubmit,
name,
placeholder,
value,
onChange,
style,
}: ISearchFormProps) => {
const t = useTranslations("general"); const t = useTranslations("general");
return ( return (
<form className="mb-8 h-12 w-full relative flex items-center"> <form
className="mb-8 h-12 w-full relative flex items-center"
onSubmit={handleSubmit}
>
<div className="h-full flex flex-1 items-center border border-black rounded-sm bg-white"> <div className="h-full flex flex-1 items-center border border-black rounded-sm bg-white">
<Image <Image
className="w-12 h-12 p-2" className="w-12 h-12 p-2"
@ -16,7 +29,10 @@ const SearchForm = () => {
alt="Search button icon" alt="Search button icon"
/> />
<input <input
placeholder="Ключевое слово или номер" onChange={onChange}
value={value}
placeholder={placeholder}
name={name}
type="text" type="text"
className="px-3 pl-2 w-full h-full text-lg focus:outline-none focus:ring-2 focus:ring-blue-500" className="px-3 pl-2 w-full h-full text-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
aria-label={t("search")} aria-label={t("search")}

View File

@ -10,6 +10,10 @@ export interface ITenders {
date_of_publication_datetime: string; date_of_publication_datetime: string;
date_of_offer_datetime: string; date_of_offer_datetime: string;
current_timestamp: string; current_timestamp: string;
plan_summ: string;
tel_number: string;
more_info_url: string;
more_info_pdf: string;
} }
export interface ITendersList extends IList { export interface ITendersList extends IList {

View File

@ -1,24 +1,32 @@
"use client"; "use client";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useTendersStore } from "./tendersStore"; import { useTendersStore } from "./tendersStore";
import { data } from "autoprefixer";
import TenderCard from "@/entities/TenderCard"; import TenderCard from "@/entities/TenderCard";
import Pagination from "@/features/Pagination/Pagination"; import Pagination from "@/features/Pagination/Pagination";
import SearchForm from "@/features/SearchForm/SearchForm"; import SearchForm from "@/features/SearchForm/SearchForm";
interface Props {} interface Props {
const TendersList = () => { searchParams: {
const [activePage, setActivePage] = useState<number>(1); ["страница-тендеров"]: string;
const [ordering, setOrdering] = useState<number>(1); };
}
const TendersList: React.FC<Props> = ({ searchParams }) => {
const [activePage, setActivePage] = useState<number>(
+searchParams["страница-тендеров"] || 1
);
const { data: tenders, getTenders, isLoading, error } = useTendersStore(); const { data: tenders, getTenders, isLoading, error } = useTendersStore();
useEffect(() => { useEffect(() => {
getTenders(ordering); getTenders(activePage);
}, []); }, [activePage]);
console.log(tenders);
const handleSubmit = () => {};
return ( return (
<div> <div>
<SearchForm /> <SearchForm
placeholder="Введите ключевое слово"
handleSubmit={handleSubmit}
/>
<div className="flex flex-col gap-2 pb-[96px] items-center"> <div className="flex flex-col gap-2 pb-[96px] items-center">
{tenders?.results?.map((tender) => ( {tenders?.results?.map((tender) => (
@ -42,7 +50,7 @@ const TendersList = () => {
next={tenders.next} next={tenders.next}
count={tenders.count as number} count={tenders.count as number}
current_count={tenders.results.length} current_count={tenders.results.length}
limit={20} limit={10}
/> />
</div> </div>
</div> </div>

View File

@ -22,7 +22,9 @@ export const useTendersStore = create<useTendersStore>((set) => ({
try { try {
set({ isLoading: true }); set({ isLoading: true });
const res = await apiInstance.get(`/procurements/?ordering=${ordering}`); const res = await apiInstance.get(
`/procurements/?ordering=${ordering}/?limit=${10}/`
);
set({ data: res.data }); set({ data: res.data });
} catch (error: unknown) { } catch (error: unknown) {
if (error instanceof AxiosError) { if (error instanceof AxiosError) {