@dashadmin/dash-admin 1.3.72 → 1.3.74-srcfree.1

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 (289) hide show
  1. package/dist/components/tenant/TenancyPlan.js +307 -0
  2. package/dist/systemResources.js +18 -2
  3. package/package.json +25 -22
  4. package/src/AppAsyncWrapper.tsx +0 -42
  5. package/src/AppWrapper.tsx +0 -45
  6. package/src/DASHAdmin.tsx +0 -502
  7. package/src/DASHAdmin.tsx.old +0 -456
  8. package/src/RoutingWrapper.tsx +0 -143
  9. package/src/classes/DASHStorageClass.tsx +0 -8
  10. package/src/components/Input/RichTextField.tsx +0 -27
  11. package/src/components/Redirect.tsx +0 -46
  12. package/src/components/avatar/Avatar.tsx +0 -71
  13. package/src/components/avatar/SingleImageUploader.tsx +0 -107
  14. package/src/components/currency/Format.tsx +0 -79
  15. package/src/components/custom/Redirect.tsx +0 -23
  16. package/src/components/error/Error.tsx +0 -168
  17. package/src/components/geocoding/GeocodingField.tsx +0 -167
  18. package/src/components/i18n/BridgedLocalesMenuButton.tsx +0 -160
  19. package/src/components/i18n/LangSwitcher.tsx +0 -204
  20. package/src/components/loader/GlobalLoader.tsx +0 -49
  21. package/src/components/logs/LogFile.tsx +0 -88
  22. package/src/components/logs/LogFileById.tsx +0 -68
  23. package/src/components/logs/LogViewer.tsx +0 -43
  24. package/src/components/menu/AppMenu.tsx +0 -22
  25. package/src/components/menu/CustomMenuItemLink.tsx +0 -61
  26. package/src/components/menu/DarkToggleMode.tsx +0 -65
  27. package/src/components/menu/LanguageToggleMode.tsx +0 -120
  28. package/src/components/misc/CustomImageInput.tsx +0 -62
  29. package/src/components/misc/DASHGlobalErrorHandler.tsx +0 -194
  30. package/src/components/misc/DarkModeSwitcher.tsx +0 -112
  31. package/src/components/misc/HorizontalScroller.tsx +0 -225
  32. package/src/components/misc/LanguageSwitcher.tsx +0 -199
  33. package/src/components/misc/MUIHtmlToolTip.tsx +0 -15
  34. package/src/components/misc/MuiSimpleJsonTable.tsx +0 -279
  35. package/src/components/misc/MultiLevelTable.tsx +0 -229
  36. package/src/components/misc/NoResults.tsx +0 -28
  37. package/src/components/misc/PDFViewer.tsx +0 -85
  38. package/src/components/navigation/Breadcrumbs.tsx +0 -220
  39. package/src/components/navigation/BreadcrumbsManager.tsx +0 -310
  40. package/src/components/navigation/index.tsx +0 -5
  41. package/src/components/panel/Error.tsx +0 -168
  42. package/src/components/permission/AvailablePermissionsContext.tsx +0 -173
  43. package/src/components/permission/PermissionsSelector.tsx +0 -834
  44. package/src/components/permission/PermissionsSelectorList.tsx +0 -473
  45. package/src/components/permission/tsx +0 -0
  46. package/src/components/racustombuttons/CustomRAButton.tsx +0 -87
  47. package/src/components/racustombuttons/QuickButton.tsx +0 -117
  48. package/src/components/racustombuttons/QuickEditButton.tsx +0 -115
  49. package/src/components/racustombuttons/QuickIconButton.tsx +0 -122
  50. package/src/components/scrollbar/Scrollbar.tsx +0 -31
  51. package/src/components/selects/MultiSelect.tsx +0 -53
  52. package/src/components/selects/RASearchableSelect.tsx +0 -282
  53. package/src/components/selects/RASearchableSelectChips.tsx +0 -308
  54. package/src/components/selects/SearchableSelect.tsx +0 -139
  55. package/src/components/serviceAccount/ApiKeyRevealDialog.tsx +0 -129
  56. package/src/components/serviceAccount/ServiceAccountStatusSwitch.tsx +0 -99
  57. package/src/components/subscription/BillingCycleSelectInput.tsx +0 -68
  58. package/src/components/subscription/PlanAddonsSettings.tsx +0 -563
  59. package/src/components/subscription/PlanAuditLog.tsx +0 -453
  60. package/src/components/subscription/PlanFeaturesSettings.tsx +0 -243
  61. package/src/components/subscription/PlanLimitsSettings.tsx +0 -230
  62. package/src/components/subscription/PlanMetadataSettings.tsx +0 -306
  63. package/src/components/subscription/PlanPricesSettings.tsx +0 -307
  64. package/src/components/subscription/index.ts +0 -7
  65. package/src/components/svgelements/SvgLoading.tsx +0 -229
  66. package/src/components/svgelements/SvgLogo.tsx +0 -53
  67. package/src/components/svgelements/SvgLogoMin.tsx +0 -64
  68. package/src/components/svgelements/SvgShipping.tsx +0 -673
  69. package/src/components/tenancy/GlobalTenantWrapper.tsx +0 -84
  70. package/src/components/tenancy/TenantSwitcher.tsx +0 -514
  71. package/src/components/tenant/AvailablePermissionsContext.tsx +0 -0
  72. package/src/components/tenant/SettingsSections.tsx +0 -151
  73. package/src/components/tenant/TenancySettings.tsx +0 -122
  74. package/src/components/tenant/TenantAttributes.tsx +0 -153
  75. package/src/components/tenant/TenantAttributesContext.tsx +0 -163
  76. package/src/components/tenant/TenantSelector.tsx +0 -142
  77. package/src/components/tenant/TenantSettings.tsx +0 -184
  78. package/src/components/tenant/TenantSettingsContext.tsx +0 -165
  79. package/src/components/tenant/TenantTheme.tsx +0 -172
  80. package/src/components/user/AvatarComponent.tsx +0 -317
  81. package/src/components/user/TenantAvatarComponent.tsx +0 -99
  82. package/src/components/user/UserPreferences.tsx +0 -677
  83. package/src/config/ACTIONS.tsx +0 -26
  84. package/src/config/ConstantsService.tsx +0 -44
  85. package/src/config/DASHAdminSystemConstants.tsx +0 -183
  86. package/src/config/PARSERS.tsx +0 -9
  87. package/src/contexts/DashQueryClientContext.tsx +0 -113
  88. package/src/contexts/DashResourceContext.tsx +0 -34
  89. package/src/contexts/I18nBridgeContext.tsx +0 -156
  90. package/src/contexts/I18nBridgeSetter.tsx +0 -39
  91. package/src/contexts/I18nReduxSync.tsx +0 -27
  92. package/src/contexts/SubscriptionPlanFormatsProvider.tsx +0 -217
  93. package/src/contexts/SystemRequestsCache.tsx +0 -215
  94. package/src/contexts/auth/AuthContext.tsx +0 -567
  95. package/src/contexts/auth/AuthContextLocalStorage.tsx +0 -140
  96. package/src/contexts/auth/DASHAuthenticationService.tsx +0 -915
  97. package/src/contexts/auth/WindowContext.tsx +0 -15
  98. package/src/contexts/auth/index.tsx +0 -3
  99. package/src/contexts/com/FCMContext.tsx +0 -415
  100. package/src/contexts/com/LaravelEchoContext.tsx +0 -41
  101. package/src/contexts/com/LaravelEchoMgr.tsx +0 -155
  102. package/src/contexts/com/components/DefaultNotificationComponent.tsx +0 -20
  103. package/src/contexts/com/components/EchoNotificationsCenter.tsx +0 -65
  104. package/src/contexts/com/components/NotificationAttributesTable.tsx +0 -54
  105. package/src/contexts/com/components/NotificationRenderer.tsx +0 -42
  106. package/src/contexts/com/components/NotificationsWidget.tsx +0 -182
  107. package/src/contexts/com/components/notificationFormats.tsx +0 -50
  108. package/src/contexts/com/useLaravelEcho.tsx +0 -432
  109. package/src/contexts/dictionary/DictionaryContext.tsx +0 -94
  110. package/src/declarations.d.ts +0 -17
  111. package/src/default-theme/DASHAppProviders.tsx +0 -117
  112. package/src/default-theme/DashThemeContext.tsx +0 -209
  113. package/src/default-theme/DashThemeContext.tsx.fast +0 -143
  114. package/src/default-theme/DashThemeContext.tsx.old +0 -306
  115. package/src/default-theme/DashThemeHelperProvider.tsx +0 -98
  116. package/src/default-theme/DomainAppLayout.tsx +0 -166
  117. package/src/default-theme/DomainHeader.tsx +0 -162
  118. package/src/default-theme/DomainTheme.tsx +0 -59
  119. package/src/default-theme/FullLayoutMarkup.tsx +0 -231
  120. package/src/default-theme/StaticLayout.tsx +0 -47
  121. package/src/default-theme/index.tsx +0 -11
  122. package/src/default-theme/menu/AppDashboardGrid.tsx +0 -279
  123. package/src/default-theme/menu/AppMaterialMenu.tsx +0 -546
  124. package/src/default-theme/menu/AppMenuComponents/SubmenuPortal.tsx +0 -61
  125. package/src/default-theme/menu/AppMenuComponents/collapsed/CollapsedSidebarItem.tsx +0 -264
  126. package/src/default-theme/menu/AppMenuComponents/collapsed/CollapsedSidebarItems.tsx +0 -31
  127. package/src/default-theme/menu/AppMenuComponents/expanded/CollapsableSidebarMenu.tsx +0 -293
  128. package/src/default-theme/menu/AppMenuComponents/expanded/SidebarItem.tsx +0 -92
  129. package/src/default-theme/menu/AppMenuComponents/getItem.tsx +0 -17
  130. package/src/default-theme/menu/AppMenuComponents/interfaces.tsx +0 -41
  131. package/src/default-theme/menu/AppMenuComponents/submenuConstants.ts +0 -90
  132. package/src/default-theme/menu/AppSidebarMaterial.tsx +0 -339
  133. package/src/default-theme/menu/SidebarActions.tsx +0 -84
  134. package/src/default-theme/updateDomCssVariables.tsx +0 -176
  135. package/src/helpers/checkRole.tsx +0 -66
  136. package/src/helpers/parseAxiosError.tsx +0 -41
  137. package/src/hooks/audio/useAudio.tsx +0 -39
  138. package/src/hooks/axios.tsx +0 -165
  139. package/src/hooks/data/useDashboardStats.tsx +0 -65
  140. package/src/hooks/data/usePackageByClientsStats.tsx +0 -44
  141. package/src/hooks/data/usePackageByCommunesStats.tsx +0 -44
  142. package/src/hooks/data/usePackageStats.tsx +0 -69
  143. package/src/hooks/data/usePackageWithdrawDetails.tsx +0 -61
  144. package/src/hooks/data/useStats.tsx +0 -86
  145. package/src/hooks/isCurrentPath.tsx +0 -22
  146. package/src/hooks/notifications/WSMessagesManager.tsx +0 -152
  147. package/src/hooks/notifications/WSPusherManager.tsx +0 -92
  148. package/src/hooks/useBreadcrumbs.tsx +0 -329
  149. package/src/hooks/useClickOutside.tsx +0 -57
  150. package/src/hooks/useFormPersistance.tsx +0 -150
  151. package/src/hooks/useGlobalErrorMediator.tsx +0 -43
  152. package/src/hooks/useGlobalLoaderMgr.tsx +0 -21
  153. package/src/hooks/useHash.tsx +0 -27
  154. package/src/hooks/useLocalStorage.tsx +0 -196
  155. package/src/hooks/usePolyglotTranslation.tsx +0 -62
  156. package/src/hooks/usePrevious.tsx +0 -9
  157. package/src/hooks/usePrintSelected.tsx +0 -37
  158. package/src/hooks/useVirtualHash.tsx +0 -33
  159. package/src/hooks/window/useWindowSize.tsx +0 -36
  160. package/src/index.tsx +0 -134
  161. package/src/interfaces/IAppResourceConfig.tsx +0 -20
  162. package/src/interfaces/Log.tsx +0 -16
  163. package/src/interfaces/Tenant.tsx +0 -25
  164. package/src/interfaces/communication/IActions.tsx +0 -5
  165. package/src/interfaces/communication/INotification.tsx +0 -21
  166. package/src/interfaces/communication/IPayload.tsx +0 -3
  167. package/src/interfaces/communication/IRequestAction.tsx +0 -10
  168. package/src/interfaces/communication/IRequestPayload.tsx +0 -7
  169. package/src/interfaces/communication/IResponseAction.tsx +0 -7
  170. package/src/interfaces/misc/IAny.tsx +0 -3
  171. package/src/interfaces/misc/IFlashMessage.tsx +0 -10
  172. package/src/interfaces/navigation/IAppMenu.ts +0 -14
  173. package/src/interfaces/navigation/ICollapsableSidebarMenu.ts +0 -12
  174. package/src/interfaces/navigation/IMenuItem.ts +0 -16
  175. package/src/interfaces/notifications/IModel.tsx +0 -6
  176. package/src/interfaces/notifications/IModelField.tsx +0 -8
  177. package/src/interfaces/notifications/IUserNotification.tsx +0 -12
  178. package/src/interfaces/notifications/IUserNotificationData.tsx +0 -13
  179. package/src/interfaces/notifications/IUserNotificationPayload.tsx +0 -8
  180. package/src/interfaces/user/IGetAuth.tsx +0 -92
  181. package/src/interfaces/user/ITenantSettings.tsx +0 -3
  182. package/src/interfaces/user/IUser.tsx +0 -60
  183. package/src/interfaces/user/IUserSettings.tsx +0 -43
  184. package/src/interfaces.tsx +0 -6
  185. package/src/layout/AppLayout.tsx +0 -112
  186. package/src/layout/ApplicationLayout.tsx +0 -197
  187. package/src/layout/MotionWrapper.original.tsx +0 -236
  188. package/src/layout/MotionWrapper.tsx +0 -236
  189. package/src/layout/ResourceMenu.tsx +0 -164
  190. package/src/layout/ResoureLayout.tsx +0 -105
  191. package/src/layout/TransitionWrapper.tsx +0 -125
  192. package/src/pages/ChangePassword.tsx +0 -179
  193. package/src/pages/DASHLanding.tsx +0 -22
  194. package/src/pages/DASHLightWeightLogin.tsx +0 -611
  195. package/src/pages/DASHSimpleLogin.tsx +0 -260
  196. package/src/pages/Login.tsx +0 -111
  197. package/src/pages/Profile.tsx +0 -357
  198. package/src/pages/RecoverPassword.tsx +0 -175
  199. package/src/pages/SingleImageUploader.tsx +0 -55
  200. package/src/pages/VerifyAccount.tsx +0 -128
  201. package/src/providers/authProvider.tsx +0 -217
  202. package/src/providers/dataProvider.tsx +0 -672
  203. package/src/providers/i18n/en.ts +0 -646
  204. package/src/providers/i18n/es.ts +0 -652
  205. package/src/providers/i18n/languages.tsx +0 -8
  206. package/src/providers/i18n/mergeTranslations.ts +0 -53
  207. package/src/providers/i18nProvider.tsx +0 -23
  208. package/src/react-admin-dash/RADashComponent.tsx +0 -240
  209. package/src/react-admin-dash/Resource.tsx +0 -77
  210. package/src/resources/Brand/BrandResource.tsx +0 -130
  211. package/src/resources/DASHResourceLoader.ts +0 -180
  212. package/src/resources/Log/LogResource.tsx +0 -73
  213. package/src/resources/Tenant/ImpersonateTenantResource.tsx +0 -113
  214. package/src/resources/Trash/TrashTemplate.tsx +0 -180
  215. package/src/resources/User/components/AvatarUploadField.tsx +0 -57
  216. package/src/resources/User/components/PasswordFields.tsx +0 -73
  217. package/src/resources/User/getProfileMenu.ts +0 -57
  218. package/src/resources/User/profileResource.tsx +0 -51
  219. package/src/resources/User/userLayout.tsx +0 -62
  220. package/src/resources/User/userResource.tsx +0 -111
  221. package/src/resources/User/userSchema.tsx +0 -213
  222. package/src/resources/User/usersFilters.tsx +0 -21
  223. package/src/resources.tsx +0 -280
  224. package/src/schemas/log.tsx +0 -45
  225. package/src/schemas/notification.tsx +0 -42
  226. package/src/schemas/permissions.tsx +0 -44
  227. package/src/schemas/roles.tsx +0 -48
  228. package/src/schemas/rolesDataGrid.tsx +0 -48
  229. package/src/schemas/subscription/components/SubscriptionActions.tsx +0 -153
  230. package/src/schemas/subscription/components/SubscriptionPaymentHistory.tsx +0 -127
  231. package/src/schemas/subscription/components/SubscriptionPlanFeatures.tsx +0 -162
  232. package/src/schemas/subscription/components/SubscriptionPlanPreview.tsx +0 -141
  233. package/src/schemas/subscription/components/SubscriptionPlanStats.tsx +0 -318
  234. package/src/schemas/subscription/components/SubscriptionStatusIndicator.tsx +0 -72
  235. package/src/schemas/subscription/subscriptionPlanSchema.tsx +0 -185
  236. package/src/schemas/subscription/subscriptionSchema.tsx +0 -152
  237. package/src/schemas/subscriptionPlan.ts +0 -422
  238. package/src/schemas/tenant.tsx +0 -129
  239. package/src/schemas/tenantUser.tsx +0 -96
  240. package/src/schemas/tenant_superadmin.tsx +0 -119
  241. package/src/schemas/user.tsx +0 -26
  242. package/src/systemResources.old.tsx +0 -928
  243. package/src/systemResources.tsx +0 -1369
  244. package/src/templates/ResourceTemplate.tsx +0 -240
  245. package/src/templates/ResourceTemplate.tsx.memoized_experiment +0 -350
  246. package/src/templates/ResourceTemplate.tsx.original +0 -396
  247. package/src/templates/ResourceTemplateCreate.tsx +0 -182
  248. package/src/templates/ResourceTemplateEdit.tsx +0 -176
  249. package/src/templates/ResourceTemplateFull.tsx +0 -581
  250. package/src/templates/ResourceTemplateList.tsx +0 -340
  251. package/src/templates/ResourceTemplateOld.tsx.bkup +0 -567
  252. package/src/templates/ResourceTemplateShow.tsx +0 -88
  253. package/src/templates/TrashTemplate.tsx +0 -179
  254. package/src/tenantResources.tsx +0 -223
  255. package/src/test_portal_bubbles.tsx +0 -40
  256. package/src/theme/AppHeader.tsx +0 -52
  257. package/src/theme/AppLayoutSetting.tsx +0 -33
  258. package/src/theme/AppLogo.tsx +0 -13
  259. package/src/theme/AppSidebar.tsx +0 -12
  260. package/src/theme/AppSidebarContent.tsx +0 -105
  261. package/src/theme/AppSidebarLogo.tsx +0 -48
  262. package/src/theme/components/PageTitle.tsx +0 -37
  263. package/src/utils/cache/CacheInvalidatorContext.tsx +0 -125
  264. package/src/utils/cache/CacheInvalidatorListenerComponent.tsx +0 -10
  265. package/src/utils/cache/useCacheInvalidatorListener.tsx +0 -27
  266. package/src/utils/convertFileToBase64.tsx +0 -9
  267. package/src/utils/convertToFile.tsx +0 -14
  268. package/src/utils/cookies.tsx +0 -33
  269. package/src/utils/dashDefaultQueryClient.tsx +0 -34
  270. package/src/utils/dataUrlToBlob.tsx +0 -30
  271. package/src/utils/deepReplace.tsx +0 -19
  272. package/src/utils/getProfileMenu.tsx +0 -41
  273. package/src/utils/getTenantSettings.tsx +0 -9
  274. package/src/utils/getType.tsx +0 -8
  275. package/src/utils/getUserSettings.tsx +0 -8
  276. package/src/utils/hasCode.tsx +0 -14
  277. package/src/utils/index.ts +0 -19
  278. package/src/utils/injectTenantStyles.ts +0 -28
  279. package/src/utils/isComponent.tsx +0 -45
  280. package/src/utils/navEvents.tsx +0 -91
  281. package/src/utils/prototypes.tsx +0 -5
  282. package/src/utils/regexp.tsx +0 -4
  283. package/src/utils/resolveObjectPath.tsx +0 -4
  284. package/src/utils/setNativeValue.tsx +0 -24
  285. package/src/utils/slugify.tsx +0 -11
  286. package/src/utils/validators/emailValidator.tsx +0 -6
  287. package/src/utils/validators/requiredValidator.tsx +0 -5
  288. package/src/utils/validators/rutValidator.tsx +0 -31
  289. package/src/utils/validators.tsx +0 -96
@@ -1,68 +0,0 @@
1
- import React from 'react';
2
- import { SelectInput } from 'react-admin';
3
- import { Box, CircularProgress, Alert } from '@mui/material';
4
- import { usePaymentGatewayCapabilities } from 'dash-web/src/hooks/usePaymentGatewayCapabilities';
5
-
6
- /**
7
- * Billing Cycle Select Input
8
- *
9
- * Dynamically filters billing cycle options based on the active payment gateway's capabilities.
10
- * This ensures users can only select billing cycles that are supported by their payment gateway.
11
- */
12
- const BillingCycleSelectInput: React.FC = () => {
13
- const { supportedBillingCycles, isLoading, gatewayName } = usePaymentGatewayCapabilities();
14
-
15
- // All possible billing cycles with user-friendly labels
16
- const allBillingCycles = [
17
- { id: 'daily', name: 'Daily' },
18
- { id: 'weekly', name: 'Weekly' },
19
- { id: 'monthly', name: 'Monthly' },
20
- { id: 'yearly', name: 'Yearly' },
21
- ];
22
-
23
- if (isLoading) {
24
- return (
25
- <Box sx={{ display: 'flex', alignItems: 'center', gap: 2, my: 2 }}>
26
- <CircularProgress size={20} />
27
- <span>Loading payment gateway capabilities...</span>
28
- </Box>
29
- );
30
- }
31
-
32
- // Filter choices based on gateway capabilities
33
- const filteredChoices = allBillingCycles.filter(cycle =>
34
- supportedBillingCycles.includes(cycle.id)
35
- );
36
-
37
- // Get unsupported cycles for info message
38
- const unsupportedCycles = allBillingCycles
39
- .filter(cycle => !supportedBillingCycles.includes(cycle.id))
40
- .map(c => c.name);
41
-
42
- return (
43
- <Box>
44
- <SelectInput
45
- source="billing_cycle"
46
- label="Billing Cycle"
47
- choices={filteredChoices}
48
- fullWidth
49
- defaultValue="monthly"
50
- helperText={
51
- gatewayName
52
- ? `Available cycles for ${gatewayName}`
53
- : 'Select billing cycle for this plan'
54
- }
55
- validate={(value) => !value ? 'Required' : undefined}
56
- />
57
-
58
- {unsupportedCycles.length > 0 && (
59
- <Alert severity="info" sx={{ mt: 1 }}>
60
- Note: {unsupportedCycles.join(', ')} billing cycle
61
- {unsupportedCycles.length > 1 ? 's are' : ' is'} not supported by your current payment gateway ({gatewayName}).
62
- </Alert>
63
- )}
64
- </Box>
65
- );
66
- };
67
-
68
- export default BillingCycleSelectInput;
@@ -1,563 +0,0 @@
1
- import { DashAutoFormTabs, IDashAutoAdminCustomFieldComponent } from "dash-auto-admin";
2
- import React, { useState, useEffect, useCallback } from "react";
3
- import { Loading, useRecordContext } from "react-admin";
4
- import { useFormContext, useWatch, Controller } from "react-hook-form";
5
- import MUISimpleJsonTable from "../misc/MuiSimpleJsonTable";
6
- import { useSubscriptionPlanFormats } from "../../contexts/SubscriptionPlanFormatsProvider";
7
- import {
8
- Box,
9
- Switch,
10
- FormControlLabel,
11
- TextField,
12
- Typography,
13
- Paper,
14
- Grid,
15
- Chip,
16
- InputAdornment,
17
- Collapse,
18
- Divider
19
- } from "@mui/material";
20
- import { priceFormatter } from 'dash-utils';
21
-
22
- /**
23
- * PlanAddonsSettings Component
24
- *
25
- * A dynamic form component for managing subscription plan add-ons with pricing.
26
- * Add-ons are specific integrations (marketplaces, POS systems) that can be
27
- * individually enabled/disabled per subscription plan, with configurable prices per currency.
28
- *
29
- * Usage:
30
- * - In edit mode: Renders form fields for each add-on defined in subscription_plans.addon_formats
31
- * with toggle switch and price inputs for each currency
32
- * - In view mode: Displays the current add-ons with their prices as a table
33
- * - In create mode: Renders form fields with default values
34
- *
35
- * Add-on naming convention:
36
- * - marketplace_{name}: Marketplace integrations (e.g., marketplace_ubereats)
37
- * - pos_{name}: Point of Sale integrations (e.g., pos_transbank)
38
- */
39
-
40
- interface AddonFormat {
41
- id: string;
42
- group: string;
43
- tab: string;
44
- attribute: string;
45
- label: string;
46
- visible: boolean;
47
- required: boolean;
48
- type: 'boolean' | 'integer' | 'string' | 'select';
49
- editable: boolean;
50
- rules: string;
51
- default_value: any;
52
- description?: string;
53
- service_class?: string | null;
54
- icon?: string;
55
- prices?: Record<string, number>;
56
- }
57
-
58
- interface SubscriptionPlan {
59
- id: number;
60
- name: string;
61
- slug: string;
62
- addons?: Record<string, boolean>;
63
- addon_prices?: Record<string, Record<string, number>>;
64
- flow_addon_items?: Record<string, number>;
65
- [key: string]: any;
66
- }
67
-
68
- // Default currencies - should match backend config
69
- const AVAILABLE_CURRENCIES = ['CLP', 'USD'];
70
- const DEFAULT_CURRENCY = 'CLP';
71
-
72
- // Currency display configuration
73
- const CURRENCY_CONFIG: Record<string, { symbol: string; decimals: number; name: string }> = {
74
- CLP: { symbol: '$', decimals: 0, name: 'Chilean Peso' },
75
- USD: { symbol: '$', decimals: 2, name: 'US Dollar' },
76
- };
77
-
78
- /**
79
- * Single addon row component with toggle and price inputs
80
- */
81
- interface AddonRowProps {
82
- addonId: string;
83
- entry: AddonFormat;
84
- plan?: SubscriptionPlan;
85
- mode: 'edit' | 'create' | 'view';
86
- }
87
-
88
- const AddonRow: React.FC<AddonRowProps> = ({ addonId, entry, plan, mode }) => {
89
- const { control, setValue, watch } = useFormContext();
90
-
91
- // Watch the enabled state for this addon
92
- const isEnabled = watch(`addons.${addonId}`) ?? entry.default_value ?? false;
93
-
94
- // Watch prices for this addon
95
- const addonPrices = watch(`addon_prices.${addonId}`) ?? plan?.addon_prices?.[addonId] ?? {};
96
-
97
- const handleToggle = useCallback((checked: boolean) => {
98
- setValue(`addons.${addonId}`, checked, { shouldDirty: true });
99
-
100
- // Initialize prices if enabling for the first time
101
- if (checked && Object.keys(addonPrices).length === 0) {
102
- const defaultPrices: Record<string, number> = {};
103
- AVAILABLE_CURRENCIES.forEach(currency => {
104
- defaultPrices[currency] = entry.prices?.[currency] ?? 0;
105
- });
106
- setValue(`addon_prices.${addonId}`, defaultPrices, { shouldDirty: true });
107
- }
108
- }, [addonId, addonPrices, entry.prices, setValue]);
109
-
110
- const handlePriceChange = useCallback((currency: string, value: string) => {
111
- const numericValue = parseInt(value.replace(/[^0-9]/g, ''), 10) || 0;
112
- setValue(`addon_prices.${addonId}.${currency}`, numericValue, { shouldDirty: true });
113
- }, [addonId, setValue]);
114
-
115
- const formatPrice = (price: number, currency: string): string => {
116
- return priceFormatter(price, currency);
117
- };
118
-
119
- const isReadOnly = mode === 'view';
120
-
121
- return (
122
- <Paper
123
- elevation={1}
124
- sx={{
125
- p: 2,
126
- mb: 2,
127
- borderLeft: isEnabled ? '4px solid #4caf50' : '4px solid #e0e0e0',
128
- transition: 'border-color 0.3s'
129
- }}
130
- >
131
- <Grid container spacing={2} sx={{
132
- alignItems: "flex-start"
133
- }}>
134
- {/* Toggle and Label */}
135
- <Grid item xs={12} md={4}>
136
- <Controller
137
- name={`addons.${addonId}`}
138
- control={control}
139
- defaultValue={entry.default_value ?? false}
140
- render={({ field }) => (
141
- <FormControlLabel
142
- control={
143
- <Switch
144
- checked={field.value ?? false}
145
- onChange={(e) => {
146
- field.onChange(e.target.checked);
147
- handleToggle(e.target.checked);
148
- }}
149
- disabled={isReadOnly}
150
- color="primary"
151
- />
152
- }
153
- label={
154
- <Box>
155
- <Typography variant="subtitle1" sx={{
156
- fontWeight: "medium"
157
- }}>
158
- {entry.icon && <span style={{ marginRight: 8 }}>{entry.icon}</span>}
159
- {entry.label}
160
- </Typography>
161
- {entry.description && (
162
- <Typography variant="caption" sx={{
163
- color: "text.secondary"
164
- }}>
165
- {entry.description}
166
- </Typography>
167
- )}
168
- </Box>
169
- }
170
- />
171
- )}
172
- />
173
- {entry.service_class && (
174
- <Chip
175
- label="Has Service Class"
176
- size="small"
177
- variant="outlined"
178
- sx={{ mt: 1 }}
179
- />
180
- )}
181
- </Grid>
182
-
183
- {/* Price Inputs - Show when enabled */}
184
- <Grid item xs={12} md={8}>
185
- <Collapse in={isEnabled}>
186
- <Box sx={{ display: 'flex', gap: 2, flexWrap: 'wrap' }}>
187
- {AVAILABLE_CURRENCIES.map((currency) => {
188
- const config = CURRENCY_CONFIG[currency];
189
- const currentPrice = addonPrices[currency] ?? entry.prices?.[currency] ?? 0;
190
-
191
- return (
192
- <Controller
193
- key={currency}
194
- name={`addon_prices.${addonId}.${currency}`}
195
- control={control}
196
- defaultValue={currentPrice}
197
- render={({ field }) => (
198
- <TextField
199
- {...field}
200
- label={`Price (${currency})`}
201
- type="text"
202
- size="small"
203
- disabled={isReadOnly}
204
- sx={{ width: 150 }}
205
- value={formatPrice(field.value ?? 0, currency)}
206
- onChange={(e) => handlePriceChange(currency, e.target.value)}
207
- helperText={config.name}
208
- slotProps={{
209
- input: {
210
- startAdornment: (
211
- <InputAdornment position="start">
212
- {config.symbol}
213
- </InputAdornment>
214
- ),
215
- }
216
- }}
217
- />
218
- )}
219
- />
220
- );
221
- })}
222
- </Box>
223
- {plan?.flow_addon_items?.[addonId] && (
224
- <Typography
225
- variant="caption"
226
- sx={{
227
- color: "text.secondary",
228
- mt: 1,
229
- display: 'block'
230
- }}>
231
- Flow Item ID: {plan.flow_addon_items[addonId]}
232
- </Typography>
233
- )}
234
- </Collapse>
235
- </Grid>
236
- </Grid>
237
- </Paper>
238
- );
239
- };
240
-
241
- const PlanAddonsSettingsEdit: React.FC<IDashAutoAdminCustomFieldComponent> = ({ method, attribute }) => {
242
- const plan: SubscriptionPlan = useRecordContext();
243
- const formContext = useFormContext();
244
- const { setValue, watch } = formContext;
245
-
246
- // Watch for changes in addons to ensure it remains an object
247
- const currentAddons = watch('addons');
248
- const currentAddonPrices = watch('addon_prices');
249
-
250
- useEffect(() => {
251
- // Fix: Ensure addons is always an object, not an array
252
- if (Array.isArray(currentAddons)) {
253
- console.warn('PlanAddonsSettings: Detected addons as array, converting to object');
254
- setValue('addons', { ...currentAddons });
255
- }
256
- }, [currentAddons, setValue]);
257
-
258
- useEffect(() => {
259
- // Fix: Ensure addon_prices is always an object, not an array
260
- if (Array.isArray(currentAddonPrices)) {
261
- console.warn('PlanAddonsSettings: Detected addon_prices as array, converting to object');
262
- setValue('addon_prices', {});
263
- } else if (!currentAddonPrices && plan?.addon_prices && !Array.isArray(plan.addon_prices)) {
264
- // Initialize addon_prices from plan if not set
265
- setValue('addon_prices', plan.addon_prices);
266
- } else if (!currentAddonPrices || (typeof currentAddonPrices === 'object' && Object.keys(currentAddonPrices).length === 0)) {
267
- // Initialize as empty object if not set
268
- setValue('addon_prices', {});
269
- }
270
- }, [currentAddonPrices, plan, setValue]);
271
-
272
- useWatch({
273
- control: formContext.control
274
- });
275
-
276
- const { addonFormats: formatsData, loading } = useSubscriptionPlanFormats();
277
-
278
- if (loading) return <Loading />;
279
-
280
- const formats = (formatsData?.formats as AddonFormat[]) || [];
281
- const visibleFormats = formats.filter((entry) => entry.visible !== false);
282
-
283
- // Group addons by tab
284
- const groupedByTab = visibleFormats.reduce((acc, entry) => {
285
- const tab = entry.tab || 'General';
286
- if (!acc[tab]) acc[tab] = [];
287
- acc[tab].push(entry);
288
- return acc;
289
- }, {} as Record<string, AddonFormat[]>);
290
-
291
- return (
292
- <Box sx={{ p: 2 }}>
293
- <Typography variant="h6" gutterBottom>
294
- Plan Add-ons Configuration
295
- </Typography>
296
- <Typography
297
- variant="body2"
298
- sx={{
299
- color: "text.secondary",
300
- mb: 3
301
- }}>
302
- Enable add-ons and set prices per currency. Prices are in the smallest currency unit (e.g., cents for USD, pesos for CLP).
303
- </Typography>
304
-
305
- {Object.entries(groupedByTab).map(([tabName, entries]) => (
306
- <Box key={tabName} sx={{ mb: 4 }}>
307
- <Typography
308
- variant="subtitle1"
309
- sx={{
310
- fontWeight: "bold",
311
- mb: 2
312
- }}>
313
- {tabName}
314
- </Typography>
315
- <Divider sx={{ mb: 2 }} />
316
- {entries.map((entry) => {
317
- const addonId = entry.attribute
318
- ? entry.attribute.replace('addons.', '')
319
- : entry.id;
320
- return (
321
- <AddonRow
322
- key={addonId}
323
- addonId={addonId}
324
- entry={entry}
325
- plan={plan}
326
- mode="edit"
327
- />
328
- );
329
- })}
330
- </Box>
331
- ))}
332
- </Box>
333
- );
334
- };
335
-
336
- const PlanAddonsSettingsCreate: React.FC<IDashAutoAdminCustomFieldComponent> = ({ method, attribute }) => {
337
- const formContext = useFormContext();
338
- const { setValue, watch } = formContext;
339
-
340
- // Watch for changes in addons to ensure it remains an object
341
- const currentAddons = watch('addons');
342
-
343
- useEffect(() => {
344
- // Fix: Ensure addons is always an object, not an array
345
- if (Array.isArray(currentAddons)) {
346
- console.warn('PlanAddonsSettings: Detected addons as array, converting to object');
347
- setValue('addons', { ...currentAddons });
348
- }
349
- }, [currentAddons, setValue]);
350
-
351
- // Initialize addon_prices structure for create mode
352
- useEffect(() => {
353
- const addonPrices = watch('addon_prices');
354
- // Fix: Ensure addon_prices is always an object, not an array
355
- if (Array.isArray(addonPrices)) {
356
- console.warn('PlanAddonsSettings: Detected addon_prices as array, converting to object');
357
- setValue('addon_prices', {});
358
- } else if (!addonPrices) {
359
- setValue('addon_prices', {});
360
- }
361
- }, [setValue, watch]);
362
-
363
- useWatch({
364
- control: formContext.control
365
- });
366
-
367
- const { addonFormats: formatsData, loading } = useSubscriptionPlanFormats();
368
-
369
- if (loading) return <Loading />;
370
-
371
- const formats = (formatsData?.formats as AddonFormat[]) || [];
372
- const visibleFormats = formats.filter((entry) => entry.visible !== false);
373
-
374
- // Group addons by tab
375
- const groupedByTab = visibleFormats.reduce((acc, entry) => {
376
- const tab = entry.tab || 'General';
377
- if (!acc[tab]) acc[tab] = [];
378
- acc[tab].push(entry);
379
- return acc;
380
- }, {} as Record<string, AddonFormat[]>);
381
-
382
- return (
383
- <Box sx={{ p: 2 }}>
384
- <Typography variant="h6" gutterBottom>
385
- Plan Add-ons Configuration
386
- </Typography>
387
- <Typography
388
- variant="body2"
389
- sx={{
390
- color: "text.secondary",
391
- mb: 3
392
- }}>
393
- Enable add-ons and set prices per currency. Prices are in the smallest currency unit.
394
- </Typography>
395
-
396
- {Object.entries(groupedByTab).map(([tabName, entries]) => (
397
- <Box key={tabName} sx={{ mb: 4 }}>
398
- <Typography
399
- variant="subtitle1"
400
- sx={{
401
- fontWeight: "bold",
402
- mb: 2
403
- }}>
404
- {tabName}
405
- </Typography>
406
- <Divider sx={{ mb: 2 }} />
407
- {entries.map((entry) => {
408
- const addonId = entry.attribute
409
- ? entry.attribute.replace('addons.', '')
410
- : entry.id;
411
- return (
412
- <AddonRow
413
- key={addonId}
414
- addonId={addonId}
415
- entry={entry}
416
- mode="create"
417
- />
418
- );
419
- })}
420
- </Box>
421
- ))}
422
- </Box>
423
- );
424
- };
425
-
426
- const PlanAddonsSettingsView: React.FC<IDashAutoAdminCustomFieldComponent> = ({ method, attribute }) => {
427
- const plan: SubscriptionPlan = useRecordContext();
428
-
429
- const { addonFormats: formatsData, loading } = useSubscriptionPlanFormats();
430
-
431
- const formatPrice = (price: number, currency: string): string => {
432
- return priceFormatter(price, currency);
433
- };
434
-
435
- if (loading) return <Loading />;
436
-
437
- const formats = (formatsData?.formats as AddonFormat[]) || [];
438
- const visibleFormats = formats.filter((entry) => entry.visible !== false);
439
-
440
- // Group addons by tab
441
- const groupedByTab = visibleFormats.reduce((acc, entry) => {
442
- const tab = entry.tab || 'General';
443
- if (!acc[tab]) acc[tab] = [];
444
- acc[tab].push(entry);
445
- return acc;
446
- }, {} as Record<string, AddonFormat[]>);
447
-
448
- return (
449
- <Box sx={{ p: 2 }}>
450
- <Typography variant="h6" gutterBottom>
451
- Plan Add-ons
452
- </Typography>
453
-
454
- {Object.entries(groupedByTab).map(([tabName, entries]) => (
455
- <Box key={tabName} sx={{ mb: 3 }}>
456
- <Typography
457
- variant="subtitle1"
458
- sx={{
459
- fontWeight: "bold",
460
- mb: 2
461
- }}>
462
- {tabName}
463
- </Typography>
464
- <Divider sx={{ mb: 2 }} />
465
-
466
- {entries.map((entry) => {
467
- const addonId = entry.attribute
468
- ? entry.attribute.replace('addons.', '')
469
- : entry.id;
470
- const isEnabled = plan?.addons?.[addonId] ?? false;
471
- const addonPrices = plan?.addon_prices?.[addonId] ?? {};
472
- const flowItemId = plan?.flow_addon_items?.[addonId];
473
-
474
- return (
475
- <Paper
476
- key={addonId}
477
- elevation={0}
478
- sx={{
479
- p: 2,
480
- mb: 1,
481
- backgroundColor: isEnabled ? 'action.selected' : 'background.default',
482
- borderLeft: isEnabled ? '4px solid #4caf50' : '4px solid #e0e0e0',
483
- }}
484
- >
485
- <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
486
- <Box>
487
- <Typography variant="subtitle2">
488
- {entry.icon && <span style={{ marginRight: 8 }}>{entry.icon}</span>}
489
- {entry.label}
490
- </Typography>
491
- <Chip
492
- label={isEnabled ? 'Enabled' : 'Disabled'}
493
- size="small"
494
- color={isEnabled ? 'success' : 'default'}
495
- sx={{ mt: 0.5 }}
496
- />
497
- </Box>
498
-
499
- {isEnabled && (
500
- <Box sx={{ textAlign: 'right' }}>
501
- {AVAILABLE_CURRENCIES.map((currency) => {
502
- const price = addonPrices[currency] ?? 0;
503
- return (
504
- <Typography key={currency} variant="body2">
505
- {currency}: {formatPrice(price, currency)}
506
- </Typography>
507
- );
508
- })}
509
- {flowItemId && (
510
- <Typography variant="caption" sx={{
511
- color: "text.secondary"
512
- }}>
513
- Flow ID: {flowItemId}
514
- </Typography>
515
- )}
516
- </Box>
517
- )}
518
- </Box>
519
- </Paper>
520
- );
521
- })}
522
- </Box>
523
- ))}
524
- </Box>
525
- );
526
- };
527
-
528
- /**
529
- * Main PlanAddonsSettings component
530
- * Renders the appropriate sub-component based on the form mode (edit, view, create)
531
- */
532
- const PlanAddonsSettings: React.FC<IDashAutoAdminCustomFieldComponent> = ({
533
- method,
534
- attribute,
535
- resourceConfig
536
- }) => {
537
- switch (method) {
538
- case "edit":
539
- return <PlanAddonsSettingsEdit
540
- attribute={attribute}
541
- method={method}
542
- resourceConfig={resourceConfig}
543
- />;
544
- case "view":
545
- return <PlanAddonsSettingsView
546
- attribute={attribute}
547
- method={method}
548
- resourceConfig={resourceConfig}
549
- />;
550
- case "create":
551
- return <PlanAddonsSettingsCreate
552
- attribute={attribute}
553
- method={method}
554
- resourceConfig={resourceConfig}
555
- />;
556
- case "list":
557
- return null;
558
- default:
559
- return null;
560
- }
561
- };
562
-
563
- export default PlanAddonsSettings;