Skip to content

Commit 6634002

Browse files
authored
Merge pull request #64 from FRedeaX/development
Обновление (offer): заменяет `api` серверным компонентом
2 parents 9d570f3 + 20a5da4 commit 6634002

File tree

24 files changed

+158
-180
lines changed

24 files changed

+158
-180
lines changed

.eslintrc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@
1010
"parser": "@typescript-eslint/parser",
1111
"plugins": ["@typescript-eslint", "prettier"],
1212
"rules": {
13+
/**
14+
* Ошибка no-void при использовании
15+
* шаблона предварительной загрузки (Next.js preload)
16+
* подробнее: https://nextjs.org/docs/app/building-your-application/data-fetching/fetching#preloading-data
17+
*/
18+
"no-void": ["error", { "allowAsStatement": true }],
1319
// ошибка no-shadow при использовании Enum
1420
"no-shadow": "off",
1521
"@typescript-eslint/no-shadow": ["error"],

app/post/[slug]/page.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { notFound } from "next/navigation";
33

44
import { getPathsToPosts, getPost } from "@/core/ssr";
55
import { RoutePost } from "@/routes/Post/Route.Post";
6+
import { preloadOffers } from "@/components/Offer/api";
67

78
type Props = {
89
params: {
@@ -50,6 +51,7 @@ export const generateMetadata = async ({
5051
const Page = async ({ params }: Props) => {
5152
const { slug } = params;
5253

54+
preloadOffers(slug);
5355
const post = await getPost({ slug });
5456

5557
if (post === null) {
@@ -58,7 +60,7 @@ const Page = async ({ params }: Props) => {
5860

5961
return (
6062
<RoutePost
61-
id={post.id}
63+
id={slug}
6264
href={post.link}
6365
title={post.title}
6466
blocks={post.blocks}

components/Offer/Offer.tsx

Lines changed: 0 additions & 41 deletions
This file was deleted.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { SearchResponseFrontend } from "@/core/elastic/type";
2+
import { PostCardItem } from "src/entities/card/Post";
3+
4+
type CardItem = PostCardItem & {
5+
id: string;
6+
};
7+
8+
export const offerAdapter = (data: SearchResponseFrontend): CardItem[] =>
9+
data.hits.hits.flatMap(({ _id, _source }) => {
10+
if (!_source) return [];
11+
12+
const { title, link, categories, departments, excerpt, thumbnail } =
13+
_source;
14+
15+
return {
16+
id: _id.toString(),
17+
title,
18+
uri: link,
19+
categories: {
20+
nodes: departments.concat(categories),
21+
},
22+
excerpt,
23+
featuredImage: thumbnail.url
24+
? {
25+
node: {
26+
sourceUrl: thumbnail.url,
27+
},
28+
}
29+
: null,
30+
};
31+
});

core/api/offers/getMinimumDataForOffer/gql/getMinimumDataForOfferGQL.ts renamed to components/Offer/api/getOffers/getMinimumDataForOffer/gql/getMinimumDataForOfferGQL.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Nullable } from "@/helpers/typings/utility-types";
44

55
export type GetMinimumDataForOfferQuery = {
66
post: Nullable<{
7+
id: string;
78
categories: {
89
nodes: {
910
name: string;
@@ -18,7 +19,8 @@ export type GetMinimumDataForOfferQuery = {
1819

1920
export const getMinimumDataForOfferDocument = gql`
2021
query GetMinimumDataForOffer($id: ID!) {
21-
post(id: $id) {
22+
post(id: $id, idType: SLUG) {
23+
id
2224
categories {
2325
nodes {
2426
name

core/api/offers/getMinimumDataForOffer/getMinimumDataForOffer.ts renamed to components/Offer/api/getOffers/getMinimumDataForOffer/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
/**
1313
* Возвращаем минимально необходимый набор данных
1414
* для последующих запросов на формирование предложения.
15-
* @param id текущей записи
15+
* @param id ярлык текущей записи
1616
*/
1717
export const getMinimumDataForOffer = async (id: string) => {
1818
const { data, error, errors } =
@@ -22,6 +22,7 @@ export const getMinimumDataForOffer = async (id: string) => {
2222
id,
2323
},
2424
});
25+
2526
if (error !== undefined) throw new ApiError(500, error.message);
2627
if (data === undefined) throw errors;
2728
const { post } = data;
@@ -32,7 +33,7 @@ export const getMinimumDataForOffer = async (id: string) => {
3233
);
3334

3435
return {
35-
notIn: id,
36+
excludedId: post.id,
3637
keywords: post.postsFields.keywords,
3738
categories: categories.nodes.map((c) => c.name).join(","),
3839
departments: departments.nodes.map((d) => d.name).join(","),
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { searchQuery } from "@/core/elastic";
2+
import { SearchParams } from "@/core/elastic/type";
3+
import { exceptionLog } from "@/helpers";
4+
5+
import { offerAdapter } from "./adapter";
6+
import { getMinimumDataForOffer } from "./getMinimumDataForOffer";
7+
8+
const fetcher = (arggs: SearchParams) => searchQuery(arggs).then(offerAdapter);
9+
10+
/** @param id ярлык текущей записи */
11+
export const getOffers = async (id: string) => {
12+
try {
13+
const { excludedId, keywords, categories, departments, lteDate } =
14+
await getMinimumDataForOffer(id);
15+
16+
const similarPostsData = keywords
17+
? fetcher({ text: keywords, lteDate, excludedId })
18+
: null;
19+
20+
const postsByCategoryData = fetcher({
21+
categories,
22+
departments,
23+
lteDate,
24+
excludedId,
25+
});
26+
27+
const [similarPosts, postsByCategory] = await Promise.all([
28+
similarPostsData,
29+
postsByCategoryData,
30+
]);
31+
32+
return { similarPosts, postsByCategory };
33+
} catch (error) {
34+
exceptionLog(error);
35+
return null;
36+
}
37+
};
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { getOffers } from "./getOffers";
2+
3+
/** @param id ярлык текущей записи */
4+
export const preloadOffers = (id: string) => {
5+
void getOffers(id);
6+
};

core/api/offers/types/index.ts renamed to components/Offer/api/getOffers/types/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { Nullable } from "@/helpers/typings/utility-types";
22

3-
import { convertData } from "../utils";
3+
import { offerAdapter } from "../adapter";
44

5-
type ConvertData = Nullable<ReturnType<typeof convertData>>;
5+
type ConvertData = Nullable<ReturnType<typeof offerAdapter>>;
66
export type ResponseOfferData = {
77
similarPosts: ConvertData;
88
postsByCategory: ConvertData;

components/Offer/api/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { getOffers } from "./getOffers/getOffers";
2+
export { preloadOffers } from "./getOffers/preloadOffers";

components/Offer/components/Tabs/Offer.Tabs.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import { Nullable } from "@/helpers/typings/utility-types";
66
import { CarouselRoot } from "@/components/Carousel/CarouselRoot";
77
import { PostCard, PostCardItem } from "src/entities/card/Post";
88

9-
import { createCategoryName } from "../../utils/createCategoryName";
10-
import { handleOnClick } from "../../utils/goal";
9+
import { createCategoryName } from "../../lib/createCategoryName";
10+
import { handleOnClick } from "../../lib/goal";
1111

1212
import {
1313
sxOfferHeader,
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
"use client";
2+
3+
import dynamic from "next/dynamic";
4+
5+
export const DynamicOfferTabs = dynamic(
6+
() => import("./Offer.Tabs").then((res) => res.OfferTabs),
7+
{ ssr: false },
8+
);

components/Offer/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { DynamicOfferTabs } from "./Tabs";

components/Offer/index.ts

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1 @@
1-
"use client";
2-
3-
import dynamic from "next/dynamic";
4-
5-
export const DynamicOffer = dynamic(
6-
() => import("./Offer").then((res) => res.Offer),
7-
{
8-
ssr: false,
9-
},
10-
);
1+
export { Offer } from "./ui";
File renamed without changes.

components/Offer/ui/index.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { getOffers } from "../api";
2+
import { DynamicOfferTabs } from "../components";
3+
4+
type OfferProps = {
5+
id: string;
6+
categories: string[];
7+
};
8+
9+
export const Offer = async ({ id, categories }: OfferProps) => {
10+
const data = await getOffers(id);
11+
12+
if (!data || !(data.similarPosts?.length || data.postsByCategory?.length))
13+
return null;
14+
15+
return (
16+
<DynamicOfferTabs
17+
categories={categories}
18+
similarPosts={data.similarPosts}
19+
postsByCategory={data.postsByCategory}
20+
/>
21+
);
22+
};

core/api/offers/index.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

core/api/offers/utils/convertData.ts

Lines changed: 0 additions & 25 deletions
This file was deleted.

core/api/offers/utils/index.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)