droplinked-editor-configs 1.8.4 → 1.8.6
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/dist/apis/blogs/interfaces.d.ts +0 -38
- package/dist/apis/blogs/services.d.ts +1 -6
- package/dist/apis/product/interface.d.ts +12 -100
- package/dist/apis/product/services.d.ts +1 -6
- package/dist/apis/shop/interface.d.ts +0 -3
- package/dist/apis/shop/service.d.ts +1 -2
- package/dist/droplinked-editor.es.js +16 -16
- package/dist/droplinked-editor.umd.js +4 -4
- package/dist/lib/stores/productQueryStore/productQueryStore.d.ts +2 -2
- package/package.json +2 -2
- package/src/apis/blogs/interfaces.ts +0 -39
- package/src/apis/blogs/services.ts +2 -5
- package/src/apis/product/interface.ts +14 -291
- package/src/apis/product/services.ts +2 -33
- package/src/apis/shop/interface.ts +0 -4
- package/src/apis/shop/service.ts +3 -7
- package/src/components/productGrid/components/ControlBar/sort/SortDropdown.tsx +1 -1
- package/src/components/productGrid/components/ControlBar/sort/SortOptionButton.tsx +1 -1
- package/src/components/productGrid/components/FilterPanel/TypeFilter.tsx +2 -2
- package/src/components/productGrid/components/ProductGrid/GridViewProductCard.tsx +2 -2
- package/src/components/productGrid/components/ProductGrid/ListViewProductCard.tsx +4 -4
- package/src/components/productGrid/components/ProductGrid/ProductGrid.tsx +2 -2
- package/src/components/productGrid/components/ProductGrid/Slider/ProductImageSlider.tsx +4 -4
- package/src/components/productGrid/hooks/useSortHandler.ts +2 -2
- package/src/lib/stores/productQueryStore/productQueryStore.ts +4 -4
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/lib/models/product.d.ts +0 -97
- package/src/lib/models/product.ts +0 -104
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "droplinked-editor-configs",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.8.
|
|
4
|
+
"version": "1.8.6",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/droplinked-editor.umd.js",
|
|
7
7
|
"module": "dist/droplinked-editor.es.js",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"classnames": "^2.5.1",
|
|
35
35
|
"clsx": "^2.1.1",
|
|
36
36
|
"cmdk": "^1.1.1",
|
|
37
|
-
"droplinked-editor-core": "^1.1.
|
|
37
|
+
"droplinked-editor-core": "^1.1.8",
|
|
38
38
|
"framer-motion": "^8.5.0",
|
|
39
39
|
"keen-slider": "^6.8.6",
|
|
40
40
|
"lucide-react": "^0.525.0",
|
|
@@ -10,45 +10,6 @@ export interface BlogPost {
|
|
|
10
10
|
slug: string;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export interface IBlogContent {
|
|
14
|
-
_id: string;
|
|
15
|
-
shopID: string;
|
|
16
|
-
author: string;
|
|
17
|
-
content: string;
|
|
18
|
-
title: string;
|
|
19
|
-
writer: string;
|
|
20
|
-
isVisible: boolean;
|
|
21
|
-
category: string[];
|
|
22
|
-
tags: string[];
|
|
23
|
-
commentsCount: number;
|
|
24
|
-
image: string;
|
|
25
|
-
likes: number;
|
|
26
|
-
readTime: number;
|
|
27
|
-
version: number;
|
|
28
|
-
isFeatured: boolean;
|
|
29
|
-
seoData: {
|
|
30
|
-
metaDescription: string;
|
|
31
|
-
keywords: string[];
|
|
32
|
-
slug: string;
|
|
33
|
-
canonicalUrl: string;
|
|
34
|
-
ogTitle: string;
|
|
35
|
-
ogDescription: string;
|
|
36
|
-
ogImage: string;
|
|
37
|
-
structuredData: string;
|
|
38
|
-
_id: string;
|
|
39
|
-
},
|
|
40
|
-
mediaData: {
|
|
41
|
-
url: string;
|
|
42
|
-
title: string;
|
|
43
|
-
positionIndex: number;
|
|
44
|
-
_id: string;
|
|
45
|
-
}[],
|
|
46
|
-
publishedDate: string;
|
|
47
|
-
createdAt: string;
|
|
48
|
-
updatedAt: Date;
|
|
49
|
-
__v: number;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
13
|
export interface Blog {
|
|
53
14
|
featured: BlogPost[];
|
|
54
15
|
recent: BlogPost[];
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import axiosInstance from "apis/axiosConfig"
|
|
2
|
-
import { Blog
|
|
2
|
+
import { Blog } from "./interfaces"
|
|
3
3
|
|
|
4
4
|
export const getShopBlogsService = (shopName: string) =>
|
|
5
|
-
axiosInstance.get<{ data: Blog }>(`blogs/public/shops/${shopName}`).then(res => res.data)
|
|
6
|
-
|
|
7
|
-
export const getBlogByIdService = ({ slug }: { slug: string }) =>
|
|
8
|
-
axiosInstance.get<{ data: IBlogContent }>(`blogs/public/${slug}`).then(res => res.data)
|
|
5
|
+
axiosInstance.get<{ data: Blog }>(`blogs/public/shops/${shopName}`).then(res => res.data)
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { IRuleSetID, IMedia as Media } from "lib/models/product";
|
|
2
1
|
import { ProductQuery } from "lib/stores/productQueryStore/productQueryStore";
|
|
3
2
|
|
|
4
3
|
export interface IGetProductsRequest extends ProductQuery {
|
|
@@ -8,296 +7,20 @@ export interface IGetProductsRequest extends ProductQuery {
|
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
export interface IHomePageProduct {
|
|
11
|
-
|
|
10
|
+
id: string;
|
|
12
11
|
title: string;
|
|
13
12
|
slug: string;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
type: string;
|
|
14
|
+
status: string;
|
|
15
|
+
images: {
|
|
16
|
+
original: string;
|
|
17
|
+
thumbnail: string;
|
|
18
|
+
alt: string;
|
|
19
|
+
}[];
|
|
20
|
+
isPurchasable: boolean;
|
|
21
|
+
lowestPrice: number;
|
|
22
|
+
collectionName: string;
|
|
18
23
|
discountRuleset: boolean;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
shopname: string;
|
|
23
|
-
productID: string;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export interface IGetProductBySlugService {
|
|
27
|
-
shopname: string;
|
|
28
|
-
slug: string;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface IGetProductByLinkId {
|
|
32
|
-
linkId: string;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Interface for media objects in the product's media array
|
|
36
|
-
interface IMedia {
|
|
37
|
-
isMain: boolean; // Indicates whether this media is the main image
|
|
38
|
-
thumbnail: string; // URL of the thumbnail image
|
|
39
|
-
url: string; // URL of the main image
|
|
40
|
-
_id: string; // Unique identifier for the media object
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Interface for the product collection object
|
|
44
|
-
interface IProductCollection {
|
|
45
|
-
title: string; // Title of the product collection
|
|
46
|
-
ruleSetID?: IRuleSetID
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Interface for the optional ruleset object (not required)
|
|
50
|
-
interface IRuleSet {
|
|
51
|
-
gated?: boolean; // Optional gated flag
|
|
52
|
-
redeemedNFTs?: any; // Optional redeemed NFTs field
|
|
53
|
-
rules?: any; // Optional rules field
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Interface for option objects inside each SKU
|
|
57
|
-
export interface IOption {
|
|
58
|
-
variantName: string; // Name of the variant (e.g., color, size)
|
|
59
|
-
value: string; // Value of the variant (e.g., red, large)
|
|
60
|
-
caption: string; // Caption for the option (additional description)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Interface for SKU objects in the skuIDs array
|
|
64
|
-
export interface ISku {
|
|
65
|
-
_id: string; // Unique identifier for the SKU
|
|
66
|
-
price: number; // Price of the SKU
|
|
67
|
-
quantity: number; // Quantity available for the SKU
|
|
68
|
-
image?: string; // Optional image URL for the SKU
|
|
69
|
-
weight: number; // Weight of the SKU
|
|
70
|
-
|
|
71
|
-
dimensions: { // Dimensions of the SKU
|
|
72
|
-
height: number;
|
|
73
|
-
length: number;
|
|
74
|
-
width: number;
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
options?: IOption[]; // Optional options array (for NON-DIGITAL products)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Main interface for the product object
|
|
81
|
-
export interface IProduct {
|
|
82
|
-
// Ensured this is exported
|
|
83
|
-
description: string; // Mandatory description of the product
|
|
84
|
-
media: IMedia[]; // Mandatory media array containing images and videos
|
|
85
|
-
productCollectionID: IProductCollection; // Object containing the product collection details
|
|
86
|
-
ruleSet?: IRuleSet; // Optional ruleSet object (could be undefined)
|
|
87
|
-
slug: string | null; // Mandatory slug (URL-friendly identifier for the product)
|
|
88
|
-
title: string; // Mandatory title of the product
|
|
89
|
-
_id: string | null; // Mandatory unique identifier for the product
|
|
90
|
-
ownerID: string | null; // Mandatory unique identifier for the owner of the product
|
|
91
|
-
product_type: "NORMAL" | "PRINT_ON_DEMAND" | "DIGITAL"; // Type of the product (one of three types)
|
|
92
|
-
skuIDs: ISku[]; // Mandatory SKU array, must contain at least one SKU
|
|
93
|
-
launchDate?: string;
|
|
94
|
-
purchaseAvailable: boolean;
|
|
95
|
-
pod_blank_product_id: string;
|
|
96
|
-
// Optional nftData object containing blockchain-related information
|
|
97
|
-
nftData?: INftData;
|
|
98
|
-
m2m_positions: IM2MPosition[];
|
|
99
|
-
m2m_services: IM2MService[];
|
|
100
|
-
shippingType: string;
|
|
101
|
-
}
|
|
102
|
-
export interface IM2MPosition {
|
|
103
|
-
placement: string
|
|
104
|
-
variantIDs: number[]
|
|
105
|
-
url: string
|
|
106
|
-
}
|
|
107
|
-
export interface IM2MService {
|
|
108
|
-
_id: string;
|
|
109
|
-
name: string;
|
|
110
|
-
chain: string;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export interface INftData {
|
|
114
|
-
deployHash: string;
|
|
115
|
-
transactionUrl: string;
|
|
116
|
-
networkName: string;
|
|
117
|
-
}
|
|
118
|
-
export interface IShippingAvailbilityData {
|
|
119
|
-
statusCode: number;
|
|
120
|
-
message: string | null;
|
|
121
|
-
data: string[];
|
|
122
|
-
}
|
|
123
|
-
// Function to convert raw product data into the IProduct model
|
|
124
|
-
export const convertProductDataToModel = (data: any): IProduct => {
|
|
125
|
-
try {
|
|
126
|
-
// Default SKU in case the SKU data is missing or incomplete
|
|
127
|
-
const defaultSku: ISku = {
|
|
128
|
-
price: 0,
|
|
129
|
-
quantity: 0,
|
|
130
|
-
_id: "unknown_sku_id",
|
|
131
|
-
weight: 0,
|
|
132
|
-
dimensions: {
|
|
133
|
-
height: 0,
|
|
134
|
-
length: 0,
|
|
135
|
-
width: 0,
|
|
136
|
-
},
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
// Default option for SKUs in NON-DIGITAL products
|
|
141
|
-
const defaultOption: IOption = {
|
|
142
|
-
variantName: "default_variant",
|
|
143
|
-
value: "default_value",
|
|
144
|
-
caption: " ",
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
// Default media object in case media array is missing or incomplete
|
|
148
|
-
const defaultMedia: IMedia = {
|
|
149
|
-
isMain: false,
|
|
150
|
-
thumbnail: "default_thumbnail.jpg",
|
|
151
|
-
url: "default_url.jpg",
|
|
152
|
-
_id: "default_media_id",
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
// Construct the product object, falling back to default values when necessary
|
|
156
|
-
const product: IProduct = {
|
|
157
|
-
description: data?.description || "No description available",
|
|
158
|
-
media:
|
|
159
|
-
Array.isArray(data?.media) && data?.media.length > 0
|
|
160
|
-
? data.media.map((mediaItem: any) => ({
|
|
161
|
-
isMain:
|
|
162
|
-
mediaItem?.isMain === "true" || mediaItem?.isMain === true,
|
|
163
|
-
thumbnail: mediaItem?.thumbnail || "",
|
|
164
|
-
url: mediaItem?.url || "",
|
|
165
|
-
_id: mediaItem?._id || "",
|
|
166
|
-
}))
|
|
167
|
-
: [defaultMedia],
|
|
168
|
-
|
|
169
|
-
productCollectionID: {
|
|
170
|
-
title: data?.productCollectionID?.title || "",
|
|
171
|
-
ruleSetID: {
|
|
172
|
-
collectionID: data?.productCollectionID?.ruleSetID?.collectionID || "",
|
|
173
|
-
createdAt: data?.productCollectionID?.ruleSetID?.createdAt || "",
|
|
174
|
-
type: data?.productCollectionID?.ruleSetID?.type || "",
|
|
175
|
-
ownerID: data?.productCollectionID?.ruleSetID?.ownerID || "",
|
|
176
|
-
_id: data?.productCollectionID?.ruleSetID?._id || "",
|
|
177
|
-
blockchainType: data?.productCollectionID?.ruleSetID?.blockchainType || "",
|
|
178
|
-
description: data?.productCollectionID?.ruleSetID?.description || "",
|
|
179
|
-
discountPercentage: data?.productCollectionID?.ruleSetID?.discountPercentage || "",
|
|
180
|
-
minimumNftRequired: data?.productCollectionID?.ruleSetID?.minimumNftRequired || "",
|
|
181
|
-
network: data?.productCollectionID?.ruleSetID?.network || "",
|
|
182
|
-
nftContractAddresses: data?.productCollectionID?.ruleSetID?.nftContractAddresses || "",
|
|
183
|
-
nftPurchaseLink: data?.productCollectionID?.ruleSetID?.nftPurchaseLink || "",
|
|
184
|
-
}
|
|
185
|
-
},
|
|
186
|
-
purchaseAvailable: data.purchaseAvailable,
|
|
187
|
-
slug: data?.slug || null,
|
|
188
|
-
title: data?.title || "",
|
|
189
|
-
_id: data?._id || null,
|
|
190
|
-
ownerID: data?.ownerID || null,
|
|
191
|
-
product_type: data?.product_type || "NORMAL",
|
|
192
|
-
launchDate: data?.launchDate,
|
|
193
|
-
pod_blank_product_id: data.pod_blank_product_id,
|
|
194
|
-
shippingType: data.shippingType,
|
|
195
|
-
skuIDs:
|
|
196
|
-
Array.isArray(data?.skuIDs) && data?.skuIDs.length > 0
|
|
197
|
-
? data.skuIDs.map((sku: any) => ({
|
|
198
|
-
price: typeof sku?.price === "number" ? sku.price : 0,
|
|
199
|
-
quantity: typeof sku?.quantity === "number" ? sku.quantity : 0,
|
|
200
|
-
_id: sku?._id || "unknown_sku_id",
|
|
201
|
-
options:
|
|
202
|
-
data?.product_type !== "DIGITAL" &&
|
|
203
|
-
Array.isArray(sku?.options) &&
|
|
204
|
-
sku.options.length > 0
|
|
205
|
-
? sku.options.map((option: any) => ({
|
|
206
|
-
variantName: option?.variantName || "default_variant",
|
|
207
|
-
value: option?.value || "default_value",
|
|
208
|
-
caption: option?.caption || " ",
|
|
209
|
-
}))
|
|
210
|
-
: undefined,
|
|
211
|
-
image: sku.image,
|
|
212
|
-
weight: sku.weight,
|
|
213
|
-
dimensions: {
|
|
214
|
-
height: sku.dimensions.height,
|
|
215
|
-
length: sku.dimensions.length,
|
|
216
|
-
width: sku.dimensions.width,
|
|
217
|
-
},
|
|
218
|
-
}))
|
|
219
|
-
: [defaultSku],
|
|
220
|
-
|
|
221
|
-
// Adding nftData
|
|
222
|
-
nftData: data?.nftData
|
|
223
|
-
? {
|
|
224
|
-
deployHash: data.nftData.deployHash,
|
|
225
|
-
transactionUrl: data.nftData.transactionUrl,
|
|
226
|
-
networkName: data.nftData.networkName,
|
|
227
|
-
}
|
|
228
|
-
: undefined,
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
m2m_positions:
|
|
232
|
-
Array.isArray(data?.m2m_positions) && data?.m2m_positions.length > 0
|
|
233
|
-
? data.m2m_positions.map((position: any) => ({
|
|
234
|
-
placement: position.placement || "",
|
|
235
|
-
variantIDs: position.variant_ids || "",
|
|
236
|
-
url: position.url || ""
|
|
237
|
-
}))
|
|
238
|
-
: [],
|
|
239
|
-
|
|
240
|
-
m2m_services:
|
|
241
|
-
Array.isArray(data?.m2m_services) && data?.m2m_services.length > 0
|
|
242
|
-
? data.m2m_services.map((service: any) => ({
|
|
243
|
-
_id: service?._id || "",
|
|
244
|
-
name: service?.name || "Unnamed Service",
|
|
245
|
-
chain: service?.chain || "Unknown Chain",
|
|
246
|
-
}))
|
|
247
|
-
: [],
|
|
248
|
-
};
|
|
249
|
-
|
|
250
|
-
return product;
|
|
251
|
-
} catch (error) {
|
|
252
|
-
console.error("Error converting product data:", error);
|
|
253
|
-
|
|
254
|
-
// If an error occurs, return a product object with default values
|
|
255
|
-
return {
|
|
256
|
-
description: "No description available",
|
|
257
|
-
purchaseAvailable: data?.purchaseAvailable,
|
|
258
|
-
media: [
|
|
259
|
-
{
|
|
260
|
-
isMain: false,
|
|
261
|
-
thumbnail: "default_thumbnail.jpg",
|
|
262
|
-
url: "default_url.jpg",
|
|
263
|
-
_id: "default_media_id",
|
|
264
|
-
},
|
|
265
|
-
],
|
|
266
|
-
productCollectionID: { title: "Default Collection" },
|
|
267
|
-
slug: null,
|
|
268
|
-
title: "",
|
|
269
|
-
_id: null,
|
|
270
|
-
ownerID: null,
|
|
271
|
-
product_type: "NORMAL",
|
|
272
|
-
pod_blank_product_id: "",
|
|
273
|
-
skuIDs: [
|
|
274
|
-
{
|
|
275
|
-
price: 0,
|
|
276
|
-
quantity: 0,
|
|
277
|
-
_id: "unknown_sku_id",
|
|
278
|
-
weight: 0,
|
|
279
|
-
dimensions: {
|
|
280
|
-
height: 0,
|
|
281
|
-
length: 0,
|
|
282
|
-
width: 0,
|
|
283
|
-
},
|
|
284
|
-
},
|
|
285
|
-
],
|
|
286
|
-
nftData: undefined,
|
|
287
|
-
m2m_positions: [],
|
|
288
|
-
m2m_services: [],
|
|
289
|
-
shippingType: ""
|
|
290
|
-
};
|
|
291
|
-
}
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
export interface ISemanticSearchParams {
|
|
295
|
-
query: string;
|
|
296
|
-
limit?: number;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
export interface NftImagesData {
|
|
300
|
-
nfts: string[];
|
|
301
|
-
domains: string[];
|
|
302
|
-
}
|
|
303
|
-
|
|
24
|
+
gatedRuleset: boolean;
|
|
25
|
+
nftRecording: any;
|
|
26
|
+
}
|
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
import axiosInstance from "apis/axiosConfig";
|
|
2
2
|
import { createQueryString } from "lib/utils/app/createQueryString";
|
|
3
3
|
import {
|
|
4
|
-
convertProductDataToModel,
|
|
5
|
-
IGetProductByLinkId,
|
|
6
|
-
IGetProductBySlugService,
|
|
7
|
-
IgetProductPublicService,
|
|
8
4
|
IGetProductsRequest,
|
|
9
|
-
IProduct,
|
|
10
|
-
ISemanticSearchParams,
|
|
11
|
-
IShippingAvailbilityData
|
|
12
5
|
} from "./interface";
|
|
13
6
|
|
|
14
7
|
export const getProductsService = (params: IGetProductsRequest) => {
|
|
@@ -19,30 +12,6 @@ export const getProductsService = (params: IGetProductsRequest) => {
|
|
|
19
12
|
}).toString()
|
|
20
13
|
|
|
21
14
|
return axiosInstance
|
|
22
|
-
.get(
|
|
15
|
+
.get(`/product-v2/public/shop/${params.shopName}?${queryString}`)
|
|
23
16
|
.then((res) => res.data)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export const getProductPublicService = ({ productID, shopname }: IgetProductPublicService) => {
|
|
27
|
-
return axiosInstance.get<{ data: IProduct }>(`product/public/${productID}?shopname=${shopname}`).then((res) => convertProductDataToModel(res.data.data));
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export const getProductBySlugService = ({ slug, shopname }: IGetProductBySlugService) => axiosInstance.get(`product/public/${slug}?shopname=${shopname}`);
|
|
31
|
-
|
|
32
|
-
export const getProductByLinkId = ({ linkId }: IGetProductByLinkId) => axiosInstance.get(`/product/link/${linkId}`);
|
|
33
|
-
|
|
34
|
-
export const getShippingAvailability = async (productId: string): Promise<IShippingAvailbilityData> => {
|
|
35
|
-
try {
|
|
36
|
-
const response = await axiosInstance.post<IShippingAvailbilityData>("/product/printful-available-shipping", {
|
|
37
|
-
product_id: productId,
|
|
38
|
-
});
|
|
39
|
-
return response.data;
|
|
40
|
-
} catch (error) {
|
|
41
|
-
console.error("Error fetching shipping availability:", error);
|
|
42
|
-
throw new Error("Failed to fetch shipping availability");
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export const semanticSearchService = ({ query, limit = 10 }: ISemanticSearchParams) => {
|
|
47
|
-
return axiosInstance.get(`/product/search/semantic${query && query !== "" ? `?query=${query}` : ""}&limit=${limit}`);
|
|
48
|
-
};
|
|
17
|
+
}
|
package/src/apis/shop/service.ts
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import axiosInstance from "apis/axiosConfig"
|
|
2
|
-
import { IgetShopService,
|
|
3
|
-
|
|
4
|
-
export const shopDomainService = ({ domain }: IshopDomainService) => {
|
|
5
|
-
return axiosInstance.get(`shop/domain/${domain}`)
|
|
6
|
-
}
|
|
2
|
+
import { IgetShopService, ProductFiltersResponse } from "./interface"
|
|
7
3
|
|
|
8
4
|
export const getShopService = ({ shopName }: IgetShopService) => {
|
|
9
|
-
return axiosInstance.get(
|
|
5
|
+
return axiosInstance.get(`/shops/v2/public/name/${shopName}`)
|
|
10
6
|
}
|
|
11
7
|
|
|
12
8
|
export const getAvailableProductFilters = (shopName: string) =>
|
|
13
|
-
axiosInstance.get<{ data: ProductFiltersResponse }>(
|
|
9
|
+
axiosInstance.get<{ data: ProductFiltersResponse }>(`/product-v2/available/filters/${shopName}`).then(res => res.data)
|
|
@@ -9,7 +9,7 @@ import Text from 'components/ui/Text';
|
|
|
9
9
|
function SortDropdown() {
|
|
10
10
|
const { isDarkTheme } = useThemeInfo();
|
|
11
11
|
const { stagedSortOption, stagedSortOrder } = useProductQueryStore((state) => ({
|
|
12
|
-
stagedSortOption: state.stagedProductQuery.
|
|
12
|
+
stagedSortOption: state.stagedProductQuery.sortBy,
|
|
13
13
|
stagedSortOrder: state.stagedProductQuery.order
|
|
14
14
|
}));
|
|
15
15
|
|
|
@@ -5,7 +5,7 @@ import useProductQueryStore from "lib/stores/productQueryStore/productQueryStore
|
|
|
5
5
|
|
|
6
6
|
function SortOptionButton({ option }: { option: SortOption }) {
|
|
7
7
|
const { stagedSortOption, stagedSortOrder } = useProductQueryStore((state) => ({
|
|
8
|
-
stagedSortOption: state.stagedProductQuery.
|
|
8
|
+
stagedSortOption: state.stagedProductQuery.sortBy,
|
|
9
9
|
stagedSortOrder: state.stagedProductQuery.order,
|
|
10
10
|
}))
|
|
11
11
|
|
|
@@ -5,7 +5,7 @@ import { useFilterData } from "components/productGrid/context/ProductFiltersCont
|
|
|
5
5
|
|
|
6
6
|
function TypeFilter() {
|
|
7
7
|
const { isLoading, data, updateFilter } = useFilterData()
|
|
8
|
-
const productTypes = useProductQueryStore(state => state.stagedProductQuery.
|
|
8
|
+
const productTypes = useProductQueryStore(state => state.stagedProductQuery.productTypes)
|
|
9
9
|
|
|
10
10
|
if (isLoading) return <FilterCheckboxSkeleton />
|
|
11
11
|
|
|
@@ -14,7 +14,7 @@ function TypeFilter() {
|
|
|
14
14
|
[...productTypes, typeValue] :
|
|
15
15
|
productTypes.filter(t => t !== typeValue)
|
|
16
16
|
|
|
17
|
-
updateFilter('
|
|
17
|
+
updateFilter('productTypes', updatedTypes)
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
return (
|
|
@@ -12,7 +12,7 @@ interface Props {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export default function GridViewProductCard({ product, isEditing }: Props) {
|
|
15
|
-
const { title,
|
|
15
|
+
const { title, lowestPrice, id, slug } = product
|
|
16
16
|
const [isHovered, setIsHovered] = useState(false)
|
|
17
17
|
|
|
18
18
|
return (
|
|
@@ -23,7 +23,7 @@ export default function GridViewProductCard({ product, isEditing }: Props) {
|
|
|
23
23
|
>
|
|
24
24
|
<ProductImageSlider product={product} isHovered={isHovered} isEditing={isEditing} />
|
|
25
25
|
<ProductTitle title={title} slug={slug} className="mt-3" />
|
|
26
|
-
<ProductPrice price={
|
|
26
|
+
<ProductPrice price={lowestPrice} slug={slug} className="mt-2" />
|
|
27
27
|
</div>
|
|
28
28
|
)
|
|
29
29
|
}
|
|
@@ -7,18 +7,18 @@ import useThemeInfo from "hooks/useThemeInfo"
|
|
|
7
7
|
import { useCustomNavigate } from "hooks/useCustomNavigate"
|
|
8
8
|
|
|
9
9
|
export default function ListViewProductCard({ product }: { product: IHomePageProduct }) {
|
|
10
|
-
const {
|
|
10
|
+
const { images, title, lowestPrice, discountRuleset, gatedRuleset, slug, id } = product
|
|
11
11
|
const { isDarkTheme } = useThemeInfo()
|
|
12
12
|
const iconClass = isDarkTheme ? "[&_path]:stroke-white" : ""
|
|
13
13
|
const { navigate } = useCustomNavigate()
|
|
14
|
-
const imageURL = (
|
|
14
|
+
const imageURL = (images.find(img => img.original) ?? images[0])?.thumbnail || images[0]?.original
|
|
15
15
|
|
|
16
16
|
return (
|
|
17
|
-
<div className="cursor-pointer" onClick={() => navigate(`product/${slug ??
|
|
17
|
+
<div className="cursor-pointer" onClick={() => navigate(`product/${slug ?? id}`)}>
|
|
18
18
|
<ProductCardBase
|
|
19
19
|
image={<img src={imageURL} alt={title} className="w-[70px] h-[70px] object-cover rounded-lg shrink-0" />}
|
|
20
20
|
title={<ProductTitle title={title} slug={slug} />}
|
|
21
|
-
price={<ProductPrice price={
|
|
21
|
+
price={<ProductPrice price={lowestPrice} slug={slug} />}
|
|
22
22
|
icons={
|
|
23
23
|
<>
|
|
24
24
|
{discountRuleset && <PLPIcons.Discount className={iconClass} />}
|
|
@@ -39,8 +39,8 @@ function ProductGrid({ limit, isEditing }: { limit?: number; isEditing?: boolean
|
|
|
39
39
|
<ProductGridLayout>
|
|
40
40
|
{products.map(product => (
|
|
41
41
|
isMobile && viewMode === 'list'
|
|
42
|
-
? <ListViewProductCard key={product.
|
|
43
|
-
: <GridViewProductCard key={product.
|
|
42
|
+
? <ListViewProductCard key={product.id} product={product} />
|
|
43
|
+
: <GridViewProductCard key={product.id} product={product} isEditing={isEditing} />
|
|
44
44
|
))}
|
|
45
45
|
|
|
46
46
|
{isFetchingNextPage && renderSkeletons()}
|
|
@@ -15,10 +15,10 @@ interface Props {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export default function ProductImageSlider({ product, isHovered, isEditing }: Props) {
|
|
18
|
-
const {
|
|
18
|
+
const { images, title, slug } = product
|
|
19
19
|
const { navigate } = useCustomNavigate()
|
|
20
20
|
const [currentIndex, setCurrentIndex] = useState(0)
|
|
21
|
-
const sliderImages =
|
|
21
|
+
const sliderImages = images.slice(0, 3)
|
|
22
22
|
|
|
23
23
|
const [sliderRef, instanceRef] = useKeenSlider<HTMLDivElement>({
|
|
24
24
|
loop: true,
|
|
@@ -53,7 +53,7 @@ export default function ProductImageSlider({ product, isHovered, isEditing }: Pr
|
|
|
53
53
|
<div className="relative overflow-hidden rounded-lg aspect-square cursor-pointer">
|
|
54
54
|
<img
|
|
55
55
|
src={sliderImages[0]?.thumbnail}
|
|
56
|
-
alt={title}
|
|
56
|
+
alt={sliderImages[0]?.alt || title}
|
|
57
57
|
onClick={handleImageClick}
|
|
58
58
|
className="w-full h-full object-cover transition-transform duration-500 ease-in-out group-hover:scale-[1.04]"
|
|
59
59
|
/>
|
|
@@ -69,7 +69,7 @@ export default function ProductImageSlider({ product, isHovered, isEditing }: Pr
|
|
|
69
69
|
<div key={index} className="keen-slider__slide w-full h-full aspect-square flex items-center justify-center">
|
|
70
70
|
<img
|
|
71
71
|
src={image.thumbnail}
|
|
72
|
-
alt={`${title}-${index}`}
|
|
72
|
+
alt={image.alt || `${title}-${index}`}
|
|
73
73
|
className="w-full h-full object-cover transition-transform duration-500 ease-in-out group-hover:scale-[1.04]"
|
|
74
74
|
/>
|
|
75
75
|
</div>
|
|
@@ -23,11 +23,11 @@ export default function useSortHandler() {
|
|
|
23
23
|
|
|
24
24
|
function handleSelectChange(sortOption: string, sortOrder?: number) {
|
|
25
25
|
if (sortOption === 'default') {
|
|
26
|
-
setStagedProductQuery('
|
|
26
|
+
setStagedProductQuery('sortBy', '')
|
|
27
27
|
setStagedProductQuery('order', undefined)
|
|
28
28
|
}
|
|
29
29
|
else {
|
|
30
|
-
setStagedProductQuery('
|
|
30
|
+
setStagedProductQuery('sortBy', sortOption)
|
|
31
31
|
setStagedProductQuery('order', sortOrder)
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -2,9 +2,9 @@ import { create } from 'zustand'
|
|
|
2
2
|
|
|
3
3
|
export interface ProductQuery {
|
|
4
4
|
search: string
|
|
5
|
-
|
|
5
|
+
sortBy: string
|
|
6
6
|
order?: number
|
|
7
|
-
|
|
7
|
+
productTypes: string[]
|
|
8
8
|
collectionId: string[]
|
|
9
9
|
minPrice?: number
|
|
10
10
|
maxPrice?: number
|
|
@@ -23,8 +23,8 @@ interface ProductQueryStore {
|
|
|
23
23
|
|
|
24
24
|
const initialProductQuery: ProductQuery = {
|
|
25
25
|
search: "",
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
sortBy: "",
|
|
27
|
+
productTypes: [],
|
|
28
28
|
collectionId: []
|
|
29
29
|
}
|
|
30
30
|
|