@wix/ditto-codegen-public 1.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 (170) hide show
  1. package/dist/examples-apps/ai-chatbot/.nvmrc +1 -0
  2. package/dist/examples-apps/ai-chatbot/README.md +21 -0
  3. package/dist/examples-apps/ai-chatbot/package-lock.json +7266 -0
  4. package/dist/examples-apps/ai-chatbot/package.json +35 -0
  5. package/dist/examples-apps/ai-chatbot/src/backend/api/chat/api.ts +62 -0
  6. package/dist/examples-apps/ai-chatbot/src/backend/api/settings/api.ts +39 -0
  7. package/dist/examples-apps/ai-chatbot/src/backend/database.ts +86 -0
  8. package/dist/examples-apps/ai-chatbot/src/dashboard/pages/product/ProductChat.module.css +3 -0
  9. package/dist/examples-apps/ai-chatbot/src/dashboard/pages/product/ProductChat.tsx +99 -0
  10. package/dist/examples-apps/ai-chatbot/src/dashboard/pages/product/page.json +6 -0
  11. package/dist/examples-apps/ai-chatbot/src/dashboard/pages/product/page.tsx +99 -0
  12. package/dist/examples-apps/ai-chatbot/src/dashboard/pages/settings/page.json +6 -0
  13. package/dist/examples-apps/ai-chatbot/src/dashboard/pages/settings/page.tsx +105 -0
  14. package/dist/examples-apps/ai-chatbot/src/dashboard/pages/wix_logo.svg +18 -0
  15. package/dist/examples-apps/ai-chatbot/src/dashboard/utils.ts +27 -0
  16. package/dist/examples-apps/ai-chatbot/src/dashboard/withProviders.tsx +15 -0
  17. package/dist/examples-apps/ai-chatbot/src/env.d.ts +4 -0
  18. package/dist/examples-apps/ai-chatbot/src/types.ts +4 -0
  19. package/dist/examples-apps/ai-chatbot/tsconfig.json +8 -0
  20. package/dist/examples-apps/ai-chatbot/wix.config.json +5 -0
  21. package/dist/examples-apps/chart-widget/.nvmrc +1 -0
  22. package/dist/examples-apps/chart-widget/README.md +21 -0
  23. package/dist/examples-apps/chart-widget/assets/chart-widget/thumbnail.png +0 -0
  24. package/dist/examples-apps/chart-widget/package-lock.json +6329 -0
  25. package/dist/examples-apps/chart-widget/package.json +30 -0
  26. package/dist/examples-apps/chart-widget/src/env.d.ts +4 -0
  27. package/dist/examples-apps/chart-widget/src/site/widgets/custom-elements/chart-widget/common.ts +20 -0
  28. package/dist/examples-apps/chart-widget/src/site/widgets/custom-elements/chart-widget/element/bar-chart.tsx +53 -0
  29. package/dist/examples-apps/chart-widget/src/site/widgets/custom-elements/chart-widget/element/pie-chart.tsx +40 -0
  30. package/dist/examples-apps/chart-widget/src/site/widgets/custom-elements/chart-widget/element.json +20 -0
  31. package/dist/examples-apps/chart-widget/src/site/widgets/custom-elements/chart-widget/element.tsx +53 -0
  32. package/dist/examples-apps/chart-widget/src/site/widgets/custom-elements/chart-widget/panel/chart-type.tsx +47 -0
  33. package/dist/examples-apps/chart-widget/src/site/widgets/custom-elements/chart-widget/panel/slice.tsx +72 -0
  34. package/dist/examples-apps/chart-widget/src/site/widgets/custom-elements/chart-widget/panel.tsx +90 -0
  35. package/dist/examples-apps/chart-widget/tsconfig.json +8 -0
  36. package/dist/examples-apps/chart-widget/wix.config.json +5 -0
  37. package/dist/examples-apps/custom-products-catalog/.nvmrc +1 -0
  38. package/dist/examples-apps/custom-products-catalog/README.md +21 -0
  39. package/dist/examples-apps/custom-products-catalog/package-lock.json +8694 -0
  40. package/dist/examples-apps/custom-products-catalog/package.json +33 -0
  41. package/dist/examples-apps/custom-products-catalog/src/dashboard/components/create-product.tsx +54 -0
  42. package/dist/examples-apps/custom-products-catalog/src/dashboard/hooks/stores.ts +60 -0
  43. package/dist/examples-apps/custom-products-catalog/src/dashboard/pages/page.json +5 -0
  44. package/dist/examples-apps/custom-products-catalog/src/dashboard/pages/page.tsx +297 -0
  45. package/dist/examples-apps/custom-products-catalog/src/dashboard/pages/wix_logo.svg +18 -0
  46. package/dist/examples-apps/custom-products-catalog/src/dashboard/withProviders.tsx +16 -0
  47. package/dist/examples-apps/custom-products-catalog/src/env.d.ts +4 -0
  48. package/dist/examples-apps/custom-products-catalog/tsconfig.json +8 -0
  49. package/dist/examples-apps/custom-products-catalog/wix.config.json +5 -0
  50. package/dist/examples-apps/inventory-countdown/.nvmrc +1 -0
  51. package/dist/examples-apps/inventory-countdown/README.md +21 -0
  52. package/dist/examples-apps/inventory-countdown/package-lock.json +7457 -0
  53. package/dist/examples-apps/inventory-countdown/package.json +33 -0
  54. package/dist/examples-apps/inventory-countdown/src/assets/stock-counter/site-plugin-logo.svg +27 -0
  55. package/dist/examples-apps/inventory-countdown/src/env.d.ts +4 -0
  56. package/dist/examples-apps/inventory-countdown/src/site/plugins/custom-elements/stock-counter/consts.ts +1 -0
  57. package/dist/examples-apps/inventory-countdown/src/site/plugins/custom-elements/stock-counter/panel.tsx +81 -0
  58. package/dist/examples-apps/inventory-countdown/src/site/plugins/custom-elements/stock-counter/plugin.json +24 -0
  59. package/dist/examples-apps/inventory-countdown/src/site/plugins/custom-elements/stock-counter/plugin.module.css +4 -0
  60. package/dist/examples-apps/inventory-countdown/src/site/plugins/custom-elements/stock-counter/plugin.tsx +132 -0
  61. package/dist/examples-apps/inventory-countdown/tsconfig.json +8 -0
  62. package/dist/examples-apps/inventory-countdown/wix.config.json +5 -0
  63. package/dist/examples-apps/mixpanel-analytics/.nvmrc +1 -0
  64. package/dist/examples-apps/mixpanel-analytics/README.md +21 -0
  65. package/dist/examples-apps/mixpanel-analytics/package-lock.json +6357 -0
  66. package/dist/examples-apps/mixpanel-analytics/package.json +31 -0
  67. package/dist/examples-apps/mixpanel-analytics/src/dashboard/components/ProjectToken.tsx +60 -0
  68. package/dist/examples-apps/mixpanel-analytics/src/dashboard/hooks/wix-embeds.ts +33 -0
  69. package/dist/examples-apps/mixpanel-analytics/src/dashboard/pages/page.json +5 -0
  70. package/dist/examples-apps/mixpanel-analytics/src/dashboard/pages/page.tsx +39 -0
  71. package/dist/examples-apps/mixpanel-analytics/src/dashboard/withProviders.tsx +19 -0
  72. package/dist/examples-apps/mixpanel-analytics/src/env.d.ts +4 -0
  73. package/dist/examples-apps/mixpanel-analytics/src/site/embedded-scripts/mixpanel-analytics/embedded.html +13 -0
  74. package/dist/examples-apps/mixpanel-analytics/src/site/embedded-scripts/mixpanel-analytics/embedded.json +7 -0
  75. package/dist/examples-apps/mixpanel-analytics/tsconfig.json +8 -0
  76. package/dist/examples-apps/mixpanel-analytics/wix.config.json +5 -0
  77. package/dist/examples-apps/my-locations-app/.nvmrc +1 -0
  78. package/dist/examples-apps/my-locations-app/README.md +21 -0
  79. package/dist/examples-apps/my-locations-app/package-lock.json +6351 -0
  80. package/dist/examples-apps/my-locations-app/package.json +31 -0
  81. package/dist/examples-apps/my-locations-app/src/dashboard/pages/page.json +5 -0
  82. package/dist/examples-apps/my-locations-app/src/dashboard/pages/page.tsx +89 -0
  83. package/dist/examples-apps/my-locations-app/src/dashboard/pages/wix_logo.svg +18 -0
  84. package/dist/examples-apps/my-locations-app/src/env.d.ts +4 -0
  85. package/dist/examples-apps/my-locations-app/tsconfig.json +8 -0
  86. package/dist/examples-apps/my-locations-app/wix.config.json +5 -0
  87. package/dist/examples-apps/site-popup/.nvmrc +1 -0
  88. package/dist/examples-apps/site-popup/README.md +21 -0
  89. package/dist/examples-apps/site-popup/package-lock.json +8033 -0
  90. package/dist/examples-apps/site-popup/package.json +34 -0
  91. package/dist/examples-apps/site-popup/postcss.config.js +7 -0
  92. package/dist/examples-apps/site-popup/src/components/activation-configuration.tsx +49 -0
  93. package/dist/examples-apps/site-popup/src/components/close-button.tsx +30 -0
  94. package/dist/examples-apps/site-popup/src/components/date-range-picker.tsx +49 -0
  95. package/dist/examples-apps/site-popup/src/components/image-picker.tsx +33 -0
  96. package/dist/examples-apps/site-popup/src/components/popup/index.css +3 -0
  97. package/dist/examples-apps/site-popup/src/components/popup/index.tsx +71 -0
  98. package/dist/examples-apps/site-popup/src/components/site-popup-settings.tsx +120 -0
  99. package/dist/examples-apps/site-popup/src/dashboard/hooks/wix-embeds.ts +33 -0
  100. package/dist/examples-apps/site-popup/src/dashboard/pages/page.tsx +78 -0
  101. package/dist/examples-apps/site-popup/src/dashboard/withProviders.tsx +19 -0
  102. package/dist/examples-apps/site-popup/src/env.d.ts +4 -0
  103. package/dist/examples-apps/site-popup/src/site/embedded-scripts/site-popup/embedded.html +12 -0
  104. package/dist/examples-apps/site-popup/src/site/embedded-scripts/site-popup/embedded.json +7 -0
  105. package/dist/examples-apps/site-popup/src/site/embedded-scripts/site-popup/params.dev.json +7 -0
  106. package/dist/examples-apps/site-popup/src/site/embedded-scripts/site-popup/popup-overlay/index.css +3 -0
  107. package/dist/examples-apps/site-popup/src/site/embedded-scripts/site-popup/popup-overlay/index.tsx +58 -0
  108. package/dist/examples-apps/site-popup/src/types.ts +14 -0
  109. package/dist/examples-apps/site-popup/tailwind.config.js +8 -0
  110. package/dist/examples-apps/site-popup/tsconfig.json +9 -0
  111. package/dist/examples-apps/site-popup/wix.config.json +5 -0
  112. package/dist/examples-apps/spis-examples/.nvmrc +1 -0
  113. package/dist/examples-apps/spis-examples/README.md +21 -0
  114. package/dist/examples-apps/spis-examples/package-lock.json +6903 -0
  115. package/dist/examples-apps/spis-examples/package.json +31 -0
  116. package/dist/examples-apps/spis-examples/src/backend/service-plugins/ecom-additional-fees/additional-fees/plugin.json +5 -0
  117. package/dist/examples-apps/spis-examples/src/backend/service-plugins/ecom-additional-fees/additional-fees/plugin.ts +24 -0
  118. package/dist/examples-apps/spis-examples/src/backend/service-plugins/ecom-discounts-trigger/discount-triggers/plugin.json +5 -0
  119. package/dist/examples-apps/spis-examples/src/backend/service-plugins/ecom-discounts-trigger/discount-triggers/plugin.ts +42 -0
  120. package/dist/examples-apps/spis-examples/src/backend/service-plugins/ecom-shipping-rates/shipping-rates/plugin.json +7 -0
  121. package/dist/examples-apps/spis-examples/src/backend/service-plugins/ecom-shipping-rates/shipping-rates/plugin.ts +34 -0
  122. package/dist/examples-apps/spis-examples/src/backend/service-plugins/ecom-validations/validations/plugin.json +6 -0
  123. package/dist/examples-apps/spis-examples/src/backend/service-plugins/ecom-validations/validations/plugin.ts +24 -0
  124. package/dist/examples-apps/spis-examples/src/backend/service-plugins/gift-cards-provider/gift-cards/plugin.json +5 -0
  125. package/dist/examples-apps/spis-examples/src/backend/service-plugins/gift-cards-provider/gift-cards/plugin.ts +38 -0
  126. package/dist/examples-apps/spis-examples/src/dashboard/pages/page.tsx +59 -0
  127. package/dist/examples-apps/spis-examples/src/dashboard/pages/wix_logo.svg +18 -0
  128. package/dist/examples-apps/spis-examples/src/env.d.ts +4 -0
  129. package/dist/examples-apps/spis-examples/tsconfig.json +8 -0
  130. package/dist/examples-apps/spis-examples/wix.config.json +5 -0
  131. package/dist/examples-apps/top-blog-posts/.nvmrc +1 -0
  132. package/dist/examples-apps/top-blog-posts/README.md +21 -0
  133. package/dist/examples-apps/top-blog-posts/package-lock.json +6406 -0
  134. package/dist/examples-apps/top-blog-posts/package.json +31 -0
  135. package/dist/examples-apps/top-blog-posts/src/dashboard/pages/blog-utils.ts +44 -0
  136. package/dist/examples-apps/top-blog-posts/src/dashboard/pages/page.tsx +129 -0
  137. package/dist/examples-apps/top-blog-posts/src/dashboard/pages/wix_logo.svg +18 -0
  138. package/dist/examples-apps/top-blog-posts/src/env.d.ts +4 -0
  139. package/dist/examples-apps/top-blog-posts/tsconfig.json +8 -0
  140. package/dist/examples-apps/top-blog-posts/wix.config.json +5 -0
  141. package/dist/out.js +1365 -0
  142. package/dist/wix-cli-templates/.nvmrc +1 -0
  143. package/dist/wix-cli-templates/README.md +21 -0
  144. package/dist/wix-cli-templates/package-lock.json +7118 -0
  145. package/dist/wix-cli-templates/package.json +35 -0
  146. package/dist/wix-cli-templates/src/assets/my-widget/thumbnail.png +0 -0
  147. package/dist/wix-cli-templates/src/backend/api/my-api/api.ts +29 -0
  148. package/dist/wix-cli-templates/src/backend/events/my-event/event.ts +16 -0
  149. package/dist/wix-cli-templates/src/backend/my-web-method.web.ts +21 -0
  150. package/dist/wix-cli-templates/src/backend/service-plugins/ecom-additional-fees/my-service-plugin/plugin.ts +9 -0
  151. package/dist/wix-cli-templates/src/backend/service-plugins/ecom-discounts-trigger/my-service-plugin/plugin.ts +14 -0
  152. package/dist/wix-cli-templates/src/backend/service-plugins/ecom-payment-settings/my-service-plugin/plugin.ts +12 -0
  153. package/dist/wix-cli-templates/src/backend/service-plugins/ecom-shipping-rates/my-service-plugin/plugin.ts +9 -0
  154. package/dist/wix-cli-templates/src/backend/service-plugins/ecom-validations/my-service-plugin/plugin.ts +9 -0
  155. package/dist/wix-cli-templates/src/backend/service-plugins/gift-cards-provider/my-service-plugin/plugin.ts +23 -0
  156. package/dist/wix-cli-templates/src/dashboard/modals/my-modal/modal.tsx +40 -0
  157. package/dist/wix-cli-templates/src/dashboard/pages/page.tsx +59 -0
  158. package/dist/wix-cli-templates/src/dashboard/pages/wix_logo.svg +18 -0
  159. package/dist/wix-cli-templates/src/env.d.ts +4 -0
  160. package/dist/wix-cli-templates/src/site/embedded-scripts/my-script/embedded.html +2 -0
  161. package/dist/wix-cli-templates/src/site/embedded-scripts/my-script/embedded.json +7 -0
  162. package/dist/wix-cli-templates/src/site/embedded-scripts/my-script/logger.ts +1 -0
  163. package/dist/wix-cli-templates/src/site/embedded-scripts/my-script/params.dev.json +3 -0
  164. package/dist/wix-cli-templates/src/site/widgets/custom-elements/my-widget/element.json +27 -0
  165. package/dist/wix-cli-templates/src/site/widgets/custom-elements/my-widget/element.module.css +32 -0
  166. package/dist/wix-cli-templates/src/site/widgets/custom-elements/my-widget/element.tsx +36 -0
  167. package/dist/wix-cli-templates/src/site/widgets/custom-elements/my-widget/panel.tsx +54 -0
  168. package/dist/wix-cli-templates/tsconfig.json +8 -0
  169. package/dist/wix-cli-templates/wix.config.json +5 -0
  170. package/package.json +28 -0
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "custom-products-catalog",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "dependencies": {
6
+ "@wix/dashboard": "^1.3.36",
7
+ "@wix/dashboard-react": "^1.0.26",
8
+ "@wix/design-system": "^1.214.1",
9
+ "@wix/patterns": "^1.265.0",
10
+ "@wix/stores": "^1.0.507",
11
+ "@wix/wix-ui-icons-common": "^3.0.0"
12
+ },
13
+ "devDependencies": {
14
+ "@types/react": "^16.0.0",
15
+ "@types/react-dom": "^16.0.0",
16
+ "@wix/cli": "^1.0.0",
17
+ "@wix/cli-app": "^1.0.0",
18
+ "@wix/sdk-types": "^1.0.0",
19
+ "react": "16.14.0",
20
+ "react-dom": "16.14.0",
21
+ "typescript": "~5.8.2"
22
+ },
23
+ "scripts": {
24
+ "wix": "wix",
25
+ "build": "wix app build",
26
+ "release": "wix app release",
27
+ "dev": "wix app dev",
28
+ "preview": "wix app preview",
29
+ "generate": "wix app generate",
30
+ "logs": "wix app logs",
31
+ "typecheck": "tsc --noEmit"
32
+ }
33
+ }
@@ -0,0 +1,54 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import {
3
+ Modal,
4
+ CustomModalLayout,
5
+ FormField,
6
+ Input,
7
+ } from '@wix/design-system';
8
+ import '@wix/design-system/styles.global.css';
9
+
10
+ export function CreateProductModal({ showModal, onSave }: { showModal: boolean, onSave: (name: string) => void }) {
11
+ const [productName, setProductName] = useState('');
12
+ const [shown, setShown] = useState(showModal);
13
+
14
+ useEffect(() => {
15
+ setShown(showModal);
16
+ }, [showModal])
17
+
18
+ const toggleModal = () => {
19
+ setShown(!shown);
20
+ setProductName('');
21
+ };
22
+
23
+ return (
24
+ <Modal
25
+ isOpen={shown}
26
+ onRequestClose={toggleModal}
27
+ shouldCloseOnOverlayClick
28
+ screen="desktop"
29
+ >
30
+ <CustomModalLayout
31
+ title="Create Product"
32
+ primaryButtonProps={{
33
+ disabled: !productName,
34
+ children: 'Save',
35
+ }}
36
+ primaryButtonOnClick={() => {
37
+ onSave(productName)
38
+ setProductName('')
39
+ }}
40
+ secondaryButtonText="Cancel"
41
+ secondaryButtonOnClick={toggleModal}
42
+ onCloseButtonClick={toggleModal}
43
+ content={
44
+ <FormField label="Name">
45
+ <Input
46
+ value={productName}
47
+ onChange={(e) => setProductName(e.currentTarget.value)}
48
+ />
49
+ </FormField>
50
+ }
51
+ />
52
+ </Modal>
53
+ );
54
+ }
@@ -0,0 +1,60 @@
1
+ import { products } from '@wix/stores';
2
+ import { useCallback } from 'react';
3
+ import { CollectionOptimisticActions } from '@wix/patterns';
4
+
5
+ export function useCreateProduct(optimisticActions: CollectionOptimisticActions<products.Product, {}>) {
6
+ const { createProduct } = products;
7
+
8
+ return useCallback((productName: string) => {
9
+ const newProduct: products.Product = {
10
+ _id: Date().toString(),
11
+ name: productName,
12
+ _createdDate: new Date(),
13
+ lastUpdated: new Date(),
14
+ productType: products.ProductType.physical,
15
+ description: 'New Product Description',
16
+ priceData: {
17
+ currency: 'USD',
18
+ price: 10,
19
+ },
20
+ };
21
+
22
+ optimisticActions.createOne(newProduct, {
23
+ submit: async (products: products.Product[]) => {
24
+ const createdProduct = products[0];
25
+ const response = await createProduct(createdProduct);
26
+ return response.product ? [response.product] : [];
27
+ },
28
+
29
+ successToast: {
30
+ message: `${newProduct.name} was successfully created`,
31
+ type: 'SUCCESS',
32
+ },
33
+ errorToast: () => 'Failed to create product',
34
+ });
35
+ }, [optimisticActions, createProduct]);
36
+ }
37
+
38
+ export function useDeleteProducts(optimisticActions: CollectionOptimisticActions<products.Product, {}>) {
39
+ const { deleteProduct } = products;
40
+
41
+ return useCallback((productsToDelete: products.Product[] ) => {
42
+ optimisticActions.deleteMany(productsToDelete, {
43
+ submit: async (deletedProducts: products.Product[]) => (
44
+ await Promise.all(
45
+ deletedProducts.map((product) => deleteProduct(product._id!))
46
+ )
47
+ ),
48
+
49
+ successToast: {
50
+ message: `${
51
+ productsToDelete.length > 1 ? 'Products' : 'Product'
52
+ } deleted successfully`,
53
+ type: 'SUCCESS',
54
+ },
55
+ errorToast: () => `Failed to delete ${
56
+ productsToDelete.length > 1 ? 'Products' : 'Product'
57
+ }`,
58
+ });
59
+ }, [optimisticActions, deleteProduct]);
60
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "$schema": "https://dev.wix.com/wix-cli/schemas/dashboard-page.json",
3
+ "id": "e50ca567-c401-42a5-a7ef-49c55444d81e",
4
+ "title": "Custom Products Catalog"
5
+ }
@@ -0,0 +1,297 @@
1
+ import React, { useState } from 'react';
2
+ import {
3
+ Box,
4
+ Text,
5
+ Image,
6
+ Breadcrumbs
7
+ } from '@wix/design-system';
8
+ import '@wix/design-system/styles.global.css';
9
+ import { products } from '@wix/stores';
10
+ import { CollectionPage } from '@wix/patterns/page';
11
+ import {
12
+ useTableCollection,
13
+ Table,
14
+ PrimaryPageButton,
15
+ useOptimisticActions,
16
+ deleteSecondaryAction,
17
+ MultiBulkActionToolbar,
18
+ CustomColumns,
19
+ Filter,
20
+ CollectionToolbarFilters,
21
+ dateRangeFilter,
22
+ RangeItem,
23
+ DateRangeFilter,
24
+ RadioGroupFilter,
25
+ stringsArrayFilter,
26
+ } from '@wix/patterns';
27
+ import { withProviders } from '../withProviders';
28
+ import { useCreateProduct, useDeleteProducts } from '../hooks/stores';
29
+ import { CreateProductModal } from '../components/create-product';
30
+
31
+ type TableFilters = {
32
+ productType: Filter<products.ProductType[]>;
33
+ lastUpdated: Filter<RangeItem<Date>>;
34
+ }
35
+
36
+ type SupportedQueryFields = Parameters<products.ProductsQueryBuilder['ascending']>[0] | Parameters<products.ProductsQueryBuilder['descending']>[0]
37
+
38
+ const productTypeToDisplayName: {[key in products.ProductType] : string | undefined} = {
39
+ [products.ProductType.physical]: 'Physical',
40
+ [products.ProductType.digital]: 'Digital',
41
+ [products.ProductType.unspecified_product_type]: undefined
42
+ }
43
+
44
+ function Products() {
45
+ const [shown, setShown] = useState(false);
46
+
47
+ const { queryProducts, deleteProduct } = products;
48
+
49
+ const tableState = useTableCollection<products.Product, TableFilters>({
50
+ queryName: 'products-catalog',
51
+ itemKey: (product: products.Product) => product._id!,
52
+ itemName: (product: products.Product) => product.name!,
53
+ limit: 20,
54
+
55
+ fetchData: (query) => {
56
+ const { limit, offset, search, sort, filters } = query;
57
+ let queryBuilder = queryProducts().limit(limit).skip(offset);
58
+
59
+ if (search) {
60
+ queryBuilder = queryBuilder.startsWith("name", search);
61
+ }
62
+
63
+ if (filters) {
64
+ const { productType, lastUpdated } = filters
65
+
66
+ if (productType) {
67
+ queryBuilder = queryBuilder.in('productType', productType);
68
+ }
69
+
70
+ if (lastUpdated) {
71
+ if (lastUpdated.from) {
72
+ queryBuilder = queryBuilder.gt('lastUpdated', lastUpdated.from);
73
+ }
74
+
75
+ if (lastUpdated.to) {
76
+ queryBuilder = queryBuilder.lt('lastUpdated', lastUpdated.to);
77
+ }
78
+ }
79
+ }
80
+
81
+ if (sort) {
82
+ sort.forEach(s => {
83
+ const fieldName = s.fieldName as SupportedQueryFields;
84
+ if (s.order === 'asc') {
85
+ queryBuilder = queryBuilder.ascending(fieldName);
86
+ } else if (s.order === 'desc') {
87
+ queryBuilder = queryBuilder.descending(fieldName);
88
+ }
89
+ });
90
+ }
91
+
92
+ return queryBuilder.find().then(({ items = [], totalCount: total }) => {
93
+ return {
94
+ items,
95
+ total,
96
+ };
97
+ });
98
+ },
99
+
100
+ fetchErrorMessage: () => 'Error fetching products',
101
+
102
+ filters: {
103
+ lastUpdated: dateRangeFilter(),
104
+ productType: stringsArrayFilter({ itemName: (p) => productTypeToDisplayName[p] ?? p })
105
+ },
106
+ });
107
+
108
+ const optimisticActions = useOptimisticActions(tableState.collection,
109
+ {
110
+ orderBy: () => [],
111
+
112
+ predicate: ({ search, filters }) => {
113
+ return (product) => {
114
+ if (search && !product.name?.startsWith(search)) {
115
+ return false;
116
+ }
117
+
118
+ if (filters.productType && product.productType && filters.productType.indexOf(product.productType) === -1) {
119
+ return false;
120
+ }
121
+
122
+ if (filters.lastUpdated && product.lastUpdated) {
123
+ const from = filters.lastUpdated.from
124
+ const to = filters.lastUpdated.to
125
+ const productLastUpdated = (new Date(product.lastUpdated)).getTime()
126
+
127
+ if (from && productLastUpdated < from.getTime()) {
128
+ return false
129
+ }
130
+
131
+ if (to && productLastUpdated > to.getTime()) {
132
+ return false
133
+ }
134
+ }
135
+
136
+ return true;
137
+ }
138
+ },
139
+ }
140
+ );
141
+
142
+ const createProduct = useCreateProduct(optimisticActions);
143
+
144
+ const deleteProducts = useDeleteProducts(optimisticActions);
145
+
146
+ return (
147
+ <CollectionPage height="100vh">
148
+ <CollectionPage.Header
149
+ title={{ text: 'Products' }}
150
+ breadcrumbs={
151
+ <Breadcrumbs
152
+ activeId="2"
153
+ items={[
154
+ { id: '1', value: 'Apps', disabled: true },
155
+ { id: '2', value: 'Products' },
156
+ ]}
157
+ />
158
+ }
159
+ primaryAction={
160
+ <PrimaryPageButton
161
+ text="Add Product"
162
+ onClick={() => setShown(!shown)}
163
+ />
164
+ }
165
+ />
166
+ <CollectionPage.Content>
167
+ <CreateProductModal showModal={shown} onSave={(productName: string) => {
168
+ createProduct(productName);
169
+ setShown(false);
170
+ }}/>
171
+
172
+ <Table
173
+ state={tableState}
174
+ maxSelection={20}
175
+ filters={
176
+ <CollectionToolbarFilters>
177
+ <RadioGroupFilter
178
+ accordionItemProps={{ label: 'Type' }}
179
+ filter={tableState.collection.filters.productType}
180
+ data={[products.ProductType.physical, products.ProductType.digital]}
181
+ />
182
+ <DateRangeFilter
183
+ filter={tableState.collection.filters.lastUpdated}
184
+ accordionItemProps={{ label: 'Last Updated' }}
185
+ />
186
+ </CollectionToolbarFilters>
187
+ }
188
+
189
+ bulkActionToolbar={({ selectedValues, openConfirmModal }) => {
190
+ const disabled = selectedValues.length > 20;
191
+ return (
192
+ <MultiBulkActionToolbar
193
+ primaryActionItems={[
194
+ {
195
+ label: 'Delete',
196
+ tooltip: disabled
197
+ ? 'Deleting is supported for up to 20 items'
198
+ : undefined,
199
+ disabled,
200
+ onClick: () => {
201
+ openConfirmModal({
202
+ theme: 'destructive',
203
+ primaryButtonOnClick: () => {
204
+ deleteProducts(selectedValues);
205
+ },
206
+ });
207
+ },
208
+ },
209
+ ]}
210
+ />)
211
+ }}
212
+
213
+ customColumns={<CustomColumns />}
214
+ columns={[
215
+ {
216
+ id: 'avatar',
217
+ name: 'Avatar',
218
+ title: '',
219
+ width: '72px',
220
+ render: (product) => <Image src={product.media?.mainMedia?.image?.url}/>,
221
+ reorderDisabled: true,
222
+ hiddenFromCustomColumnsSelection: true
223
+ },
224
+ {
225
+ id: 'name',
226
+ title: 'Product / Description',
227
+ render: (row: products.Product) => (
228
+ <Box direction="vertical" gap="3px">
229
+ <Text size="medium" weight="normal">
230
+ {row.name}
231
+ </Text>
232
+ <Text size="tiny" weight="thin" secondary>
233
+ {row.description}
234
+ </Text>
235
+ </Box>
236
+ ),
237
+ width: 'auto',
238
+ reorderDisabled: true,
239
+ hideable: false
240
+ },
241
+ {
242
+ id: 'price',
243
+ title: 'Price',
244
+ render: (row: products.Product) => `$${row.priceData?.price}`,
245
+ width: '100px',
246
+ sortable: true,
247
+ },
248
+ {
249
+ id: 'type',
250
+ title: 'Type',
251
+ render: (row: products.Product) => {
252
+ if (!row.productType) {
253
+ return ''
254
+ }
255
+
256
+ return productTypeToDisplayName[row.productType] ?? row.productType
257
+ },
258
+ width: '100px',
259
+ },
260
+ {
261
+ id: 'last-updated',
262
+ title: 'Last Updated',
263
+ render: (row: products.Product) =>
264
+ row.lastUpdated
265
+ ? new Date(row.lastUpdated).toLocaleDateString()
266
+ : '',
267
+ width: '100px',
268
+ defaultHidden: true,
269
+ },
270
+ ]}
271
+
272
+ actionCell={(_product, _index, actionCellAPI) => ({
273
+ secondaryActions: [
274
+ deleteSecondaryAction({
275
+ optimisticActions,
276
+ actionCellAPI,
277
+ submit: (products: products.Product[]) => (
278
+ Promise.all(
279
+ products.map((product: products.Product) => deleteProduct(product._id!))
280
+ )
281
+ ),
282
+ successToast: {
283
+ message: `${_product.name} deleted successfully.`,
284
+ type: 'SUCCESS',
285
+ },
286
+ errorToast: () => 'Product deletion failed.',
287
+ }),
288
+ ]
289
+ }
290
+ )}
291
+ />
292
+ </CollectionPage.Content>
293
+ </CollectionPage>
294
+ );
295
+ }
296
+
297
+ export default withProviders(Products);
@@ -0,0 +1,18 @@
1
+ <svg width="166" height="64" viewBox="0 0 166 64" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g clip-path="url(#clip0_14809_9463)">
3
+ <path
4
+ d="M165.304 0H156.173C153.64 0 151.273 1.25433 149.85 3.35199L137.639 21.3662C137.313 21.844 136.608 21.844 136.283 21.3662L124.071 3.35199C122.651 1.25433 120.281 0 117.748 0H108.617L130.371 32.0894L108.737 64H117.868C120.401 64 122.769 62.7457 124.192 60.648L136.283 42.8126C136.608 42.3349 137.313 42.3349 137.639 42.8126L149.73 60.648C151.15 62.7457 153.52 64 156.053 64H165.184L143.551 32.0894L165.304 0Z"
5
+ fill="black" />
6
+ <path
7
+ d="M89.8281 6.54652V64H94.1922C97.8088 64 100.74 61.0697 100.74 57.4535V0H96.3755C92.7588 0 89.8281 2.93032 89.8281 6.54652Z"
8
+ fill="black" />
9
+ <path
10
+ d="M81.8276 0H77.944C73.6681 0 69.9633 2.95701 69.0158 7.12564L60.3278 45.3185L52.7234 9.66632C51.3168 3.0771 44.5559 -1.36641 37.6375 0.544431C33.2307 1.76139 29.9637 5.48434 29.0108 9.95455L21.4839 45.2705L12.8118 7.12831C11.8616 2.95968 8.15687 0 3.88092 0H0L14.5548 63.9973H20.0692C25.0738 63.9973 29.3978 60.4986 30.4415 55.604L39.7461 11.9401C39.8608 11.3984 40.3466 11.006 40.8991 11.006C41.4516 11.006 41.9374 11.3984 42.0522 11.9401L51.3648 55.6067C52.4084 60.5012 56.7324 63.9973 61.7371 63.9973H67.2702L81.8276 0Z"
11
+ fill="black" />
12
+ </g>
13
+ <defs>
14
+ <clipPath id="clip0_14809_9463">
15
+ <rect width="165.305" height="64" fill="white" />
16
+ </clipPath>
17
+ </defs>
18
+ </svg>
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import { WixDesignSystemProvider } from '@wix/design-system';
3
+ import { WixPatternsProvider } from '@wix/patterns/provider';
4
+ import { withDashboard } from '@wix/dashboard-react';
5
+
6
+ export function withProviders<P extends {} = {}>(Component: React.FC<P>) {
7
+ return withDashboard(function DashboardProviders(props: P) {
8
+ return (
9
+ <WixDesignSystemProvider>
10
+ <WixPatternsProvider>
11
+ <Component {...props} />
12
+ </WixPatternsProvider>
13
+ </WixDesignSystemProvider>
14
+ );
15
+ });
16
+ }
@@ -0,0 +1,4 @@
1
+ /// <reference types="@wix/cli-app/client" />
2
+ /// <reference types="@wix/sdk-types/client" />
3
+
4
+ // NOTE: This file should not be edited. This is an auto-generated file.
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "@wix/cli-app/tsconfig.app.json",
3
+ "compilerOptions": {
4
+ "rootDir": "src",
5
+ "types": ["react"]
6
+ },
7
+ "include": ["src"]
8
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "$schema": "https://dev.wix.com/wix-cli/schemas/wix-config.json",
3
+ "appId": "04f0b8cf-a46f-46c1-bdab-d65e62e05de3",
4
+ "projectId": "custom-products-catalog"
5
+ }
@@ -0,0 +1 @@
1
+ 22.10.0
@@ -0,0 +1,21 @@
1
+ # inventory-countdown
2
+
3
+ This project was bootstrapped with [Create Wix App](https://www.npmjs.com/package/@wix/create-app).
4
+ Read more about it in the [Wix CLI for Apps
5
+ documentation](https://dev.wix.com/docs/build-apps/developer-tools/cli/get-started/about-the-wix-cli-for-apps).
6
+
7
+ ## Setup 🔧
8
+
9
+ ##### Install dependencies:
10
+
11
+ ```console
12
+ npm install
13
+ ```
14
+
15
+ ## Available Scripts
16
+
17
+ In the project directory, you can run:
18
+
19
+ ```console
20
+ npm run dev
21
+ ```