This commit is contained in:
2024-07-09 12:10:18 +04:00
parent e42777db8d
commit 1577eabcde
55 changed files with 1779 additions and 139 deletions

View File

@@ -0,0 +1,19 @@
import {
beanSchema,
beansSchema,
pageOfBeansSchema,
thisItemIsBean,
type BeanType,
type PageOfBeansType,
} from "./schema";
export {
beanSchema,
beansSchema,
pageOfBeansSchema,
thisItemIsBean,
type BeanType,
type PageOfBeansType,
};
import { BeansService } from "./service";
export { BeansService };

View File

@@ -0,0 +1,51 @@
import { z } from "zod";
import { ItemType, TypesOfItems } from "../types";
export const beanSchema = z.object({
beanId: z.number(),
groupName: z.array(z.string()),
ingredients: z.array(z.string()),
flavorName: z.string(),
description: z.string(),
colorGroup: z.string(),
backgroundColor: z.string(),
imageUrl: z.string(),
glutenFree: z.boolean(),
sugarFree: z.boolean(),
seasonal: z.boolean(),
kosher: z.boolean(),
// Показывает, что этот item - bean
type: z
.any()
.optional()
.transform(() => TypesOfItems.bean),
});
export type BeanType = z.infer<typeof beanSchema>;
export const isBean = (a: any): a is BeanType => {
return beanSchema.safeParse(a).success;
};
export const beansSchema = z.array(z.any()).transform((a) => {
const beans: BeanType[] = [];
a.forEach((e) => {
if (isBean(e)) beans.push(beanSchema.parse(e));
else console.error("Bean parse error - ", e);
});
return beans;
});
export const pageOfBeansSchema = z.object({
totalCount: z.number(),
pageSize: z.number(),
currentPage: z.number(),
totalPages: z.number(),
items: beansSchema,
});
export type PageOfBeansType = z.infer<typeof pageOfBeansSchema>;
export const thisItemIsBean = (i: ItemType): i is BeanType => {
return (i as BeanType).type === TypesOfItems.bean;
};

View File

@@ -0,0 +1,29 @@
import { HTTPService } from "@/shared/utils/http";
import { IItemService, staticImplements } from "../types";
import { beanSchema, pageOfBeansSchema } from "./schema";
@staticImplements<IItemService>()
export abstract class BeansService {
public static urlPrefix = "beans";
public static cacheOptions = {
next: {
revalidate: 60 * 5,
},
};
public static async Get(id: number) {
return await HTTPService.get(
`/${this.urlPrefix}/${id}`,
beanSchema,
this.cacheOptions
);
}
public static async GetPage(page: number, pageSize?: number) {
return await HTTPService.get(
`/${this.urlPrefix}?pageIndex=${page}&pageSize=${pageSize ?? 2 * 3 * 2}`,
pageOfBeansSchema,
this.cacheOptions
);
}
}

View File

@@ -0,0 +1,19 @@
import {
combinationSchema,
combinationsSchema,
pageOfCombinationsSchema,
thisItemIsCombination,
type CombinationType,
type PageOfCombinationsType,
} from "./schema";
export {
combinationSchema,
combinationsSchema,
pageOfCombinationsSchema,
thisItemIsCombination,
type CombinationType,
type PageOfCombinationsType,
};
import { CombinationsService } from "./service";
export { CombinationsService };

View File

@@ -0,0 +1,42 @@
import { z } from "zod";
import { ItemType, TypesOfItems } from "../types";
export const combinationSchema = z.object({
combinationId: z.number(),
name: z.string(),
tag: z.array(z.string()),
// Показывает, что этот item - combination
type: z
.any()
.optional()
.transform(() => TypesOfItems.combination),
});
export type CombinationType = z.infer<typeof combinationSchema>;
export const isCombination = (a: any): a is CombinationType => {
return combinationSchema.safeParse(a).success;
};
export const combinationsSchema = z.array(z.any()).transform((a) => {
const combinations: CombinationType[] = [];
a.forEach((e) => {
if (isCombination(e)) combinations.push(combinationSchema.parse(e));
else console.error("Combination parse error - ", e);
});
return combinations;
});
export const pageOfCombinationsSchema = z.object({
totalCount: z.number(),
pageSize: z.number(),
currentPage: z.number(),
totalPages: z.number(),
items: combinationsSchema,
});
export type PageOfCombinationsType = z.infer<typeof pageOfCombinationsSchema>;
export const thisItemIsCombination = (i: ItemType): i is CombinationType => {
return (i as CombinationType).type === TypesOfItems.combination;
};

View File

@@ -0,0 +1,29 @@
import { HTTPService } from "@/shared/utils/http";
import { IItemService, staticImplements } from "../types";
import { combinationSchema, pageOfCombinationsSchema } from "./schema";
@staticImplements<IItemService>()
export abstract class CombinationsService {
public static urlPrefix = "combinations";
public static cacheOptions = {
next: {
revalidate: 60 * 5,
},
};
public static async Get(id: number) {
return await HTTPService.get(
`/${this.urlPrefix}/${id}`,
combinationSchema,
this.cacheOptions
);
}
public static async GetPage(page: number, pageSize?: number) {
return await HTTPService.get(
`/${this.urlPrefix}?pageIndex=${page}&pageSize=${pageSize ?? 2 * 3 * 3}`,
pageOfCombinationsSchema,
this.cacheOptions
);
}
}

View File

@@ -0,0 +1,19 @@
import {
factSchema,
factsSchema,
pageOfFactsSchema,
thisItemIsFact,
type FactType,
type PageOfFactsType,
} from "./schema";
export {
factSchema,
factsSchema,
pageOfFactsSchema,
thisItemIsFact,
type FactType,
type PageOfFactsType,
};
import { FactsService } from "./service";
export { FactsService };

View File

@@ -0,0 +1,42 @@
import { z } from "zod";
import { ItemType, TypesOfItems } from "../types";
export const factSchema = z.object({
factId: z.number(),
title: z.string(),
description: z.string(),
// Показывает, что этот item - fact
type: z
.any()
.optional()
.transform(() => TypesOfItems.fact),
});
export type FactType = z.infer<typeof factSchema>;
export const isFact = (a: any): a is FactType => {
return factSchema.safeParse(a).success;
};
export const factsSchema = z.array(z.any()).transform((a) => {
const facts: FactType[] = [];
a.forEach((e) => {
if (isFact(e)) facts.push(factSchema.parse(e));
else console.error("Fact parse error - ", e);
});
return facts;
});
export const pageOfFactsSchema = z.object({
totalCount: z.number(),
pageSize: z.number(),
currentPage: z.number(),
totalPages: z.number(),
items: factsSchema,
});
export type PageOfFactsType = z.infer<typeof pageOfFactsSchema>;
export const thisItemIsFact = (i: ItemType): i is FactType => {
return (i as FactType).type === TypesOfItems.fact;
};

View File

@@ -0,0 +1,29 @@
import { HTTPService } from "@/shared/utils/http";
import { IItemService, staticImplements } from "../types";
import { factSchema, pageOfFactsSchema } from "./schema";
@staticImplements<IItemService>()
export abstract class FactsService {
public static urlPrefix = "facts";
public static cacheOptions = {
next: {
revalidate: 60 * 5,
},
};
public static async Get(id: number) {
return await HTTPService.get(
`/${this.urlPrefix}/${id}`,
factSchema,
this.cacheOptions
);
}
public static async GetPage(page: number, pageSize?: number) {
return await HTTPService.get(
`/${this.urlPrefix}?pageIndex=${page}&pageSize=${pageSize ?? 2 * 3 * 3}`,
pageOfFactsSchema,
this.cacheOptions
);
}
}

View File

@@ -0,0 +1,22 @@
import { thisItemIsBean, type BeanType } from "./beans";
export { thisItemIsBean, type BeanType };
import { thisItemIsFact, type FactType } from "./facts";
export { thisItemIsFact, type FactType };
import { thisItemIsRecipe, type RecipeType } from "./recipes";
export { thisItemIsRecipe, type RecipeType };
import { thisItemIsCombination, type CombinationType } from "./combinations";
export { thisItemIsCombination, type CombinationType };
import { ItemService } from "./item";
export { ItemService };
import {
TypesOfItems,
type IItemService,
type ItemType,
type PageOfItemsType,
} from "./types";
export { TypesOfItems, type IItemService, type ItemType, type PageOfItemsType };

49
src/entities/item/item.ts Normal file
View File

@@ -0,0 +1,49 @@
import { BeansService, thisItemIsBean } from "./beans";
import { CombinationsService, thisItemIsCombination } from "./combinations";
import { FactsService, thisItemIsFact } from "./facts";
import { MileStonesService, thisItemIsMileStone } from "./mileStones";
import { RecipesService, thisItemIsRecipe } from "./recipes";
import { IItemService, ItemType, TypesOfItems } from "./types";
export abstract class ItemService {
static get itemsConfiguration(): {
[k in TypesOfItems]: {
service: IItemService;
};
} {
return {
[TypesOfItems.bean]: {
service: BeansService,
},
[TypesOfItems.fact]: {
service: FactsService,
},
[TypesOfItems.recipe]: {
service: RecipesService,
},
[TypesOfItems.combination]: {
service: CombinationsService,
},
[TypesOfItems.mileStone]: {
service: MileStonesService,
},
};
}
public static GetTypeOfItem(i: ItemType): TypesOfItems {
if (thisItemIsBean(i)) return TypesOfItems.bean;
if (thisItemIsFact(i)) return TypesOfItems.fact;
if (thisItemIsRecipe(i)) return TypesOfItems.recipe;
if (thisItemIsCombination(i)) return TypesOfItems.combination;
if (thisItemIsMileStone(i)) return TypesOfItems.mileStone;
throw Error("unknown Item");
}
public static GetItemId(i: ItemType): number {
if (thisItemIsBean(i)) return i.beanId;
if (thisItemIsFact(i)) return i.factId;
if (thisItemIsRecipe(i)) return i.recipeId;
if (thisItemIsCombination(i)) return i.combinationId;
if (thisItemIsMileStone(i)) return i.mileStoneId;
throw Error("unknown Item");
}
}

View File

@@ -0,0 +1,19 @@
import {
mileStoneSchema,
mileStonesSchema,
pageOfMileStonesSchema,
thisItemIsMileStone,
type MileStoneType,
type PageOfMileStonesType,
} from "./schema";
export {
mileStoneSchema,
mileStonesSchema,
pageOfMileStonesSchema,
thisItemIsMileStone,
type MileStoneType,
type PageOfMileStonesType,
};
import { MileStonesService } from "./service";
export { MileStonesService };

View File

@@ -0,0 +1,42 @@
import { z } from "zod";
import { ItemType, TypesOfItems } from "../types";
export const mileStoneSchema = z.object({
mileStoneId: z.number(),
year: z.number(),
description: z.string(),
// Показывает, что этот item - mileStone
type: z
.any()
.optional()
.transform(() => TypesOfItems.mileStone),
});
export type MileStoneType = z.infer<typeof mileStoneSchema>;
export const isMileStone = (a: any): a is MileStoneType => {
return mileStoneSchema.safeParse(a).success;
};
export const mileStonesSchema = z.array(z.any()).transform((a) => {
const mileStones: MileStoneType[] = [];
a.forEach((e) => {
if (isMileStone(e)) mileStones.push(mileStoneSchema.parse(e));
else console.error("MileStone parse error - ", e);
});
return mileStones;
});
export const pageOfMileStonesSchema = z.object({
totalCount: z.number(),
pageSize: z.number(),
currentPage: z.number(),
totalPages: z.number(),
items: mileStonesSchema,
});
export type PageOfMileStonesType = z.infer<typeof pageOfMileStonesSchema>;
export const thisItemIsMileStone = (i: ItemType): i is MileStoneType => {
return (i as MileStoneType).type === TypesOfItems.mileStone;
};

View File

@@ -0,0 +1,29 @@
import { HTTPService } from "@/shared/utils/http";
import { IItemService, staticImplements } from "../types";
import { mileStoneSchema, pageOfMileStonesSchema } from "./schema";
@staticImplements<IItemService>()
export abstract class MileStonesService {
public static urlPrefix = "mileStones";
public static cacheOptions = {
next: {
revalidate: 60 * 5,
},
};
public static async Get(id: number) {
return await HTTPService.get(
`/${this.urlPrefix}/${id}`,
mileStoneSchema,
this.cacheOptions
);
}
public static async GetPage(page: number, pageSize?: number) {
return await HTTPService.get(
`/${this.urlPrefix}?pageIndex=${page}&pageSize=${pageSize ?? 2 * 3 * 3}`,
pageOfMileStonesSchema,
this.cacheOptions
);
}
}

View File

@@ -0,0 +1,19 @@
import {
recipeSchema,
recipesSchema,
pageOfRecipesSchema,
thisItemIsRecipe,
type RecipeType,
type PageOfRecipesType,
} from "./schema";
export {
recipeSchema,
recipesSchema,
pageOfRecipesSchema,
thisItemIsRecipe,
type RecipeType,
type PageOfRecipesType,
};
import { RecipesService } from "./service";
export { RecipesService };

View File

@@ -0,0 +1,53 @@
import { z } from "zod";
import { ItemType, TypesOfItems } from "../types";
export const recipeSchema = z.object({
recipeId: z.number(),
name: z.string(),
description: z.string(),
prepTime: z.string(),
cookTime: z.string(),
totalTime: z.string(),
makingAmount: z.string(),
imageUrl: z.string(),
ingredients: z.array(z.string()),
additions1: z.array(z.string()),
additions2: z.array(z.unknown()),
additions3: z.array(z.unknown()),
directions: z.array(z.string()),
tips: z.array(z.string()),
// Показывает, что этот item - recipe
type: z
.any()
.optional()
.transform(() => TypesOfItems.recipe),
});
export type RecipeType = z.infer<typeof recipeSchema>;
export const isRecipe = (a: any): a is RecipeType => {
return recipeSchema.safeParse(a).success;
};
export const recipesSchema = z.array(z.any()).transform((a) => {
const recipes: RecipeType[] = [];
a.forEach((e) => {
if (isRecipe(e)) recipes.push(recipeSchema.parse(e));
else console.error("Recipe parse error - ", e);
});
return recipes;
});
export const pageOfRecipesSchema = z.object({
totalCount: z.number(),
pageSize: z.number(),
currentPage: z.number(),
totalPages: z.number(),
items: recipesSchema,
});
export type PageOfRecipesType = z.infer<typeof pageOfRecipesSchema>;
export const thisItemIsRecipe = (i: ItemType): i is RecipeType => {
return (i as RecipeType).type === TypesOfItems.recipe;
};

View File

@@ -0,0 +1,29 @@
import { HTTPService } from "@/shared/utils/http";
import { IItemService, staticImplements } from "../types";
import { recipeSchema, pageOfRecipesSchema } from "./schema";
@staticImplements<IItemService>()
export abstract class RecipesService {
public static urlPrefix = "recipes";
public static cacheOptions = {
next: {
revalidate: 60 * 5,
},
};
public static async Get(id: number) {
return await HTTPService.get(
`/${this.urlPrefix}/${id}`,
recipeSchema,
this.cacheOptions
);
}
public static async GetPage(page: number, pageSize?: number) {
return await HTTPService.get(
`/${this.urlPrefix}?pageIndex=${page}&pageSize=${pageSize ?? 2 * 3 * 2}`,
pageOfRecipesSchema,
this.cacheOptions
);
}
}

View File

@@ -0,0 +1,37 @@
import { BeanType, PageOfBeansType } from "./beans";
import { CombinationType, PageOfCombinationsType } from "./combinations";
import { FactType, PageOfFactsType } from "./facts";
import { MileStoneType, PageOfMileStonesType } from "./mileStones";
import { PageOfRecipesType, RecipeType } from "./recipes";
export type ItemType =
| BeanType
| FactType
| RecipeType
| CombinationType
| MileStoneType;
export type PageOfItemsType =
| PageOfBeansType
| PageOfFactsType
| PageOfRecipesType
| PageOfCombinationsType
| PageOfMileStonesType;
export enum TypesOfItems {
bean,
fact,
recipe,
combination,
mileStone,
}
export interface IItemService {
urlPrefix: string;
Get(id: number): Promise<ItemType | null>;
GetPage(page: number, pageSize?: number): Promise<PageOfItemsType | null>;
}
export const staticImplements =
<T>() =>
<U extends T>(constructor: U) =>
constructor;