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.
Files changed (158) hide show
  1. package/.env.example +2 -0
  2. package/.github/dependabot.yml +11 -11
  3. package/.github/todo.yml +3 -3
  4. package/.github/workflows/deploy.yml +39 -39
  5. package/.stackblitzrc +5 -5
  6. package/.vscode/extensions.json +5 -5
  7. package/.vscode/launch.json +11 -11
  8. package/.vscode/settings.json +5 -5
  9. package/LICENSE +21 -21
  10. package/README.md +113 -113
  11. package/astro-i18next.config.mjs +17 -17
  12. package/astro-i18next.config.ts +10 -10
  13. package/astro.config.mjs +147 -147
  14. package/dev-dist/sw.js +91 -91
  15. package/dev-dist/workbox-c676b6d3.js +3391 -3391
  16. package/index.ts +58 -58
  17. package/package.json +1 -1
  18. package/public/fonts/lg.svg +53 -53
  19. package/public/fonts/vwhead-bold-demo.html +549 -549
  20. package/public/fonts/vwhead-regular-demo.html +549 -549
  21. package/public/fonts/vwtext-bold-demo.html +549 -549
  22. package/public/fonts/vwtext-regular-demo.html +549 -549
  23. package/public/github.svg +3 -3
  24. package/public/grid_dot.svg +4 -4
  25. package/public/linkedin.svg +44 -44
  26. package/public/locales/en/translation.json +8 -8
  27. package/public/locales/pl/translation.json +8 -8
  28. package/public/make-scrollable-code-focusable.js +3 -3
  29. package/public/pagefind.yml +3 -3
  30. package/public/polo.blue.svg +29 -29
  31. package/public/spoko.space.svg +71 -71
  32. package/public/twitter.svg +46 -46
  33. package/renovate.json +6 -6
  34. package/sandbox.config.json +11 -11
  35. package/src/MyComponent.astro +8 -8
  36. package/src/components/Badge.vue +19 -19
  37. package/src/components/Badges.vue +21 -21
  38. package/src/components/Breadcrumbs.vue +110 -110
  39. package/src/components/Button.vue +55 -55
  40. package/src/components/ButtonCopy.vue +47 -47
  41. package/src/components/Card.astro +27 -27
  42. package/src/components/Carousel.astro +26 -26
  43. package/src/components/Category/CategoriesCarousel.astro +101 -101
  44. package/src/components/Category/CategoriesSidebar.astro +186 -186
  45. package/src/components/Category/CategoryDetails.astro +82 -82
  46. package/src/components/Category/CategoryLink.vue +23 -23
  47. package/src/components/Category/CategorySection.astro +69 -69
  48. package/src/components/Category/CategorySidebarToggler.vue +9 -9
  49. package/src/components/Category/SubCategoryLink.vue +29 -29
  50. package/src/components/CategoryLink.astro +18 -18
  51. package/src/components/Copyright.astro +12 -12
  52. package/src/components/Date.astro +7 -7
  53. package/src/components/Faq.astro +33 -33
  54. package/src/components/FaqItem.astro +96 -96
  55. package/src/components/FeaturesList.vue +41 -41
  56. package/src/components/FuckRussia.vue +80 -80
  57. package/src/components/HandDrive.astro +29 -29
  58. package/src/components/Header/Header.astro +214 -214
  59. package/src/components/Header/SkipToContent.astro +1 -1
  60. package/src/components/Headline.vue +48 -48
  61. package/src/components/Image.astro +30 -30
  62. package/src/components/Jumbatron.vue +40 -40
  63. package/src/components/LeftSidebar.astro +53 -53
  64. package/src/components/MainColors.vue +23 -23
  65. package/src/components/MainInput.vue +15 -15
  66. package/src/components/Modal.astro +27 -27
  67. package/src/components/PageContent.astro +5 -5
  68. package/src/components/PartNumber.vue +27 -27
  69. package/src/components/PostHeader.astro +103 -103
  70. package/src/components/PrCode.vue +156 -156
  71. package/src/components/Product/ProductButton.vue +18 -18
  72. package/src/components/Product/ProductCodes.vue +167 -167
  73. package/src/components/Product/ProductEngineType.vue +42 -42
  74. package/src/components/Product/ProductImage.astro +41 -41
  75. package/src/components/Product/ProductLinkInfo.astro +37 -37
  76. package/src/components/Product/ProductNumber.astro +104 -104
  77. package/src/components/ProductCarousel.astro +38 -38
  78. package/src/components/ProductCodes.vue +39 -39
  79. package/src/components/ProductDetailName.vue +52 -52
  80. package/src/components/ProductDetailsList.vue +65 -65
  81. package/src/components/ProductNumber copy.astro +116 -116
  82. package/src/components/ProductNumber.astro +104 -104
  83. package/src/components/ProductTile.astro +48 -48
  84. package/src/components/Quote.vue +23 -23
  85. package/src/components/ReloadPrompt.astro +50 -50
  86. package/src/components/SlimBanner.vue +72 -72
  87. package/src/components/Table.vue +32 -32
  88. package/src/components/TableOfContents.astro +15 -15
  89. package/src/components/Translations.vue +23 -23
  90. package/src/components/flags/FlagPL.vue +3 -3
  91. package/src/components/flags/FlagUA.vue +2 -2
  92. package/src/components/layout/Container.astro +7 -7
  93. package/src/components/layout/Header.astro +80 -80
  94. package/src/config.ts +56 -56
  95. package/src/design.config.ts +81 -81
  96. package/src/env.d.ts +1 -1
  97. package/src/layouts/Layout.astro +60 -60
  98. package/src/layouts/MainLayout.astro +81 -81
  99. package/src/layouts/partials/FooterCommon.astro +4 -4
  100. package/src/layouts/partials/HeadCommon.astro +44 -44
  101. package/src/layouts/partials/HeadSEO.astro +41 -41
  102. package/src/pages/components/badges.mdx +57 -57
  103. package/src/pages/components/breadcrumbs.mdx +139 -139
  104. package/src/pages/components/buttons.mdx +236 -236
  105. package/src/pages/components/card.mdx +294 -294
  106. package/src/pages/components/carousel.mdx +62 -62
  107. package/src/pages/components/copyright.mdx +42 -42
  108. package/src/pages/components/details-list.mdx +115 -115
  109. package/src/pages/components/features-list.mdx +37 -37
  110. package/src/pages/components/flags.mdx +49 -49
  111. package/src/pages/components/fuck-russia.mdx +39 -39
  112. package/src/pages/components/hand-drive.mdx +38 -38
  113. package/src/pages/components/headline.mdx +152 -152
  114. package/src/pages/components/icons.astro +48 -48
  115. package/src/pages/components/image.mdx +513 -513
  116. package/src/pages/components/input.mdx +45 -45
  117. package/src/pages/components/jumbatron.mdx +95 -95
  118. package/src/pages/components/modal.mdx +64 -64
  119. package/src/pages/components/post-header.mdx +60 -60
  120. package/src/pages/components/pr-code.mdx +65 -65
  121. package/src/pages/components/product-number.mdx +66 -66
  122. package/src/pages/components/product-tile.mdx +51 -51
  123. package/src/pages/components/quote.mdx +33 -33
  124. package/src/pages/components/slimbanner.mdx +35 -35
  125. package/src/pages/components/table.mdx +108 -108
  126. package/src/pages/core/colors.mdx +10 -10
  127. package/src/pages/core/grid.mdx +89 -89
  128. package/src/pages/core/introduction.mdx +77 -77
  129. package/src/pages/core/shadows.astro +20 -20
  130. package/src/pages/core/typography.astro +47 -47
  131. package/src/pages/index.astro +126 -126
  132. package/src/pages/patterns/introduction.mdx +60 -60
  133. package/src/pwa.ts +12 -12
  134. package/src/styles/_variables.scss +70 -70
  135. package/src/styles/base/base.css +184 -184
  136. package/src/styles/base/grid.css +92 -92
  137. package/src/styles/base/typography.css +70 -70
  138. package/src/styles/content.css +73 -73
  139. package/src/styles/main.css +7 -7
  140. package/src/types/Product.ts +31 -31
  141. package/src/types/astro.d.ts +4 -4
  142. package/src/types/index.ts +237 -0
  143. package/src/utils/api/getCategories.ts +3 -0
  144. package/src/utils/category/getMainCategoryList.ts +31 -0
  145. package/src/utils/category/getSortedCategories.ts +11 -0
  146. package/src/utils/getData.ts +52 -0
  147. package/src/utils/product/getPriceFormatted.ts +13 -13
  148. package/src/utils/product/getProductChecklist.ts +15 -15
  149. package/src/utils/seo/getShorterDescription.ts +12 -12
  150. package/src/utils/text/formatDate.ts +5 -5
  151. package/src/utils/text/formatLocaleNumber.ts +6 -6
  152. package/src/utils/text/formatPad.ts +11 -11
  153. package/src/utils/text/getNumberFormatted.ts +32 -32
  154. package/src/utils/text/getTranslatedLink.ts +4 -4
  155. package/src/utils/text.ts +42 -42
  156. package/tailwind.config.cjs +8 -8
  157. package/tsconfig.json +28 -11
  158. package/uno.config.ts +256 -256
@@ -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
+ }
@@ -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";
@@ -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
  }
@@ -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,3 @@
1
+ import { getData } from "@utils/getData"
2
+
3
+ export const getApiCategories = await getData('categories')
@@ -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,11 @@
1
+ import type { CatObject, SubCategory } from "@types/index";
2
+
3
+
4
+ // compareFn
5
+ export const getSortedCategories = (a: CatObject|SubCategory, b: CatObject|SubCategory) => {
6
+ if (a.sort && b.sort)
7
+ return (a.sort - b.sort)
8
+
9
+ else
10
+ return 0
11
+ }
@@ -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
  }