spoko-design-system 0.2.41 → 0.2.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +2 -0
- package/.github/dependabot.yml +11 -11
- package/.github/todo.yml +3 -3
- package/.github/workflows/deploy.yml +39 -39
- package/.stackblitzrc +5 -5
- package/.vscode/extensions.json +5 -5
- package/.vscode/launch.json +11 -11
- package/.vscode/settings.json +5 -5
- package/LICENSE +21 -21
- package/README.md +113 -113
- package/astro-i18next.config.mjs +17 -17
- package/astro-i18next.config.ts +10 -10
- package/astro.config.mjs +147 -147
- package/dev-dist/sw.js +91 -91
- package/dev-dist/workbox-c676b6d3.js +3391 -3391
- package/index.ts +58 -58
- package/package.json +1 -1
- package/public/fonts/lg.svg +53 -53
- package/public/fonts/vwhead-bold-demo.html +549 -549
- package/public/fonts/vwhead-regular-demo.html +549 -549
- package/public/fonts/vwtext-bold-demo.html +549 -549
- package/public/fonts/vwtext-regular-demo.html +549 -549
- package/public/github.svg +3 -3
- package/public/grid_dot.svg +4 -4
- package/public/linkedin.svg +44 -44
- package/public/locales/en/translation.json +8 -8
- package/public/locales/pl/translation.json +8 -8
- package/public/make-scrollable-code-focusable.js +3 -3
- package/public/pagefind.yml +3 -3
- package/public/polo.blue.svg +29 -29
- package/public/spoko.space.svg +71 -71
- package/public/twitter.svg +46 -46
- package/renovate.json +6 -6
- package/sandbox.config.json +11 -11
- package/src/MyComponent.astro +8 -8
- package/src/components/Badge.vue +19 -19
- package/src/components/Badges.vue +21 -21
- package/src/components/Breadcrumbs.vue +110 -110
- package/src/components/Button.vue +55 -55
- package/src/components/ButtonCopy.vue +47 -47
- package/src/components/Card.astro +27 -27
- package/src/components/Carousel.astro +26 -26
- package/src/components/Category/CategoriesCarousel.astro +101 -101
- package/src/components/Category/CategoriesSidebar.astro +186 -186
- package/src/components/Category/CategoryDetails.astro +82 -82
- package/src/components/Category/CategoryLink.vue +23 -23
- package/src/components/Category/CategorySection.astro +69 -69
- package/src/components/Category/CategorySidebarToggler.vue +9 -9
- package/src/components/Category/SubCategoryLink.vue +29 -29
- package/src/components/CategoryLink.astro +18 -18
- package/src/components/Copyright.astro +12 -12
- package/src/components/Date.astro +7 -7
- package/src/components/Faq.astro +33 -33
- package/src/components/FaqItem.astro +96 -96
- package/src/components/FeaturesList.vue +41 -41
- package/src/components/FuckRussia.vue +80 -80
- package/src/components/HandDrive.astro +29 -29
- package/src/components/Header/Header.astro +214 -214
- package/src/components/Header/SkipToContent.astro +1 -1
- package/src/components/Headline.vue +48 -48
- package/src/components/Image.astro +30 -30
- package/src/components/Jumbatron.vue +40 -40
- package/src/components/LeftSidebar.astro +53 -53
- package/src/components/MainColors.vue +23 -23
- package/src/components/MainInput.vue +15 -15
- package/src/components/Modal.astro +27 -27
- package/src/components/PageContent.astro +5 -5
- package/src/components/PartNumber.vue +27 -27
- package/src/components/PostHeader.astro +103 -103
- package/src/components/PrCode.vue +156 -156
- package/src/components/Product/ProductButton.vue +18 -18
- package/src/components/Product/ProductCodes.vue +167 -167
- package/src/components/Product/ProductEngineType.vue +42 -42
- package/src/components/Product/ProductImage.astro +41 -41
- package/src/components/Product/ProductLinkInfo.astro +37 -37
- package/src/components/Product/ProductNumber.astro +104 -104
- package/src/components/ProductCarousel.astro +38 -38
- package/src/components/ProductCodes.vue +39 -39
- package/src/components/ProductDetailName.vue +52 -52
- package/src/components/ProductDetailsList.vue +65 -65
- package/src/components/ProductNumber copy.astro +116 -116
- package/src/components/ProductNumber.astro +104 -104
- package/src/components/ProductTile.astro +48 -48
- package/src/components/Quote.vue +23 -23
- package/src/components/ReloadPrompt.astro +50 -50
- package/src/components/SlimBanner.vue +72 -72
- package/src/components/Table.vue +32 -32
- package/src/components/TableOfContents.astro +15 -15
- package/src/components/Translations.vue +23 -23
- package/src/components/flags/FlagPL.vue +3 -3
- package/src/components/flags/FlagUA.vue +2 -2
- package/src/components/layout/Container.astro +7 -7
- package/src/components/layout/Header.astro +80 -80
- package/src/config.ts +56 -56
- package/src/design.config.ts +81 -81
- package/src/env.d.ts +1 -1
- package/src/layouts/Layout.astro +60 -60
- package/src/layouts/MainLayout.astro +81 -81
- package/src/layouts/partials/FooterCommon.astro +4 -4
- package/src/layouts/partials/HeadCommon.astro +44 -44
- package/src/layouts/partials/HeadSEO.astro +41 -41
- package/src/pages/components/badges.mdx +57 -57
- package/src/pages/components/breadcrumbs.mdx +139 -139
- package/src/pages/components/buttons.mdx +236 -236
- package/src/pages/components/card.mdx +294 -294
- package/src/pages/components/carousel.mdx +62 -62
- package/src/pages/components/copyright.mdx +42 -42
- package/src/pages/components/details-list.mdx +115 -115
- package/src/pages/components/features-list.mdx +37 -37
- package/src/pages/components/flags.mdx +49 -49
- package/src/pages/components/fuck-russia.mdx +39 -39
- package/src/pages/components/hand-drive.mdx +38 -38
- package/src/pages/components/headline.mdx +152 -152
- package/src/pages/components/icons.astro +48 -48
- package/src/pages/components/image.mdx +513 -513
- package/src/pages/components/input.mdx +45 -45
- package/src/pages/components/jumbatron.mdx +95 -95
- package/src/pages/components/modal.mdx +64 -64
- package/src/pages/components/post-header.mdx +60 -60
- package/src/pages/components/pr-code.mdx +65 -65
- package/src/pages/components/product-number.mdx +66 -66
- package/src/pages/components/product-tile.mdx +51 -51
- package/src/pages/components/quote.mdx +33 -33
- package/src/pages/components/slimbanner.mdx +35 -35
- package/src/pages/components/table.mdx +108 -108
- package/src/pages/core/colors.mdx +10 -10
- package/src/pages/core/grid.mdx +89 -89
- package/src/pages/core/introduction.mdx +77 -77
- package/src/pages/core/shadows.astro +20 -20
- package/src/pages/core/typography.astro +47 -47
- package/src/pages/index.astro +126 -126
- package/src/pages/patterns/introduction.mdx +60 -60
- package/src/pwa.ts +12 -12
- package/src/styles/_variables.scss +70 -70
- package/src/styles/base/base.css +184 -184
- package/src/styles/base/grid.css +92 -92
- package/src/styles/base/typography.css +70 -70
- package/src/styles/content.css +73 -73
- package/src/styles/main.css +7 -7
- package/src/types/Product.ts +31 -31
- package/src/types/astro.d.ts +4 -4
- package/src/types/index.ts +237 -0
- package/src/utils/api/getCategories.ts +3 -0
- package/src/utils/category/getMainCategoryList.ts +31 -0
- package/src/utils/category/getSortedCategories.ts +11 -0
- package/src/utils/getData.ts +52 -0
- package/src/utils/product/getPriceFormatted.ts +13 -13
- package/src/utils/product/getProductChecklist.ts +15 -15
- package/src/utils/seo/getShorterDescription.ts +12 -12
- package/src/utils/text/formatDate.ts +5 -5
- package/src/utils/text/formatLocaleNumber.ts +6 -6
- package/src/utils/text/formatPad.ts +11 -11
- package/src/utils/text/getNumberFormatted.ts +32 -32
- package/src/utils/text/getTranslatedLink.ts +4 -4
- package/src/utils/text.ts +42 -42
- package/tailwind.config.cjs +8 -8
- package/tsconfig.json +28 -11
- package/uno.config.ts +256 -256
package/src/styles/content.css
CHANGED
|
@@ -1,73 +1,73 @@
|
|
|
1
|
-
.content {
|
|
2
|
-
.main-section {
|
|
3
|
-
&>h1,
|
|
4
|
-
&>h2,
|
|
5
|
-
&>h3,
|
|
6
|
-
&>h4,
|
|
7
|
-
&>h5,
|
|
8
|
-
&>h6 {
|
|
9
|
-
margin-top: 1.77rem;
|
|
10
|
-
}
|
|
11
|
-
&>h1 {
|
|
12
|
-
font-size: 22pt;
|
|
13
|
-
font-weight: 400;
|
|
14
|
-
}
|
|
15
|
-
&>h2 {
|
|
16
|
-
font-size: 17pt;
|
|
17
|
-
font-weight: 500;
|
|
18
|
-
}
|
|
19
|
-
&>h3 {
|
|
20
|
-
font-size: 15pt;
|
|
21
|
-
}
|
|
22
|
-
&>h4 {
|
|
23
|
-
font-size: 13pt;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
&>ul {
|
|
27
|
-
@apply list-disc pl-5
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
&>h1,
|
|
32
|
-
&>h2,
|
|
33
|
-
&>h3,
|
|
34
|
-
&>h4,
|
|
35
|
-
&>h5 {
|
|
36
|
-
font-weight: bold;
|
|
37
|
-
@apply font-textbold;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
code {
|
|
41
|
-
font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco,
|
|
42
|
-
Consolas, "Liberation Mono", "Courier New", monospace;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
.component-preview {
|
|
46
|
-
@apply bg-blue-600 bg-opacity-5 px-4 py-4 mx-0 flex items-center overflow-x-auto sm:(p-8);
|
|
47
|
-
gap: 1rem;
|
|
48
|
-
border-radius: 0.33rem;
|
|
49
|
-
border: 1px solid theme("colors.slate.200");
|
|
50
|
-
resize: both;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
.astro-code {
|
|
54
|
-
@apply mx-0 p-4;
|
|
55
|
-
border-radius: 0.44rem;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
table {
|
|
60
|
-
@apply table-auto text-left border bg-white shadow-md;
|
|
61
|
-
|
|
62
|
-
tr {
|
|
63
|
-
@apply border;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
td, th {
|
|
67
|
-
@apply px-4 py-2;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
thead {
|
|
71
|
-
@apply bg-gray-100;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
1
|
+
.content {
|
|
2
|
+
.main-section {
|
|
3
|
+
&>h1,
|
|
4
|
+
&>h2,
|
|
5
|
+
&>h3,
|
|
6
|
+
&>h4,
|
|
7
|
+
&>h5,
|
|
8
|
+
&>h6 {
|
|
9
|
+
margin-top: 1.77rem;
|
|
10
|
+
}
|
|
11
|
+
&>h1 {
|
|
12
|
+
font-size: 22pt;
|
|
13
|
+
font-weight: 400;
|
|
14
|
+
}
|
|
15
|
+
&>h2 {
|
|
16
|
+
font-size: 17pt;
|
|
17
|
+
font-weight: 500;
|
|
18
|
+
}
|
|
19
|
+
&>h3 {
|
|
20
|
+
font-size: 15pt;
|
|
21
|
+
}
|
|
22
|
+
&>h4 {
|
|
23
|
+
font-size: 13pt;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
&>ul {
|
|
27
|
+
@apply list-disc pl-5
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
&>h1,
|
|
32
|
+
&>h2,
|
|
33
|
+
&>h3,
|
|
34
|
+
&>h4,
|
|
35
|
+
&>h5 {
|
|
36
|
+
font-weight: bold;
|
|
37
|
+
@apply font-textbold;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
code {
|
|
41
|
+
font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco,
|
|
42
|
+
Consolas, "Liberation Mono", "Courier New", monospace;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.component-preview {
|
|
46
|
+
@apply bg-blue-600 bg-opacity-5 px-4 py-4 mx-0 flex items-center overflow-x-auto sm:(p-8);
|
|
47
|
+
gap: 1rem;
|
|
48
|
+
border-radius: 0.33rem;
|
|
49
|
+
border: 1px solid theme("colors.slate.200");
|
|
50
|
+
resize: both;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.astro-code {
|
|
54
|
+
@apply mx-0 p-4;
|
|
55
|
+
border-radius: 0.44rem;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
table {
|
|
60
|
+
@apply table-auto text-left border bg-white shadow-md;
|
|
61
|
+
|
|
62
|
+
tr {
|
|
63
|
+
@apply border;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
td, th {
|
|
67
|
+
@apply px-4 py-2;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
thead {
|
|
71
|
+
@apply bg-gray-100;
|
|
72
|
+
}
|
|
73
|
+
}
|
package/src/styles/main.css
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
/* @import "variables"; */
|
|
3
|
-
@import "base/typography";
|
|
4
|
-
@import "base/base";
|
|
5
|
-
@import "base/grid";
|
|
6
|
-
|
|
7
|
-
@import "content.css";
|
|
1
|
+
|
|
2
|
+
/* @import "variables"; */
|
|
3
|
+
@import "base/typography";
|
|
4
|
+
@import "base/base";
|
|
5
|
+
@import "base/grid";
|
|
6
|
+
|
|
7
|
+
@import "content.css";
|
package/src/types/Product.ts
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
export interface ProductImage {
|
|
2
|
-
path: string;
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
export interface BaseProduct {
|
|
6
|
-
id: string | number;
|
|
7
|
-
number: string;
|
|
8
|
-
photo: string | null;
|
|
9
|
-
price_pln?: number;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface ShopProduct extends BaseProduct {
|
|
13
|
-
images: ProductImage[];
|
|
14
|
-
slug: string;
|
|
15
|
-
name_pl: string;
|
|
16
|
-
name_en: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface CatalogProduct extends BaseProduct {
|
|
20
|
-
photo: string | null;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export type Product = ShopProduct | CatalogProduct;
|
|
24
|
-
|
|
25
|
-
export interface ProductLinkProps {
|
|
26
|
-
productId: string;
|
|
27
|
-
bigTile?: boolean;
|
|
28
|
-
locale: string;
|
|
29
|
-
index?: number | null;
|
|
30
|
-
loading?: 'lazy' | 'eager';
|
|
31
|
-
isShopProduct?: boolean;
|
|
1
|
+
export interface ProductImage {
|
|
2
|
+
path: string;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export interface BaseProduct {
|
|
6
|
+
id: string | number;
|
|
7
|
+
number: string;
|
|
8
|
+
photo: string | null;
|
|
9
|
+
price_pln?: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface ShopProduct extends BaseProduct {
|
|
13
|
+
images: ProductImage[];
|
|
14
|
+
slug: string;
|
|
15
|
+
name_pl: string;
|
|
16
|
+
name_en: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface CatalogProduct extends BaseProduct {
|
|
20
|
+
photo: string | null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type Product = ShopProduct | CatalogProduct;
|
|
24
|
+
|
|
25
|
+
export interface ProductLinkProps {
|
|
26
|
+
productId: string;
|
|
27
|
+
bigTile?: boolean;
|
|
28
|
+
locale: string;
|
|
29
|
+
index?: number | null;
|
|
30
|
+
loading?: 'lazy' | 'eager';
|
|
31
|
+
isShopProduct?: boolean;
|
|
32
32
|
}
|
package/src/types/astro.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
declare module '*.astro' {
|
|
3
|
-
const component: any;
|
|
4
|
-
export default component;
|
|
1
|
+
|
|
2
|
+
declare module '*.astro' {
|
|
3
|
+
const component: any;
|
|
4
|
+
export default component;
|
|
5
5
|
}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
|
2
|
+
|
|
3
|
+
export interface Breadcrumb {
|
|
4
|
+
name: string,
|
|
5
|
+
path: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
export interface Navigation {
|
|
10
|
+
currentIndex: number | null
|
|
11
|
+
prev: Product | null
|
|
12
|
+
next: Product | null
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ResponsiveImage {
|
|
16
|
+
media: string
|
|
17
|
+
src: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface SubCategory {
|
|
21
|
+
id: number
|
|
22
|
+
name: string
|
|
23
|
+
parent_id: number
|
|
24
|
+
title?: string
|
|
25
|
+
desc?: string
|
|
26
|
+
slug: string
|
|
27
|
+
sort: number | null
|
|
28
|
+
description?: string
|
|
29
|
+
hasProducts: boolean
|
|
30
|
+
photo?: string | null
|
|
31
|
+
children?: SubCategory[]
|
|
32
|
+
seoTitle?: string
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface Category {
|
|
36
|
+
id: number
|
|
37
|
+
parent_id: number | null
|
|
38
|
+
title?: string
|
|
39
|
+
slug: string
|
|
40
|
+
sort: number | null
|
|
41
|
+
description?: string
|
|
42
|
+
hasProducts: boolean
|
|
43
|
+
photo?: string | null
|
|
44
|
+
children: SubCategory[]
|
|
45
|
+
seoTitle?: string
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface CatObject {
|
|
49
|
+
id: number
|
|
50
|
+
name: string
|
|
51
|
+
desc: string
|
|
52
|
+
parent_id: number | null
|
|
53
|
+
title?: string
|
|
54
|
+
slug: string
|
|
55
|
+
sort?: number | null
|
|
56
|
+
description?: string
|
|
57
|
+
hasProducts: boolean
|
|
58
|
+
photo?: string | null
|
|
59
|
+
children: SubCategory[]
|
|
60
|
+
seoTitle?: string
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface CatLevels {
|
|
64
|
+
lvl1: Category|CatObject | null
|
|
65
|
+
lvl2: CatObject | null
|
|
66
|
+
lvl3: CatObject | null
|
|
67
|
+
}
|
|
68
|
+
export interface CatInfo {
|
|
69
|
+
category: CatObject | null
|
|
70
|
+
subcategory: CatObject | null
|
|
71
|
+
subsubcategory: CatObject | null
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface Replacement {
|
|
75
|
+
date: string | null
|
|
76
|
+
info: string | null
|
|
77
|
+
number: string
|
|
78
|
+
prcodes: string[] | null
|
|
79
|
+
manufacturer: string | null
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface Color {
|
|
83
|
+
id: Number
|
|
84
|
+
slug: String
|
|
85
|
+
name?: String
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface DetailList {
|
|
89
|
+
name: string
|
|
90
|
+
id: string
|
|
91
|
+
value: string | number[] | Color[]
|
|
92
|
+
translated: boolean
|
|
93
|
+
icon: boolean | null
|
|
94
|
+
isArrayValue: boolean | null
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface importantDetail {
|
|
98
|
+
name: string
|
|
99
|
+
id: string
|
|
100
|
+
value: string | number[]
|
|
101
|
+
translated: boolean
|
|
102
|
+
icon: boolean | null
|
|
103
|
+
isArrayValue: boolean | null
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface Detail {
|
|
107
|
+
name: string
|
|
108
|
+
value: string | number[]
|
|
109
|
+
translated: boolean
|
|
110
|
+
icon: boolean | null
|
|
111
|
+
isArrayValue: boolean | null
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface DetailObject {
|
|
115
|
+
importantDetails: importantDetail[]
|
|
116
|
+
list: DetailList[],
|
|
117
|
+
checklist: DetailList[]
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
export interface Image {
|
|
122
|
+
id: number
|
|
123
|
+
path: string
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export interface ImageType {
|
|
127
|
+
id: number
|
|
128
|
+
path: string
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export interface ImageApi {
|
|
132
|
+
id: number
|
|
133
|
+
slug: string
|
|
134
|
+
path: string
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export interface ImageObject {
|
|
138
|
+
id: number
|
|
139
|
+
path: string
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export interface ProductFile {
|
|
143
|
+
id: number
|
|
144
|
+
name: string
|
|
145
|
+
slug: string
|
|
146
|
+
path: string
|
|
147
|
+
type: number
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export interface Product {
|
|
151
|
+
id: number
|
|
152
|
+
number: string
|
|
153
|
+
info: string | null
|
|
154
|
+
date: string | null
|
|
155
|
+
prcodes: string[] | null
|
|
156
|
+
engines: string[] | null
|
|
157
|
+
engine_type: EngineType[] | null
|
|
158
|
+
manufacturer: string[] | null
|
|
159
|
+
manufacturer_number: string | null
|
|
160
|
+
related: string[] | null
|
|
161
|
+
color_ids: string[] | null
|
|
162
|
+
position: string[] | null
|
|
163
|
+
model: string[] | null
|
|
164
|
+
replacement: Replacement[] | null
|
|
165
|
+
details: DetailList[] | null
|
|
166
|
+
photo: string
|
|
167
|
+
files: number[] | null
|
|
168
|
+
images: Image[] | null
|
|
169
|
+
category_id: number
|
|
170
|
+
hand_drive: number | null
|
|
171
|
+
materials: MaterialsObject[] | null
|
|
172
|
+
sort: number
|
|
173
|
+
created_at: string
|
|
174
|
+
updated_at: string
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export interface MaterialsObject {
|
|
178
|
+
name: string,
|
|
179
|
+
list: Material[]
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
export interface Product2FullSearch {
|
|
184
|
+
number: string
|
|
185
|
+
category_id: number
|
|
186
|
+
photo: string
|
|
187
|
+
hand_drive: number | null
|
|
188
|
+
manufacturer: string[] | null
|
|
189
|
+
date: string | null
|
|
190
|
+
text: string
|
|
191
|
+
details: DetailList[] | null
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export interface Link {
|
|
195
|
+
path: String
|
|
196
|
+
name: String
|
|
197
|
+
}
|
|
198
|
+
export interface EngineType {
|
|
199
|
+
id: Number
|
|
200
|
+
type: String
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export interface Model {
|
|
204
|
+
id: Number
|
|
205
|
+
slug: String
|
|
206
|
+
sort: Number
|
|
207
|
+
name: String
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export interface Material {
|
|
211
|
+
id: Number
|
|
212
|
+
name: String
|
|
213
|
+
slug: String
|
|
214
|
+
sort: Number | null
|
|
215
|
+
value?: String | null
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export interface ProductImage {
|
|
219
|
+
title: string
|
|
220
|
+
alt: string
|
|
221
|
+
link: string
|
|
222
|
+
style?: string
|
|
223
|
+
__typename: string
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export interface Position {
|
|
227
|
+
id: number
|
|
228
|
+
slug: string
|
|
229
|
+
sort: number
|
|
230
|
+
name: string
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export interface Hreflang {
|
|
234
|
+
rel: 'alternate' | 'canonical'
|
|
235
|
+
href: string
|
|
236
|
+
hreflang: 'en' | 'pl' | 'x-default'
|
|
237
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { CatObject } from "@types/index";
|
|
2
|
+
|
|
3
|
+
import i18next, { t } from "i18next";
|
|
4
|
+
import { getApiCategories } from "@utils/api/getCategories";
|
|
5
|
+
import { getSortedCategories } from "@utils/category/getSortedCategories";
|
|
6
|
+
|
|
7
|
+
// Retrieve main categories:
|
|
8
|
+
export const getMainCategoryList = async (locale: string = 'en'): Promise<CatObject[]> => {
|
|
9
|
+
// Set the selected language
|
|
10
|
+
await i18next.changeLanguage(locale);
|
|
11
|
+
|
|
12
|
+
// Fetch categories from API
|
|
13
|
+
const categories = await getApiCategories();
|
|
14
|
+
|
|
15
|
+
// Map categories with translations
|
|
16
|
+
const translatedCategories = categories.map((category) => {
|
|
17
|
+
const name = t(`cat.${category.slug}.name`);
|
|
18
|
+
const desc = i18next.exists(`cat.${category.slug}.desc`)
|
|
19
|
+
? t(`cat.${category.slug}.desc`)
|
|
20
|
+
: '';
|
|
21
|
+
|
|
22
|
+
if (!desc) {
|
|
23
|
+
console.warn('No category description', category.slug, i18next.language);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return { ...category, name, desc };
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// Sort and return processed categories
|
|
30
|
+
return translatedCategories.sort(getSortedCategories);
|
|
31
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import fetch from 'node-fetch';
|
|
3
|
+
import dotenv from 'dotenv';
|
|
4
|
+
|
|
5
|
+
dotenv.config();
|
|
6
|
+
|
|
7
|
+
const API_URL = process.env.API_URL || '';
|
|
8
|
+
const CACHE_DIR = process.env.CACHE_DIR || './.cache';
|
|
9
|
+
const version = new Date().toISOString().split('T')[0]; // 'YYYY-MM-DD' daily version to refresh cache from Cloudflare
|
|
10
|
+
|
|
11
|
+
export const getData = async (type: string): Promise<any | null> => {
|
|
12
|
+
if (!API_URL) {
|
|
13
|
+
console.error("API_URL is not defined in .env");
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const cacheFilePath = `${CACHE_DIR}/${type}.json`;
|
|
18
|
+
const apiUrl = `${API_URL}${type}?version=${version}`;
|
|
19
|
+
|
|
20
|
+
// Ensure cache directory exists
|
|
21
|
+
if (!fs.existsSync(CACHE_DIR)) {
|
|
22
|
+
fs.mkdirSync(CACHE_DIR, { recursive: true });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Check if cached file exists
|
|
26
|
+
if (fs.existsSync(cacheFilePath)) {
|
|
27
|
+
try {
|
|
28
|
+
const rawData = fs.readFileSync(cacheFilePath, 'utf-8');
|
|
29
|
+
return JSON.parse(rawData);
|
|
30
|
+
} catch (error) {
|
|
31
|
+
console.error("Failed to read or parse cached data:", error);
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Fetch data from API and cache it
|
|
37
|
+
try {
|
|
38
|
+
const response = await fetch(apiUrl);
|
|
39
|
+
const jsonObject = await response.json();
|
|
40
|
+
|
|
41
|
+
if (jsonObject.success) {
|
|
42
|
+
fs.writeFileSync(cacheFilePath, JSON.stringify(jsonObject.data, null, 2));
|
|
43
|
+
return jsonObject.data;
|
|
44
|
+
} else {
|
|
45
|
+
console.warn(`API response unsuccessful for type: ${type}`);
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
} catch (error) {
|
|
49
|
+
console.error("Error fetching data from API:", error);
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import i18next from "i18next";
|
|
2
|
-
|
|
3
|
-
export const getPriceFormatted = (product: any) => {
|
|
4
|
-
if (i18next.language === 'en') {
|
|
5
|
-
return new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(product.price_eur, )
|
|
6
|
-
}
|
|
7
|
-
if (i18next.language === 'pl') {
|
|
8
|
-
return new Intl.NumberFormat('pl-PL', { style: 'currency', currency: 'PLN' }).format(product.price_pln, )
|
|
9
|
-
}
|
|
10
|
-
else {
|
|
11
|
-
return 'no price'
|
|
12
|
-
}
|
|
13
|
-
}
|
|
1
|
+
import i18next from "i18next";
|
|
2
|
+
|
|
3
|
+
export const getPriceFormatted = (product: any) => {
|
|
4
|
+
if (i18next.language === 'en') {
|
|
5
|
+
return new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(product.price_eur, )
|
|
6
|
+
}
|
|
7
|
+
if (i18next.language === 'pl') {
|
|
8
|
+
return new Intl.NumberFormat('pl-PL', { style: 'currency', currency: 'PLN' }).format(product.price_pln, )
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
return 'no price'
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
14
|
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { t } from "i18next";
|
|
2
|
-
|
|
3
|
-
export const getProductCheckList = (productDetails) => {
|
|
4
|
-
if (!productDetails || !productDetails.length) {
|
|
5
|
-
return null;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const list = productDetails.filter(item => item.icon);
|
|
9
|
-
|
|
10
|
-
if (!list.length) {
|
|
11
|
-
return null;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
return list.map(detail => t(`detail.value.${detail.value}`));
|
|
15
|
-
}
|
|
1
|
+
import { t } from "i18next";
|
|
2
|
+
|
|
3
|
+
export const getProductCheckList = (productDetails) => {
|
|
4
|
+
if (!productDetails || !productDetails.length) {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const list = productDetails.filter(item => item.icon);
|
|
9
|
+
|
|
10
|
+
if (!list.length) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return list.map(detail => t(`detail.value.${detail.value}`));
|
|
15
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
const MAX_DESCRIPTION_LENGTH = 150;
|
|
2
|
-
|
|
3
|
-
export const getShorterDescription = (description: string | null, limit = MAX_DESCRIPTION_LENGTH) => {
|
|
4
|
-
function cutString(s: string, n: number) {
|
|
5
|
-
const text = s.replace(/(\n)/g, " ");
|
|
6
|
-
const cut = text.indexOf('. ', n);
|
|
7
|
-
return cut === -1 ? text : `${text.substring(0, cut)}.`;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
return description ? cutString(description, limit) || '' : '';
|
|
11
|
-
|
|
12
|
-
}
|
|
1
|
+
const MAX_DESCRIPTION_LENGTH = 150;
|
|
2
|
+
|
|
3
|
+
export const getShorterDescription = (description: string | null, limit = MAX_DESCRIPTION_LENGTH) => {
|
|
4
|
+
function cutString(s: string, n: number) {
|
|
5
|
+
const text = s.replace(/(\n)/g, " ");
|
|
6
|
+
const cut = text.indexOf('. ', n);
|
|
7
|
+
return cut === -1 ? text : `${text.substring(0, cut)}.`;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
return description ? cutString(description, limit) || '' : '';
|
|
11
|
+
|
|
12
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
/* Format date */
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export function formatDate(date: Date ) {
|
|
5
|
-
return new Date(date);
|
|
1
|
+
/* Format date */
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export function formatDate(date: Date ) {
|
|
5
|
+
return new Date(date);
|
|
6
6
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/* Format numbers like details data: liters, measuring etc. */
|
|
2
|
-
|
|
3
|
-
import i18next from "i18next";
|
|
4
|
-
|
|
5
|
-
export function formatLocaleNumber(number: number ) {
|
|
6
|
-
return i18next.language === 'en' ? String(number).replace(/,/g, '.') : String(number);
|
|
1
|
+
/* Format numbers like details data: liters, measuring etc. */
|
|
2
|
+
|
|
3
|
+
import i18next from "i18next";
|
|
4
|
+
|
|
5
|
+
export function formatLocaleNumber(number: number ) {
|
|
6
|
+
return i18next.language === 'en' ? String(number).replace(/,/g, '.') : String(number);
|
|
7
7
|
}
|