@webbycrown/webbycommerce 1.2.1 → 2.0.0

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 (162) hide show
  1. package/README.md +21 -3
  2. package/admin/app.js +3 -0
  3. package/admin/jsconfig.json +20 -0
  4. package/admin/src/components/ApiCollectionsContent.jsx +4626 -0
  5. package/admin/src/components/CompareContent.jsx +300 -0
  6. package/admin/src/components/ConfigureContent.jsx +407 -0
  7. package/admin/src/components/Initializer.jsx +64 -0
  8. package/admin/src/components/LoginRegisterContent.jsx +280 -0
  9. package/admin/src/components/PluginIcon.jsx +6 -0
  10. package/admin/src/components/ShippingTypeContent.jsx +230 -0
  11. package/admin/src/components/SmtpContent.jsx +316 -0
  12. package/admin/src/components/WishlistContent.jsx +273 -0
  13. package/admin/src/index.js +81 -0
  14. package/admin/src/pages/ApiCollections.jsx +169 -0
  15. package/admin/src/pages/Configure.jsx +55 -0
  16. package/admin/src/pages/Settings.jsx +93 -0
  17. package/admin/src/pluginId.js +4 -0
  18. package/{dist/_chunks/en-CiQ97iC8.js → admin/src/translations/en.json} +712 -574
  19. package/bin/setup.js +50 -3
  20. package/package.json +14 -13
  21. package/server/bootstrap.js +3 -0
  22. package/server/register.js +3 -0
  23. package/server/src/bootstrap.js +3826 -0
  24. package/server/src/components/content-block.json +37 -0
  25. package/server/src/components/shipping-zone-location.json +27 -0
  26. package/server/src/config/index.js +7 -0
  27. package/server/src/content-types/address/index.js +7 -0
  28. package/server/src/content-types/address/schema.json +74 -0
  29. package/server/src/content-types/cart/index.js +61 -0
  30. package/server/src/content-types/cart-item/index.js +79 -0
  31. package/server/src/content-types/compare.js +73 -0
  32. package/server/src/content-types/coupon/index.js +7 -0
  33. package/server/src/content-types/coupon/schema.json +67 -0
  34. package/server/src/content-types/index.js +42 -0
  35. package/server/src/content-types/order/index.js +7 -0
  36. package/server/src/content-types/order/schema.json +121 -0
  37. package/server/src/content-types/payment-transaction/index.js +7 -0
  38. package/server/src/content-types/payment-transaction/schema.json +73 -0
  39. package/server/src/content-types/product/index.js +7 -0
  40. package/server/src/content-types/product/schema.json +104 -0
  41. package/server/src/content-types/product-attribute/index.js +7 -0
  42. package/server/src/content-types/product-attribute/schema.json +80 -0
  43. package/server/src/content-types/product-attribute-value/index.js +7 -0
  44. package/server/src/content-types/product-attribute-value/schema.json +52 -0
  45. package/server/src/content-types/product-category/index.js +7 -0
  46. package/server/src/content-types/product-category/schema.json +54 -0
  47. package/server/src/content-types/product-tag/index.js +7 -0
  48. package/server/src/content-types/product-tag/schema.json +38 -0
  49. package/server/src/content-types/product-variation/index.js +7 -0
  50. package/server/src/content-types/product-variation/schema.json +74 -0
  51. package/server/src/content-types/shipping-method/index.js +7 -0
  52. package/server/src/content-types/shipping-method/schema.json +91 -0
  53. package/server/src/content-types/shipping-rate/index.js +7 -0
  54. package/server/src/content-types/shipping-rate/schema.json +73 -0
  55. package/server/src/content-types/shipping-rule/index.js +7 -0
  56. package/server/src/content-types/shipping-rule/schema.json +84 -0
  57. package/server/src/content-types/shipping-zone/index.js +7 -0
  58. package/server/src/content-types/shipping-zone/schema.json +57 -0
  59. package/server/src/content-types/wishlist.js +66 -0
  60. package/server/src/controllers/address.js +374 -0
  61. package/server/src/controllers/auth.js +1409 -0
  62. package/server/src/controllers/cart.js +337 -0
  63. package/server/src/controllers/category.js +388 -0
  64. package/server/src/controllers/compare.js +246 -0
  65. package/server/src/controllers/controller.js +168 -0
  66. package/server/src/controllers/ecommerce.js +20 -0
  67. package/server/src/controllers/index.js +34 -0
  68. package/server/src/controllers/order.js +1100 -0
  69. package/server/src/controllers/payment.js +243 -0
  70. package/server/src/controllers/product.js +1006 -0
  71. package/server/src/controllers/productTag.js +370 -0
  72. package/server/src/controllers/productVariation.js +181 -0
  73. package/server/src/controllers/shipping.js +1046 -0
  74. package/server/src/controllers/wishlist.js +332 -0
  75. package/server/src/destroy.js +6 -0
  76. package/server/src/index.js +26 -0
  77. package/server/src/middlewares/index.js +4 -0
  78. package/server/src/policies/index.js +4 -0
  79. package/server/src/register.js +67 -0
  80. package/server/src/routes/index.js +1130 -0
  81. package/server/src/services/cart.js +531 -0
  82. package/server/src/services/compare.js +300 -0
  83. package/server/src/services/index.js +16 -0
  84. package/server/src/services/service.js +19 -0
  85. package/server/src/services/shipping.js +513 -0
  86. package/server/src/services/wishlist.js +238 -0
  87. package/server/src/utils/check-ecommerce-permission.js +204 -0
  88. package/server/src/utils/extend-user-schema.js +161 -0
  89. package/server/src/utils/seed-data.js +639 -0
  90. package/server/src/utils/send-email.js +98 -0
  91. package/strapi-server.js +1 -6
  92. package/dist/_chunks/Settings-Bg2JyQ4c.js +0 -31518
  93. package/dist/_chunks/Settings-BonPzbwr.mjs +0 -31499
  94. package/dist/_chunks/en-DE15m4xZ.mjs +0 -574
  95. package/dist/_chunks/index-BWVy9o1d.mjs +0 -128
  96. package/dist/_chunks/index-NRuOdjd7.js +0 -127
  97. package/dist/admin/index.js +0 -3
  98. package/dist/admin/index.mjs +0 -4
  99. package/dist/robots.txt +0 -3
  100. package/dist/server/index.js +0 -27336
  101. package/dist/uploads/.gitkeep +0 -0
  102. package/dist/uploads/accessories_category_2a5631094b.jpeg +0 -0
  103. package/dist/uploads/beauty_personal_care_category_57f8a8f1e3.jpeg +0 -0
  104. package/dist/uploads/books_category_a9a253eada.jpeg +0 -0
  105. package/dist/uploads/classic_cotton_tshirt_1_cd713425f6.png +0 -0
  106. package/dist/uploads/clothing_category_d5c60ef07b.jpeg +0 -0
  107. package/dist/uploads/daviddoe_strapi_adbcd41787.jpeg +0 -0
  108. package/dist/uploads/electronics_category_fc3e5ef571.jpeg +0 -0
  109. package/dist/uploads/ergonomic_office_chair_1_c751cffb07.png +0 -0
  110. package/dist/uploads/home_garden_category_4f6eb3f8d6.jpeg +0 -0
  111. package/dist/uploads/istockphoto_1188462138_612x612_11f295b9c0.jpg +0 -0
  112. package/dist/uploads/istockphoto_1188462138_612x612_396fb272fd.jpg +0 -0
  113. package/dist/uploads/large_daviddoe_strapi_adbcd41787.jpeg +0 -0
  114. package/dist/uploads/leather_travel_backpack_1_238bc1ae4d.png +0 -0
  115. package/dist/uploads/mechanical_keyboard_pro_1_0cd391a6ac.png +0 -0
  116. package/dist/uploads/medium_classic_cotton_tshirt_1_cd713425f6.png +0 -0
  117. package/dist/uploads/medium_daviddoe_strapi_adbcd41787.jpeg +0 -0
  118. package/dist/uploads/medium_ergonomic_office_chair_1_c751cffb07.png +0 -0
  119. package/dist/uploads/medium_leather_travel_backpack_1_238bc1ae4d.png +0 -0
  120. package/dist/uploads/medium_mechanical_keyboard_pro_1_0cd391a6ac.png +0 -0
  121. package/dist/uploads/medium_smart_watch_series_5_1_cdc2511fb7.png +0 -0
  122. package/dist/uploads/medium_smartphone_x_pro_1_c3f0cbd080.png +0 -0
  123. package/dist/uploads/medium_the_great_gatsby_special_1_2e7c76d997.png +0 -0
  124. package/dist/uploads/medium_wireless_headphones_1_fa75cd50c3.png +0 -0
  125. package/dist/uploads/medium_yoga_mat_premium_1_01f9a3b5fa.png +0 -0
  126. package/dist/uploads/predictive_maintenance_icons_industry_automation_600nw_2685943461_e18a8aa3b0.webp +0 -0
  127. package/dist/uploads/small_classic_cotton_tshirt_1_cd713425f6.png +0 -0
  128. package/dist/uploads/small_daviddoe_strapi_adbcd41787.jpeg +0 -0
  129. package/dist/uploads/small_ergonomic_office_chair_1_c751cffb07.png +0 -0
  130. package/dist/uploads/small_leather_travel_backpack_1_238bc1ae4d.png +0 -0
  131. package/dist/uploads/small_mechanical_keyboard_pro_1_0cd391a6ac.png +0 -0
  132. package/dist/uploads/small_smart_watch_series_5_1_cdc2511fb7.png +0 -0
  133. package/dist/uploads/small_smartphone_x_pro_1_c3f0cbd080.png +0 -0
  134. package/dist/uploads/small_the_great_gatsby_special_1_2e7c76d997.png +0 -0
  135. package/dist/uploads/small_wireless_headphones_1_fa75cd50c3.png +0 -0
  136. package/dist/uploads/small_yoga_mat_premium_1_01f9a3b5fa.png +0 -0
  137. package/dist/uploads/smart_watch_series_5_1_cdc2511fb7.png +0 -0
  138. package/dist/uploads/smartphone_x_pro_1_c3f0cbd080.png +0 -0
  139. package/dist/uploads/the_great_gatsby_special_1_2e7c76d997.png +0 -0
  140. package/dist/uploads/thumbnail_accessories_category_2a5631094b.jpeg +0 -0
  141. package/dist/uploads/thumbnail_beauty_personal_care_category_57f8a8f1e3.jpeg +0 -0
  142. package/dist/uploads/thumbnail_books_category_a9a253eada.jpeg +0 -0
  143. package/dist/uploads/thumbnail_classic_cotton_tshirt_1_cd713425f6.png +0 -0
  144. package/dist/uploads/thumbnail_clothing_category_d5c60ef07b.jpeg +0 -0
  145. package/dist/uploads/thumbnail_daviddoe_strapi_adbcd41787.jpeg +0 -0
  146. package/dist/uploads/thumbnail_electronics_category_fc3e5ef571.jpeg +0 -0
  147. package/dist/uploads/thumbnail_ergonomic_office_chair_1_c751cffb07.png +0 -0
  148. package/dist/uploads/thumbnail_home_garden_category_4f6eb3f8d6.jpeg +0 -0
  149. package/dist/uploads/thumbnail_istockphoto_1188462138_612x612_11f295b9c0.jpg +0 -0
  150. package/dist/uploads/thumbnail_istockphoto_1188462138_612x612_396fb272fd.jpg +0 -0
  151. package/dist/uploads/thumbnail_leather_travel_backpack_1_238bc1ae4d.png +0 -0
  152. package/dist/uploads/thumbnail_mechanical_keyboard_pro_1_0cd391a6ac.png +0 -0
  153. package/dist/uploads/thumbnail_predictive_maintenance_icons_industry_automation_600nw_2685943461_e18a8aa3b0.webp +0 -0
  154. package/dist/uploads/thumbnail_smart_watch_series_5_1_cdc2511fb7.png +0 -0
  155. package/dist/uploads/thumbnail_smartphone_x_pro_1_c3f0cbd080.png +0 -0
  156. package/dist/uploads/thumbnail_the_great_gatsby_special_1_2e7c76d997.png +0 -0
  157. package/dist/uploads/thumbnail_wireless_headphones_1_fa75cd50c3.png +0 -0
  158. package/dist/uploads/thumbnail_yoga_mat_premium_1_01f9a3b5fa.png +0 -0
  159. package/dist/uploads/webby-commerce.png +0 -0
  160. package/dist/uploads/wireless_headphones_1_fa75cd50c3.png +0 -0
  161. package/dist/uploads/yoga_mat_premium_1_01f9a3b5fa.png +0 -0
  162. /package/{dist → server/src}/data/demo-data.json +0 -0
@@ -0,0 +1,300 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * compare service
5
+ */
6
+
7
+ const { createCoreService } = require('@strapi/strapi').factories;
8
+
9
+ module.exports = createCoreService('plugin::webbycommerce.compare', ({ strapi }) => ({
10
+ async findUserCompare(userId) {
11
+ try {
12
+ const compares = await strapi.db.query('plugin::webbycommerce.compare').findMany({
13
+ where: {
14
+ userId: String(userId),
15
+ },
16
+ orderBy: { createdAt: 'desc' },
17
+ populate: {
18
+ products: {
19
+ populate: {
20
+ images: true,
21
+ product_categories: true,
22
+ tags: true,
23
+ variations: {
24
+ populate: {
25
+ attributes: true,
26
+ attributeValues: true,
27
+ },
28
+ },
29
+ },
30
+ },
31
+ category: true,
32
+ },
33
+ });
34
+
35
+ return compares.length > 0 ? compares[0] : null;
36
+ } catch (error) {
37
+ throw new Error(`Failed to find user compare: ${error.message}`);
38
+ }
39
+ },
40
+
41
+ async createUserCompare(userId, userEmail, data = {}) {
42
+ try {
43
+ const compareData = {
44
+ userId: String(userId),
45
+ userEmail,
46
+ products: [],
47
+ isPublic: data.isPublic || false,
48
+ name: data.name || null,
49
+ notes: data.notes || null,
50
+ category: data.categoryId || null,
51
+ };
52
+
53
+ await strapi.entityService.create('plugin::webbycommerce.compare', {
54
+ data: compareData,
55
+ });
56
+
57
+ // Refetch compare with populated products
58
+ return await this.findUserCompare(userId);
59
+ } catch (error) {
60
+ throw new Error(`Failed to create user compare: ${error.message}`);
61
+ }
62
+ },
63
+
64
+ async addProductToCompare(userId, userEmail, productId) {
65
+ try {
66
+ // Find existing compare or create new one
67
+ let compare = await this.findUserCompare(userId);
68
+
69
+ if (!compare) {
70
+ compare = await this.createUserCompare(userId, userEmail);
71
+ }
72
+
73
+ // Ensure products array exists
74
+ if (!compare.products) {
75
+ compare.products = [];
76
+ }
77
+
78
+ // Check if compare list is already full (max 4 products)
79
+ if (compare.products.length >= 4) {
80
+ throw new Error('Compare list is full. Maximum 4 products allowed.');
81
+ }
82
+
83
+ // Check if product already exists in compare
84
+ // Handle both populated (object with id) and unpopulated (just id) cases
85
+ const productExists = compare.products.some(product => {
86
+ const productIdValue = typeof product === 'object' && product !== null ? product.id : product;
87
+ return productIdValue === parseInt(productId);
88
+ });
89
+
90
+ if (productExists) {
91
+ throw new Error('Product already exists in compare list');
92
+ }
93
+
94
+ // Verify product exists
95
+ const product = await strapi.entityService.findOne('plugin::webbycommerce.product', productId, {
96
+ populate: ['product_categories'],
97
+ });
98
+
99
+ if (!product) {
100
+ throw new Error('Product not found');
101
+ }
102
+
103
+ // Check if product belongs to same category (optional but recommended)
104
+ if (compare.category && product.product_categories && product.product_categories.length > 0 && compare.category.id !== product.product_categories[0].id) {
105
+ // Allow but log warning - user can compare different categories if they want
106
+ strapi.log.warn(`Adding product from different category to compare list. Compare category: ${compare.category.name}, Product category: ${product.product_categories[0].name}`);
107
+ }
108
+
109
+ // Get existing product IDs (handle both populated and unpopulated cases)
110
+ const existingProductIds = compare.products.map(p => {
111
+ return typeof p === 'object' && p !== null ? p.id : p;
112
+ }).filter(id => id != null);
113
+
114
+ // Add product to compare
115
+ await strapi.entityService.update('plugin::webbycommerce.compare', compare.id, {
116
+ data: {
117
+ products: { set: [...existingProductIds, parseInt(productId, 10)].map((id) => ({ id })) },
118
+ category: compare.category || product.product_categories?.[0]?.id || null,
119
+ },
120
+ });
121
+
122
+ // Refetch compare with populated products
123
+ return await this.findUserCompare(userId);
124
+ } catch (error) {
125
+ throw new Error(`Failed to add product to compare: ${error.message}`);
126
+ }
127
+ },
128
+
129
+ async removeProductFromCompare(userId, productId) {
130
+ try {
131
+ const compare = await this.findUserCompare(userId);
132
+
133
+ if (!compare) {
134
+ throw new Error('Compare list not found');
135
+ }
136
+
137
+ // Ensure products array exists
138
+ if (!compare.products) {
139
+ compare.products = [];
140
+ }
141
+
142
+ // Remove product from compare
143
+ // Handle both populated (object with id) and unpopulated (just id) cases
144
+ const updatedProducts = compare.products
145
+ .filter(product => {
146
+ const productIdValue = typeof product === 'object' && product !== null ? product.id : product;
147
+ return productIdValue !== parseInt(productId);
148
+ })
149
+ .map(product => {
150
+ return typeof product === 'object' && product !== null ? product.id : product;
151
+ });
152
+
153
+ await strapi.entityService.update('plugin::webbycommerce.compare', compare.id, {
154
+ data: {
155
+ products: { set: updatedProducts.map((id) => ({ id })) },
156
+ // Reset category if no products left
157
+ category: updatedProducts.length === 0 ? null : compare.category,
158
+ },
159
+ });
160
+
161
+ // Refetch compare with populated products
162
+ return await this.findUserCompare(userId);
163
+ } catch (error) {
164
+ throw new Error(`Failed to remove product from compare: ${error.message}`);
165
+ }
166
+ },
167
+
168
+ async clearCompare(userId) {
169
+ try {
170
+ const compare = await this.findUserCompare(userId);
171
+
172
+ if (!compare) {
173
+ throw new Error('Compare list not found');
174
+ }
175
+
176
+ await strapi.entityService.update('plugin::webbycommerce.compare', compare.id, {
177
+ data: {
178
+ products: { set: [] },
179
+ category: null,
180
+ },
181
+ });
182
+
183
+ // Refetch compare with populated products
184
+ return await this.findUserCompare(userId);
185
+ } catch (error) {
186
+ throw new Error(`Failed to clear compare list: ${error.message}`);
187
+ }
188
+ },
189
+
190
+ async updateCompare(userId, data) {
191
+ try {
192
+ const compare = await this.findUserCompare(userId);
193
+
194
+ if (!compare) {
195
+ throw new Error('Compare list not found');
196
+ }
197
+
198
+ await strapi.entityService.update('plugin::webbycommerce.compare', compare.id, {
199
+ data: {
200
+ name: data.name !== undefined ? data.name : compare.name,
201
+ notes: data.notes !== undefined ? data.notes : compare.notes,
202
+ isPublic: data.isPublic !== undefined ? data.isPublic : compare.isPublic,
203
+ },
204
+ });
205
+
206
+ // Refetch compare with populated products
207
+ return await this.findUserCompare(userId);
208
+ } catch (error) {
209
+ throw new Error(`Failed to update compare list: ${error.message}`);
210
+ }
211
+ },
212
+
213
+ async getCompareData(userId) {
214
+ try {
215
+ const compare = await this.findUserCompare(userId);
216
+
217
+ if (!compare) {
218
+ return {
219
+ products: [],
220
+ category: null,
221
+ comparisonData: {},
222
+ };
223
+ }
224
+
225
+ // Ensure products array exists
226
+ if (!compare.products) {
227
+ compare.products = [];
228
+ }
229
+
230
+ // Generate comparison data
231
+ const comparisonData = this.generateComparisonData(compare.products);
232
+
233
+ return {
234
+ products: compare.products,
235
+ category: compare.category,
236
+ comparisonData,
237
+ };
238
+ } catch (error) {
239
+ throw new Error(`Failed to get compare data: ${error.message}`);
240
+ }
241
+ },
242
+
243
+ generateComparisonData(products) {
244
+ if (!products || products.length === 0) {
245
+ return {};
246
+ }
247
+
248
+ const comparisonData = {
249
+ specifications: {},
250
+ pricing: {},
251
+ availability: {},
252
+ ratings: {},
253
+ };
254
+
255
+ // Extract common specifications
256
+ const specKeys = new Set();
257
+ products.forEach(product => {
258
+ if (product.specifications) {
259
+ Object.keys(product.specifications).forEach(key => specKeys.add(key));
260
+ }
261
+ });
262
+
263
+ // Build comparison matrix
264
+ specKeys.forEach(specKey => {
265
+ comparisonData.specifications[specKey] = {};
266
+ products.forEach(product => {
267
+ comparisonData.specifications[specKey][product.id] =
268
+ product.specifications?.[specKey] || 'N/A';
269
+ });
270
+ });
271
+
272
+ // Pricing comparison
273
+ products.forEach(product => {
274
+ comparisonData.pricing[product.id] = {
275
+ regularPrice: product.regularPrice || 0,
276
+ salePrice: product.salePrice || null,
277
+ discount: product.discount || 0,
278
+ };
279
+ });
280
+
281
+ // Availability comparison
282
+ products.forEach(product => {
283
+ comparisonData.availability[product.id] = {
284
+ inStock: product.stockQuantity > 0,
285
+ stockQuantity: product.stockQuantity || 0,
286
+ status: product.status || 'active',
287
+ };
288
+ });
289
+
290
+ // Ratings comparison
291
+ products.forEach(product => {
292
+ comparisonData.ratings[product.id] = {
293
+ averageRating: product.averageRating || 0,
294
+ totalReviews: product.totalReviews || 0,
295
+ };
296
+ });
297
+
298
+ return comparisonData;
299
+ },
300
+ }));
@@ -0,0 +1,16 @@
1
+ 'use strict';
2
+
3
+ const service = require('./service');
4
+ const compare = require('./compare');
5
+ const cart = require('./cart');
6
+ const wishlist = require('./wishlist');
7
+ const shipping = require('./shipping');
8
+
9
+ module.exports = {
10
+ service,
11
+ compare,
12
+ cart,
13
+ wishlist,
14
+ shipping,
15
+ };
16
+
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+
3
+ const PLUGIN_ID = 'webbycommerce';
4
+
5
+ const { seedDemoData } = require('../utils/seed-data');
6
+
7
+ module.exports = ({ strapi }) => ({
8
+ getPluginInfo() {
9
+ return {
10
+ name: PLUGIN_ID,
11
+ version: '1.0.0',
12
+ };
13
+ },
14
+
15
+ async seedDemoData() {
16
+ return await seedDemoData(strapi);
17
+ }
18
+ });
19
+