realtimex-crm 0.1.2

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 (468) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +104 -0
  3. package/dist/assets/DealList-DqDrFeDV.js +59 -0
  4. package/dist/assets/DealList-DqDrFeDV.js.map +1 -0
  5. package/dist/assets/index-BiQoGq1P.css +1 -0
  6. package/dist/assets/index-CDIy4x-0.js +152 -0
  7. package/dist/assets/index-CDIy4x-0.js.map +1 -0
  8. package/dist/auth-callback.html +140 -0
  9. package/dist/favicon.ico +0 -0
  10. package/dist/img/adding-users.png +0 -0
  11. package/dist/img/empty.svg +42 -0
  12. package/dist/index.html +1 -0
  13. package/dist/logo192.png +0 -0
  14. package/dist/logo512.png +0 -0
  15. package/dist/logos/0.png +0 -0
  16. package/dist/logos/1.png +0 -0
  17. package/dist/logos/10.png +0 -0
  18. package/dist/logos/11.png +0 -0
  19. package/dist/logos/12.png +0 -0
  20. package/dist/logos/13.png +0 -0
  21. package/dist/logos/14.png +0 -0
  22. package/dist/logos/15.png +0 -0
  23. package/dist/logos/16.png +0 -0
  24. package/dist/logos/17.png +0 -0
  25. package/dist/logos/18.png +0 -0
  26. package/dist/logos/19.png +0 -0
  27. package/dist/logos/2.png +0 -0
  28. package/dist/logos/20.png +0 -0
  29. package/dist/logos/21.png +0 -0
  30. package/dist/logos/22.png +0 -0
  31. package/dist/logos/23.png +0 -0
  32. package/dist/logos/24.png +0 -0
  33. package/dist/logos/25.png +0 -0
  34. package/dist/logos/26.png +0 -0
  35. package/dist/logos/27.png +0 -0
  36. package/dist/logos/28.png +0 -0
  37. package/dist/logos/29.png +0 -0
  38. package/dist/logos/3.png +0 -0
  39. package/dist/logos/30.png +0 -0
  40. package/dist/logos/31.png +0 -0
  41. package/dist/logos/32.png +0 -0
  42. package/dist/logos/33.png +0 -0
  43. package/dist/logos/34.png +0 -0
  44. package/dist/logos/35.png +0 -0
  45. package/dist/logos/36.png +0 -0
  46. package/dist/logos/37.png +0 -0
  47. package/dist/logos/38.png +0 -0
  48. package/dist/logos/39.png +0 -0
  49. package/dist/logos/4.png +0 -0
  50. package/dist/logos/40.png +0 -0
  51. package/dist/logos/41.png +0 -0
  52. package/dist/logos/42.png +0 -0
  53. package/dist/logos/43.png +0 -0
  54. package/dist/logos/44.png +0 -0
  55. package/dist/logos/45.png +0 -0
  56. package/dist/logos/46.png +0 -0
  57. package/dist/logos/47.png +0 -0
  58. package/dist/logos/48.png +0 -0
  59. package/dist/logos/49.png +0 -0
  60. package/dist/logos/5.png +0 -0
  61. package/dist/logos/50.png +0 -0
  62. package/dist/logos/51.png +0 -0
  63. package/dist/logos/52.png +0 -0
  64. package/dist/logos/53.png +0 -0
  65. package/dist/logos/54.png +0 -0
  66. package/dist/logos/55.png +0 -0
  67. package/dist/logos/6.png +0 -0
  68. package/dist/logos/7.png +0 -0
  69. package/dist/logos/8.png +0 -0
  70. package/dist/logos/9.png +0 -0
  71. package/dist/logos/Readme.md +1 -0
  72. package/dist/logos/logo_atomic_crm.svg +14 -0
  73. package/dist/logos/logo_atomic_crm_dark.svg +14 -0
  74. package/dist/logos/logo_atomic_crm_light.svg +14 -0
  75. package/dist/manifest.json +25 -0
  76. package/dist/robots.txt +3 -0
  77. package/dist/stats.html +4949 -0
  78. package/package.json +152 -0
  79. package/public/auth-callback.html +140 -0
  80. package/public/favicon.ico +0 -0
  81. package/public/img/adding-users.png +0 -0
  82. package/public/img/empty.svg +42 -0
  83. package/public/logo192.png +0 -0
  84. package/public/logo512.png +0 -0
  85. package/public/logos/0.png +0 -0
  86. package/public/logos/1.png +0 -0
  87. package/public/logos/10.png +0 -0
  88. package/public/logos/11.png +0 -0
  89. package/public/logos/12.png +0 -0
  90. package/public/logos/13.png +0 -0
  91. package/public/logos/14.png +0 -0
  92. package/public/logos/15.png +0 -0
  93. package/public/logos/16.png +0 -0
  94. package/public/logos/17.png +0 -0
  95. package/public/logos/18.png +0 -0
  96. package/public/logos/19.png +0 -0
  97. package/public/logos/2.png +0 -0
  98. package/public/logos/20.png +0 -0
  99. package/public/logos/21.png +0 -0
  100. package/public/logos/22.png +0 -0
  101. package/public/logos/23.png +0 -0
  102. package/public/logos/24.png +0 -0
  103. package/public/logos/25.png +0 -0
  104. package/public/logos/26.png +0 -0
  105. package/public/logos/27.png +0 -0
  106. package/public/logos/28.png +0 -0
  107. package/public/logos/29.png +0 -0
  108. package/public/logos/3.png +0 -0
  109. package/public/logos/30.png +0 -0
  110. package/public/logos/31.png +0 -0
  111. package/public/logos/32.png +0 -0
  112. package/public/logos/33.png +0 -0
  113. package/public/logos/34.png +0 -0
  114. package/public/logos/35.png +0 -0
  115. package/public/logos/36.png +0 -0
  116. package/public/logos/37.png +0 -0
  117. package/public/logos/38.png +0 -0
  118. package/public/logos/39.png +0 -0
  119. package/public/logos/4.png +0 -0
  120. package/public/logos/40.png +0 -0
  121. package/public/logos/41.png +0 -0
  122. package/public/logos/42.png +0 -0
  123. package/public/logos/43.png +0 -0
  124. package/public/logos/44.png +0 -0
  125. package/public/logos/45.png +0 -0
  126. package/public/logos/46.png +0 -0
  127. package/public/logos/47.png +0 -0
  128. package/public/logos/48.png +0 -0
  129. package/public/logos/49.png +0 -0
  130. package/public/logos/5.png +0 -0
  131. package/public/logos/50.png +0 -0
  132. package/public/logos/51.png +0 -0
  133. package/public/logos/52.png +0 -0
  134. package/public/logos/53.png +0 -0
  135. package/public/logos/54.png +0 -0
  136. package/public/logos/55.png +0 -0
  137. package/public/logos/6.png +0 -0
  138. package/public/logos/7.png +0 -0
  139. package/public/logos/8.png +0 -0
  140. package/public/logos/9.png +0 -0
  141. package/public/logos/Readme.md +1 -0
  142. package/public/logos/logo_atomic_crm.svg +14 -0
  143. package/public/logos/logo_atomic_crm_dark.svg +14 -0
  144. package/public/logos/logo_atomic_crm_light.svg +14 -0
  145. package/public/manifest.json +25 -0
  146. package/public/robots.txt +3 -0
  147. package/src/App.css +42 -0
  148. package/src/App.tsx +58 -0
  149. package/src/assets/react.svg +1 -0
  150. package/src/components/admin/Readme.md +40 -0
  151. package/src/components/admin/admin.tsx +132 -0
  152. package/src/components/admin/app-sidebar.tsx +166 -0
  153. package/src/components/admin/array-field.tsx +59 -0
  154. package/src/components/admin/array-input.tsx +201 -0
  155. package/src/components/admin/authentication.tsx +86 -0
  156. package/src/components/admin/autocomplete-array-input.tsx +254 -0
  157. package/src/components/admin/autocomplete-input.tsx +296 -0
  158. package/src/components/admin/badge-field.tsx +65 -0
  159. package/src/components/admin/boolean-input.tsx +116 -0
  160. package/src/components/admin/breadcrumb.tsx +135 -0
  161. package/src/components/admin/bulk-actions-toolbar.tsx +83 -0
  162. package/src/components/admin/bulk-delete-button.tsx +70 -0
  163. package/src/components/admin/bulk-export-button.tsx +76 -0
  164. package/src/components/admin/cancel-button.tsx +46 -0
  165. package/src/components/admin/columns-button.tsx +345 -0
  166. package/src/components/admin/confirm.tsx +166 -0
  167. package/src/components/admin/count.tsx +94 -0
  168. package/src/components/admin/create-button.tsx +58 -0
  169. package/src/components/admin/create.tsx +132 -0
  170. package/src/components/admin/data-table.tsx +520 -0
  171. package/src/components/admin/date-field.tsx +136 -0
  172. package/src/components/admin/date-input.tsx +317 -0
  173. package/src/components/admin/date-time-input.tsx +331 -0
  174. package/src/components/admin/delete-button.tsx +113 -0
  175. package/src/components/admin/edit-button.tsx +64 -0
  176. package/src/components/admin/edit-guesser.tsx +157 -0
  177. package/src/components/admin/edit.tsx +152 -0
  178. package/src/components/admin/email-field.tsx +74 -0
  179. package/src/components/admin/error.tsx +111 -0
  180. package/src/components/admin/export-button.tsx +126 -0
  181. package/src/components/admin/field-toggle.tsx +164 -0
  182. package/src/components/admin/file-field.tsx +123 -0
  183. package/src/components/admin/file-input.tsx +361 -0
  184. package/src/components/admin/filter-form.tsx +510 -0
  185. package/src/components/admin/form.tsx +312 -0
  186. package/src/components/admin/icon-button-with-tooltip.tsx +85 -0
  187. package/src/components/admin/index.ts +73 -0
  188. package/src/components/admin/input-helper-text.tsx +29 -0
  189. package/src/components/admin/layout.tsx +69 -0
  190. package/src/components/admin/list-guesser.tsx +239 -0
  191. package/src/components/admin/list-pagination.tsx +247 -0
  192. package/src/components/admin/list.tsx +178 -0
  193. package/src/components/admin/loading.tsx +40 -0
  194. package/src/components/admin/locales-menu-button.tsx +60 -0
  195. package/src/components/admin/login-page.tsx +104 -0
  196. package/src/components/admin/notification.tsx +114 -0
  197. package/src/components/admin/number-field.tsx +84 -0
  198. package/src/components/admin/number-input.tsx +124 -0
  199. package/src/components/admin/radio-button-group-input.tsx +184 -0
  200. package/src/components/admin/ready.tsx +55 -0
  201. package/src/components/admin/record-field.tsx +132 -0
  202. package/src/components/admin/reference-array-field.tsx +152 -0
  203. package/src/components/admin/reference-array-input.tsx +68 -0
  204. package/src/components/admin/reference-field.tsx +153 -0
  205. package/src/components/admin/reference-input.tsx +46 -0
  206. package/src/components/admin/reference-many-count.tsx +92 -0
  207. package/src/components/admin/reference-many-field.tsx +132 -0
  208. package/src/components/admin/refresh-button.tsx +31 -0
  209. package/src/components/admin/saved-queries.tsx +174 -0
  210. package/src/components/admin/search-input.tsx +57 -0
  211. package/src/components/admin/select-field.tsx +111 -0
  212. package/src/components/admin/select-input.tsx +323 -0
  213. package/src/components/admin/show-button.tsx +57 -0
  214. package/src/components/admin/show-guesser.tsx +215 -0
  215. package/src/components/admin/show.tsx +184 -0
  216. package/src/components/admin/simple-form-iterator.tsx +582 -0
  217. package/src/components/admin/simple-form.tsx +95 -0
  218. package/src/components/admin/simple-show-layout.tsx +8 -0
  219. package/src/components/admin/single-field-list.tsx +67 -0
  220. package/src/components/admin/sort-button.tsx +152 -0
  221. package/src/components/admin/spinner.tsx +46 -0
  222. package/src/components/admin/text-field.tsx +60 -0
  223. package/src/components/admin/text-input.tsx +77 -0
  224. package/src/components/admin/theme-mode-toggle.tsx +48 -0
  225. package/src/components/admin/theme-provider.tsx +74 -0
  226. package/src/components/admin/toggle-filter-button.tsx +77 -0
  227. package/src/components/admin/url-field.tsx +83 -0
  228. package/src/components/admin/user-menu.tsx +84 -0
  229. package/src/components/atomic-crm/activity/ActivityLog.tsx +54 -0
  230. package/src/components/atomic-crm/activity/ActivityLogCompanyCreated.tsx +50 -0
  231. package/src/components/atomic-crm/activity/ActivityLogContactCreated.tsx +42 -0
  232. package/src/components/atomic-crm/activity/ActivityLogContactNoteCreated.tsx +71 -0
  233. package/src/components/atomic-crm/activity/ActivityLogContext.tsx +11 -0
  234. package/src/components/atomic-crm/activity/ActivityLogDealCreated.tsx +41 -0
  235. package/src/components/atomic-crm/activity/ActivityLogDealNoteCreated.tsx +84 -0
  236. package/src/components/atomic-crm/activity/ActivityLogIterator.tsx +80 -0
  237. package/src/components/atomic-crm/activity/ActivityLogNote.tsx +36 -0
  238. package/src/components/atomic-crm/companies/AutocompleteCompanyInput.tsx +43 -0
  239. package/src/components/atomic-crm/companies/CompanyAside.tsx +207 -0
  240. package/src/components/atomic-crm/companies/CompanyAvatar.tsx +29 -0
  241. package/src/components/atomic-crm/companies/CompanyCard.tsx +88 -0
  242. package/src/components/atomic-crm/companies/CompanyCreate.tsx +41 -0
  243. package/src/components/atomic-crm/companies/CompanyEdit.tsx +33 -0
  244. package/src/components/atomic-crm/companies/CompanyEmpty.tsx +26 -0
  245. package/src/components/atomic-crm/companies/CompanyInputs.tsx +160 -0
  246. package/src/components/atomic-crm/companies/CompanyList.tsx +54 -0
  247. package/src/components/atomic-crm/companies/CompanyListFilter.tsx +55 -0
  248. package/src/components/atomic-crm/companies/CompanyShow.tsx +241 -0
  249. package/src/components/atomic-crm/companies/GridList.tsx +46 -0
  250. package/src/components/atomic-crm/companies/index.ts +11 -0
  251. package/src/components/atomic-crm/companies/sizes.ts +7 -0
  252. package/src/components/atomic-crm/consts.ts +5 -0
  253. package/src/components/atomic-crm/contacts/Avatar.tsx +40 -0
  254. package/src/components/atomic-crm/contacts/ContactAside.tsx +187 -0
  255. package/src/components/atomic-crm/contacts/ContactCreate.tsx +34 -0
  256. package/src/components/atomic-crm/contacts/ContactEdit.tsx +32 -0
  257. package/src/components/atomic-crm/contacts/ContactEmpty.tsx +28 -0
  258. package/src/components/atomic-crm/contacts/ContactImportButton.tsx +213 -0
  259. package/src/components/atomic-crm/contacts/ContactInputs.tsx +209 -0
  260. package/src/components/atomic-crm/contacts/ContactList.tsx +116 -0
  261. package/src/components/atomic-crm/contacts/ContactListContent.tsx +107 -0
  262. package/src/components/atomic-crm/contacts/ContactListFilter.tsx +126 -0
  263. package/src/components/atomic-crm/contacts/ContactMergeButton.tsx +263 -0
  264. package/src/components/atomic-crm/contacts/ContactShow.tsx +76 -0
  265. package/src/components/atomic-crm/contacts/ExportVCardButton.tsx +79 -0
  266. package/src/components/atomic-crm/contacts/TagsList.tsx +33 -0
  267. package/src/components/atomic-crm/contacts/TagsListEdit.tsx +155 -0
  268. package/src/components/atomic-crm/contacts/contacts_export.csv +3 -0
  269. package/src/components/atomic-crm/contacts/exportToVCard.ts +104 -0
  270. package/src/components/atomic-crm/contacts/index.tsx +14 -0
  271. package/src/components/atomic-crm/contacts/useContactImport.tsx +206 -0
  272. package/src/components/atomic-crm/dashboard/Dashboard.tsx +66 -0
  273. package/src/components/atomic-crm/dashboard/DashboardActivityLog.tsx +22 -0
  274. package/src/components/atomic-crm/dashboard/DashboardStepper.tsx +72 -0
  275. package/src/components/atomic-crm/dashboard/DealsChart.tsx +202 -0
  276. package/src/components/atomic-crm/dashboard/DealsPipeline.tsx +90 -0
  277. package/src/components/atomic-crm/dashboard/HotContacts.tsx +92 -0
  278. package/src/components/atomic-crm/dashboard/LatestNotes.tsx +116 -0
  279. package/src/components/atomic-crm/dashboard/TasksList.tsx +69 -0
  280. package/src/components/atomic-crm/dashboard/TasksListEmpty.tsx +22 -0
  281. package/src/components/atomic-crm/dashboard/TasksListFilter.tsx +72 -0
  282. package/src/components/atomic-crm/dashboard/Welcome.tsx +41 -0
  283. package/src/components/atomic-crm/deals/ContactList.tsx +31 -0
  284. package/src/components/atomic-crm/deals/DealArchivedList.tsx +105 -0
  285. package/src/components/atomic-crm/deals/DealCard.tsx +78 -0
  286. package/src/components/atomic-crm/deals/DealColumn.tsx +52 -0
  287. package/src/components/atomic-crm/deals/DealCreate.tsx +95 -0
  288. package/src/components/atomic-crm/deals/DealEdit.tsx +81 -0
  289. package/src/components/atomic-crm/deals/DealEmpty.tsx +63 -0
  290. package/src/components/atomic-crm/deals/DealInputs.tsx +103 -0
  291. package/src/components/atomic-crm/deals/DealList.tsx +95 -0
  292. package/src/components/atomic-crm/deals/DealListContent.tsx +245 -0
  293. package/src/components/atomic-crm/deals/DealShow.tsx +260 -0
  294. package/src/components/atomic-crm/deals/OnlyMineInput.tsx +30 -0
  295. package/src/components/atomic-crm/deals/deal.ts +5 -0
  296. package/src/components/atomic-crm/deals/dealUtils.ts +26 -0
  297. package/src/components/atomic-crm/deals/index.ts +6 -0
  298. package/src/components/atomic-crm/deals/stages.ts +28 -0
  299. package/src/components/atomic-crm/filters/FilterCategory.tsx +20 -0
  300. package/src/components/atomic-crm/layout/FormToolbar.tsx +12 -0
  301. package/src/components/atomic-crm/layout/Header.tsx +134 -0
  302. package/src/components/atomic-crm/layout/Layout.tsx +21 -0
  303. package/src/components/atomic-crm/layout/TopToolbar.tsx +24 -0
  304. package/src/components/atomic-crm/login/LoginSkeleton.tsx +18 -0
  305. package/src/components/atomic-crm/login/SignupPage.tsx +150 -0
  306. package/src/components/atomic-crm/login/StartPage.tsx +27 -0
  307. package/src/components/atomic-crm/misc/AsideSection.tsx +21 -0
  308. package/src/components/atomic-crm/misc/ContactOption.tsx +26 -0
  309. package/src/components/atomic-crm/misc/ImageEditorField.tsx +206 -0
  310. package/src/components/atomic-crm/misc/RelativeDate.tsx +5 -0
  311. package/src/components/atomic-crm/misc/Status.tsx +28 -0
  312. package/src/components/atomic-crm/misc/fetchWithTimeout.ts +19 -0
  313. package/src/components/atomic-crm/misc/isLinkedInUrl.ts +15 -0
  314. package/src/components/atomic-crm/misc/unsupportedDomains.const.ts +105 -0
  315. package/src/components/atomic-crm/misc/useAppBarHeight.ts +9 -0
  316. package/src/components/atomic-crm/misc/usePapaParse.tsx +144 -0
  317. package/src/components/atomic-crm/notes/Note.tsx +187 -0
  318. package/src/components/atomic-crm/notes/NoteAttachments.tsx +56 -0
  319. package/src/components/atomic-crm/notes/NoteCreate.tsx +112 -0
  320. package/src/components/atomic-crm/notes/NoteInputs.tsx +92 -0
  321. package/src/components/atomic-crm/notes/NotesIterator.tsx +37 -0
  322. package/src/components/atomic-crm/notes/StatusSelector.tsx +39 -0
  323. package/src/components/atomic-crm/notes/index.ts +3 -0
  324. package/src/components/atomic-crm/notes/utils.ts +13 -0
  325. package/src/components/atomic-crm/providers/commons/activity.ts +174 -0
  326. package/src/components/atomic-crm/providers/commons/canAccess.ts +26 -0
  327. package/src/components/atomic-crm/providers/commons/getCompanyAvatar.spec.ts +20 -0
  328. package/src/components/atomic-crm/providers/commons/getCompanyAvatar.ts +21 -0
  329. package/src/components/atomic-crm/providers/commons/getContactAvatar.spec.ts +80 -0
  330. package/src/components/atomic-crm/providers/commons/getContactAvatar.ts +70 -0
  331. package/src/components/atomic-crm/providers/commons/mergeContacts.ts +185 -0
  332. package/src/components/atomic-crm/providers/fakerest/authProvider.ts +74 -0
  333. package/src/components/atomic-crm/providers/fakerest/dataGenerator/companies.ts +53 -0
  334. package/src/components/atomic-crm/providers/fakerest/dataGenerator/contactNotes.ts +25 -0
  335. package/src/components/atomic-crm/providers/fakerest/dataGenerator/contacts.ts +103 -0
  336. package/src/components/atomic-crm/providers/fakerest/dataGenerator/dealNotes.ts +19 -0
  337. package/src/components/atomic-crm/providers/fakerest/dataGenerator/deals.ts +53 -0
  338. package/src/components/atomic-crm/providers/fakerest/dataGenerator/finalize.ts +10 -0
  339. package/src/components/atomic-crm/providers/fakerest/dataGenerator/index.ts +25 -0
  340. package/src/components/atomic-crm/providers/fakerest/dataGenerator/sales.ts +37 -0
  341. package/src/components/atomic-crm/providers/fakerest/dataGenerator/tags.ts +14 -0
  342. package/src/components/atomic-crm/providers/fakerest/dataGenerator/tasks.ts +55 -0
  343. package/src/components/atomic-crm/providers/fakerest/dataGenerator/types.ts +21 -0
  344. package/src/components/atomic-crm/providers/fakerest/dataGenerator/utils.ts +28 -0
  345. package/src/components/atomic-crm/providers/fakerest/dataProvider.ts +518 -0
  346. package/src/components/atomic-crm/providers/fakerest/index.ts +2 -0
  347. package/src/components/atomic-crm/providers/fakerest/internal/listParser.ts +48 -0
  348. package/src/components/atomic-crm/providers/fakerest/internal/supabaseAdapter.spec.ts +721 -0
  349. package/src/components/atomic-crm/providers/fakerest/internal/supabaseAdapter.ts +49 -0
  350. package/src/components/atomic-crm/providers/fakerest/internal/transformContainsFilter.spec.ts +35 -0
  351. package/src/components/atomic-crm/providers/fakerest/internal/transformContainsFilter.ts +17 -0
  352. package/src/components/atomic-crm/providers/fakerest/internal/transformFilter.ts +57 -0
  353. package/src/components/atomic-crm/providers/fakerest/internal/transformInFilter.spec.ts +32 -0
  354. package/src/components/atomic-crm/providers/fakerest/internal/transformInFilter.ts +17 -0
  355. package/src/components/atomic-crm/providers/fakerest/internal/transformOrFilter.spec.ts +23 -0
  356. package/src/components/atomic-crm/providers/fakerest/internal/transformOrFilter.ts +17 -0
  357. package/src/components/atomic-crm/providers/supabase/authProvider.ts +121 -0
  358. package/src/components/atomic-crm/providers/supabase/dataProvider.ts +407 -0
  359. package/src/components/atomic-crm/providers/supabase/index.ts +2 -0
  360. package/src/components/atomic-crm/providers/supabase/supabase.ts +34 -0
  361. package/src/components/atomic-crm/providers/types.ts +1 -0
  362. package/src/components/atomic-crm/root/CRM.tsx +167 -0
  363. package/src/components/atomic-crm/root/ConfigurationContext.tsx +80 -0
  364. package/src/components/atomic-crm/root/defaultConfiguration.ts +64 -0
  365. package/src/components/atomic-crm/root/i18nProvider.tsx +25 -0
  366. package/src/components/atomic-crm/sales/SaleName.tsx +13 -0
  367. package/src/components/atomic-crm/sales/SalesCreate.tsx +51 -0
  368. package/src/components/atomic-crm/sales/SalesEdit.tsx +82 -0
  369. package/src/components/atomic-crm/sales/SalesInputs.tsx +31 -0
  370. package/src/components/atomic-crm/sales/SalesList.tsx +62 -0
  371. package/src/components/atomic-crm/sales/index.ts +12 -0
  372. package/src/components/atomic-crm/settings/DatabaseSettings.tsx +169 -0
  373. package/src/components/atomic-crm/settings/SettingsPage.tsx +259 -0
  374. package/src/components/atomic-crm/setup/SupabaseSetupWizard.tsx +215 -0
  375. package/src/components/atomic-crm/simple-list/ListNoResults.tsx +53 -0
  376. package/src/components/atomic-crm/simple-list/ListPlaceholder.tsx +9 -0
  377. package/src/components/atomic-crm/simple-list/SimpleList.tsx +245 -0
  378. package/src/components/atomic-crm/simple-list/SimpleListItem.tsx +138 -0
  379. package/src/components/atomic-crm/simple-list/SimpleListLoading.tsx +60 -0
  380. package/src/components/atomic-crm/tags/RoundButton.tsx +10 -0
  381. package/src/components/atomic-crm/tags/TagChip.tsx +45 -0
  382. package/src/components/atomic-crm/tags/TagCreateModal.tsx +39 -0
  383. package/src/components/atomic-crm/tags/TagDialog.tsx +118 -0
  384. package/src/components/atomic-crm/tags/TagEditModal.tsx +42 -0
  385. package/src/components/atomic-crm/tags/colors.ts +12 -0
  386. package/src/components/atomic-crm/tasks/AddTask.tsx +191 -0
  387. package/src/components/atomic-crm/tasks/Task.tsx +184 -0
  388. package/src/components/atomic-crm/tasks/TaskEdit.tsx +96 -0
  389. package/src/components/atomic-crm/tasks/TasksIterator.tsx +30 -0
  390. package/src/components/atomic-crm/types.ts +226 -0
  391. package/src/components/supabase/forgot-password-page.tsx +86 -0
  392. package/src/components/supabase/layout.tsx +27 -0
  393. package/src/components/supabase/set-password-page.tsx +119 -0
  394. package/src/components/ui/README.md +34 -0
  395. package/src/components/ui/accordion.tsx +64 -0
  396. package/src/components/ui/alert.tsx +66 -0
  397. package/src/components/ui/avatar.tsx +99 -0
  398. package/src/components/ui/badge.tsx +46 -0
  399. package/src/components/ui/breadcrumb.tsx +109 -0
  400. package/src/components/ui/button.tsx +59 -0
  401. package/src/components/ui/card.tsx +92 -0
  402. package/src/components/ui/checkbox.tsx +30 -0
  403. package/src/components/ui/command.tsx +175 -0
  404. package/src/components/ui/dialog.tsx +133 -0
  405. package/src/components/ui/drawer.tsx +133 -0
  406. package/src/components/ui/dropdown-menu.tsx +255 -0
  407. package/src/components/ui/input.tsx +21 -0
  408. package/src/components/ui/label.tsx +24 -0
  409. package/src/components/ui/navigation-menu.tsx +168 -0
  410. package/src/components/ui/pagination.tsx +127 -0
  411. package/src/components/ui/popover.tsx +46 -0
  412. package/src/components/ui/progress.tsx +29 -0
  413. package/src/components/ui/radio-group.tsx +43 -0
  414. package/src/components/ui/select.tsx +183 -0
  415. package/src/components/ui/separator.tsx +26 -0
  416. package/src/components/ui/sheet.tsx +137 -0
  417. package/src/components/ui/sidebar.tsx +724 -0
  418. package/src/components/ui/skeleton.tsx +13 -0
  419. package/src/components/ui/sonner.tsx +38 -0
  420. package/src/components/ui/spinner.tsx +51 -0
  421. package/src/components/ui/switch.tsx +29 -0
  422. package/src/components/ui/table.tsx +114 -0
  423. package/src/components/ui/tabs.tsx +64 -0
  424. package/src/components/ui/textarea.tsx +18 -0
  425. package/src/components/ui/tooltip.tsx +61 -0
  426. package/src/hooks/saved-queries.tsx +67 -0
  427. package/src/hooks/simple-form-iterator-context.tsx +70 -0
  428. package/src/hooks/use-mobile.ts +21 -0
  429. package/src/hooks/useBulkExport.tsx +61 -0
  430. package/src/hooks/useSupportCreateSuggestion.tsx +188 -0
  431. package/src/hooks/user-menu-context.tsx +24 -0
  432. package/src/index.css +170 -0
  433. package/src/lib/field.type.ts +22 -0
  434. package/src/lib/genericMemo.ts +18 -0
  435. package/src/lib/i18nProvider.ts +9 -0
  436. package/src/lib/sanitizeInputRestProps.ts +46 -0
  437. package/src/lib/supabase-config.ts +123 -0
  438. package/src/lib/utils.ts +6 -0
  439. package/src/main.tsx +10 -0
  440. package/src/setupTests.js +5 -0
  441. package/src/vite-env.d.ts +1 -0
  442. package/supabase/config.toml +157 -0
  443. package/supabase/functions/.env.development +7 -0
  444. package/supabase/functions/_shared/db.ts +187 -0
  445. package/supabase/functions/_shared/supabaseAdmin.ts +13 -0
  446. package/supabase/functions/_shared/utils.ts +13 -0
  447. package/supabase/functions/mergeContacts/index.ts +215 -0
  448. package/supabase/functions/postmark/addNoteToContact.ts +129 -0
  449. package/supabase/functions/postmark/extractMailContactData.ts +41 -0
  450. package/supabase/functions/postmark/getExpectedAuthorization.ts +4 -0
  451. package/supabase/functions/postmark/getNoteContent.ts +6 -0
  452. package/supabase/functions/postmark/index.ts +210 -0
  453. package/supabase/functions/updatePassword/index.ts +50 -0
  454. package/supabase/functions/users/index.ts +206 -0
  455. package/supabase/migrations/20240730075029_init_db.sql +600 -0
  456. package/supabase/migrations/20240730075425_init_triggers.sql +57 -0
  457. package/supabase/migrations/20240806124555_task_sales_id.sql +1 -0
  458. package/supabase/migrations/20240807082449_remove-aquisition.sql +20 -0
  459. package/supabase/migrations/20240808141826_init_state_configure.sql +9 -0
  460. package/supabase/migrations/20240813084010_tags_policy.sql +18 -0
  461. package/supabase/migrations/20241104153231_sales_policies.sql +7 -0
  462. package/supabase/migrations/20250109152531_email_jsonb.sql +43 -0
  463. package/supabase/migrations/20250113132531_phone_jsonb.sql +67 -0
  464. package/supabase/migrations/20251204172855_merge_contacts_function.sql +153 -0
  465. package/supabase/migrations/20251204201317_drop_merge_contacts_function.sql +2 -0
  466. package/supabase/seed.sql +0 -0
  467. package/supabase/templates/invite.html +70 -0
  468. package/supabase/templates/recovery.html +75 -0
@@ -0,0 +1,188 @@
1
+ import * as React from "react";
2
+ import type { ChangeEvent, ReactElement } from "react";
3
+ import {
4
+ createContext,
5
+ isValidElement,
6
+ useContext,
7
+ useRef,
8
+ useState,
9
+ } from "react";
10
+ import type { Identifier, OptionText } from "ra-core";
11
+ import { useTranslate } from "ra-core";
12
+ import set from "lodash/set";
13
+
14
+ /**
15
+ * This hook provides support for suggestion creation in inputs which have choices.
16
+ *
17
+ * @deprecated Use `useSupportCreateSuggestion` from "ra-core" when available.
18
+ *
19
+ * @param options The hook option
20
+ * @param {ReactElement} options.create A react element which will be rendered when users choose to create a new choice. This component must call the `useCreateSuggestionContext` hook which provides `onCancel`, `onCreate` and `filter`. See the examples.
21
+ * @param {React.ReactNode|string} options.createLabel Optional. The label for the choice item allowing users to create a new choice. Can be a translation key. Defaults to `ra.action.create`.
22
+ * @param {React.ReactNode|string} options.createItemLabel Optional. The label for the choice item allowing users to create a new choice when they already entered a filter. Can be a translation key. The function and ttranslation will receive an `item` parameter. Providing this option will turn the create label when there is no filter to be a hint (i.e. a disabled item).
23
+ * @param {any} options.createValue Optional. The value for the choice item allowing users to create a new choice. Defaults to `@@ra-create`.
24
+ * @param {any} options.createHintValue Optional. The value for the (disabled) item hinting users on how to create a new choice. Defaults to `@@ra-create-hint`.
25
+ * @param {String} options.filter Optional. The filter users may have already entered. Useful for autocomplete inputs for example.
26
+ * @param {OnCreateHandler} options.onCreate Optional. A function which will be called when users choose to create a new choice, if the `create` option wasn't provided.
27
+ * @param {Function} options.handleChange A function to pass to the input. Receives the same parameter as the original event handler and an additional newItem parameter if a new item was create.
28
+ *
29
+ * @returns {UseSupportCreateValue} An object with the following properties:
30
+ * - getCreateItem: a function which will return the label of the choice for create a new choice.
31
+ * - handleChange: a function which should be called when the input value changes. It will call the `onCreate` function if the value is the createValue.
32
+ * - createElement: a React element to render after the input. It will be rendered when users choose to create a new choice. It renders null otherwise.
33
+ * - getOptionDisabled: a function which should be passed to the input to disable the create choice when the filter is empty (to make it a hint).
34
+ */
35
+ export const useSupportCreateSuggestion = <T = unknown,>(
36
+ options: SupportCreateSuggestionOptions<T>,
37
+ ): UseSupportCreateValue<T> => {
38
+ const {
39
+ create,
40
+ createLabel = "ra.action.create",
41
+ createItemLabel,
42
+ createValue = "@@ra-create",
43
+ createHintValue = "@@ra-create-hint",
44
+ optionText = "name",
45
+ filter,
46
+ handleChange,
47
+ onCreate,
48
+ } = options;
49
+
50
+ const translate = useTranslate();
51
+ const [renderOnCreate, setRenderOnCreate] = useState(false);
52
+ const filterRef = useRef(filter);
53
+
54
+ return {
55
+ createId: createValue,
56
+ createHintId: createHintValue,
57
+ getCreateItem: (filter?: string) => {
58
+ filterRef.current = filter;
59
+
60
+ return set(
61
+ {
62
+ id: createItemLabel && !filter ? createHintValue : createValue,
63
+ },
64
+ typeof optionText === "string" ? optionText : "name",
65
+ filter && createItemLabel
66
+ ? typeof createItemLabel === "string"
67
+ ? translate(createItemLabel, {
68
+ item: filter,
69
+ _: createItemLabel,
70
+ })
71
+ : createItemLabel(filter)
72
+ : typeof createLabel === "string"
73
+ ? translate(createLabel, { _: createLabel })
74
+ : createLabel,
75
+ );
76
+ },
77
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
78
+ handleChange: async (eventOrValue: MouseEvent | any) => {
79
+ const value = eventOrValue?.target?.value || eventOrValue;
80
+ const finalValue = Array.isArray(value) ? [...value].pop() : value;
81
+
82
+ if (finalValue?.id === createValue || finalValue === createValue) {
83
+ if (!isValidElement(create)) {
84
+ if (!onCreate) {
85
+ // this should never happen because the createValue is only added if a create function is provided
86
+ // @see AutocompleteInput:filterOptions
87
+ throw new Error(
88
+ "To create a new option, you must pass an onCreate function or a create element.",
89
+ );
90
+ }
91
+ const newSuggestion = await onCreate(filter);
92
+ if (newSuggestion) {
93
+ handleChange(newSuggestion);
94
+ return;
95
+ }
96
+ } else {
97
+ setRenderOnCreate(true);
98
+ return;
99
+ }
100
+ }
101
+ handleChange(eventOrValue);
102
+ },
103
+ createElement:
104
+ renderOnCreate && isValidElement(create) ? (
105
+ <CreateSuggestionContext.Provider
106
+ value={{
107
+ filter: filterRef.current,
108
+ onCancel: () => setRenderOnCreate(false),
109
+ onCreate: (item) => {
110
+ setRenderOnCreate(false);
111
+ handleChange(item as T);
112
+ },
113
+ }}
114
+ >
115
+ {create}
116
+ </CreateSuggestionContext.Provider>
117
+ ) : null,
118
+ getOptionDisabled: (option) =>
119
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
120
+ (option as any)?.id === createHintValue || option === createHintValue,
121
+ };
122
+ };
123
+
124
+ /**
125
+ * @deprecated Use `SupportCreateSuggestionOptions` from "ra-core" when available.
126
+ */
127
+ export interface SupportCreateSuggestionOptions<T = unknown> {
128
+ create?: ReactElement;
129
+ createValue?: string;
130
+ createHintValue?: string;
131
+ createLabel?: React.ReactNode;
132
+ createItemLabel?: string | ((filter: string) => React.ReactNode);
133
+ filter?: string;
134
+ handleChange: (value: T) => void;
135
+ onCreate?: OnCreateHandler;
136
+ optionText?: OptionText;
137
+ }
138
+
139
+ /**
140
+ * @deprecated Use `UseSupportCreateValue` from "ra-core" when available.
141
+ */
142
+ export interface UseSupportCreateValue<T = unknown> {
143
+ createId: string;
144
+ createHintId: string;
145
+ getCreateItem: (filterValue?: string) => {
146
+ id: Identifier;
147
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
148
+ [key: string]: any;
149
+ };
150
+ handleChange: (eventOrValue: ChangeEvent | T) => Promise<void>;
151
+ createElement: ReactElement | null;
152
+ getOptionDisabled: (option: T) => boolean;
153
+ }
154
+
155
+ /**
156
+ * @deprecated Use `CreateSuggestionContext` from "ra-core" when available.
157
+ */
158
+ const CreateSuggestionContext = createContext<
159
+ CreateSuggestionContextValue | undefined
160
+ >(undefined);
161
+
162
+ /**
163
+ * @deprecated Use `CreateSuggestionContextValue` from "ra-core" when available.
164
+ */
165
+ interface CreateSuggestionContextValue<T = unknown> {
166
+ filter?: string;
167
+ onCreate: (choice: T) => void;
168
+ onCancel: () => void;
169
+ }
170
+
171
+ /**
172
+ * @deprecated Use `useCreateSuggestionContext` from "ra-core" when available.
173
+ */
174
+ export const useCreateSuggestionContext = () => {
175
+ const context = useContext(CreateSuggestionContext);
176
+ if (!context) {
177
+ throw new Error(
178
+ "useCreateSuggestionContext must be used inside a CreateSuggestionContext.Provider",
179
+ );
180
+ }
181
+ return context;
182
+ };
183
+
184
+ /**
185
+ * @deprecated Use `OnCreateHandler` from "ra-core" when available.
186
+ */
187
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
188
+ export type OnCreateHandler = (filter?: string) => any | Promise<any>;
@@ -0,0 +1,24 @@
1
+ import { createContext, useContext } from "react";
2
+
3
+ /**
4
+ * @deprecated Use UserMenuContextValue from `ra-core` once available.
5
+ */
6
+ export type UserMenuContextValue = {
7
+ /**
8
+ * Closes the user menu
9
+ * @see UserMenu
10
+ */
11
+ onClose: () => void;
12
+ };
13
+
14
+ /**
15
+ * @deprecated Use UserMenuContext from `ra-core` once available.
16
+ */
17
+ export const UserMenuContext = createContext<UserMenuContextValue | undefined>(
18
+ undefined,
19
+ );
20
+
21
+ /**
22
+ * @deprecated Use useUserMenu from `ra-core` once available.
23
+ */
24
+ export const useUserMenu = () => useContext(UserMenuContext);
package/src/index.css ADDED
@@ -0,0 +1,170 @@
1
+ @import "tailwindcss";
2
+ @import "tw-animate-css";
3
+
4
+ @custom-variant dark (&:is(.dark *));
5
+
6
+ @theme inline {
7
+ --radius-sm: calc(var(--radius) - 4px);
8
+ --radius-md: calc(var(--radius) - 2px);
9
+ --radius-lg: var(--radius);
10
+ --radius-xl: calc(var(--radius) + 4px);
11
+ --color-background: var(--background);
12
+ --color-foreground: var(--foreground);
13
+ --color-card: var(--card);
14
+ --color-card-foreground: var(--card-foreground);
15
+ --color-popover: var(--popover);
16
+ --color-popover-foreground: var(--popover-foreground);
17
+ --color-primary: var(--primary);
18
+ --color-primary-foreground: var(--primary-foreground);
19
+ --color-secondary: var(--secondary);
20
+ --color-secondary-foreground: var(--secondary-foreground);
21
+ --color-muted: var(--muted);
22
+ --color-muted-foreground: var(--muted-foreground);
23
+ --color-accent: var(--accent);
24
+ --color-accent-foreground: var(--accent-foreground);
25
+ --color-destructive: var(--destructive);
26
+ --color-border: var(--border);
27
+ --color-input: var(--input);
28
+ --color-ring: var(--ring);
29
+ --color-chart-1: var(--chart-1);
30
+ --color-chart-2: var(--chart-2);
31
+ --color-chart-3: var(--chart-3);
32
+ --color-chart-4: var(--chart-4);
33
+ --color-chart-5: var(--chart-5);
34
+ --color-sidebar: var(--sidebar);
35
+ --color-sidebar-foreground: var(--sidebar-foreground);
36
+ --color-sidebar-primary: var(--sidebar-primary);
37
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
38
+ --color-sidebar-accent: var(--sidebar-accent);
39
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
40
+ --color-sidebar-border: var(--sidebar-border);
41
+ --color-sidebar-ring: var(--sidebar-ring);
42
+ }
43
+
44
+ :root {
45
+ --radius: 0.625rem;
46
+ --background: oklch(1 0 0);
47
+ --foreground: oklch(0.145 0 0);
48
+ --card: oklch(1 0 0);
49
+ --card-foreground: oklch(0.145 0 0);
50
+ --popover: oklch(1 0 0);
51
+ --popover-foreground: oklch(0.145 0 0);
52
+ --primary: oklch(0.205 0 0);
53
+ --primary-foreground: oklch(0.985 0 0);
54
+ --secondary: oklch(0.97 0 0);
55
+ --secondary-foreground: oklch(0.205 0 0);
56
+ --muted: oklch(0.97 0 0);
57
+ --muted-foreground: oklch(0.556 0 0);
58
+ --accent: oklch(0.97 0 0);
59
+ --accent-foreground: oklch(0.205 0 0);
60
+ --destructive: oklch(0.577 0.245 27.325);
61
+ --border: oklch(0.922 0 0);
62
+ --input: oklch(0.922 0 0);
63
+ --ring: oklch(0.708 0 0);
64
+ --chart-1: oklch(0.646 0.222 41.116);
65
+ --chart-2: oklch(0.6 0.118 184.704);
66
+ --chart-3: oklch(0.398 0.07 227.392);
67
+ --chart-4: oklch(0.828 0.189 84.429);
68
+ --chart-5: oklch(0.769 0.188 70.08);
69
+ --sidebar: oklch(0.985 0 0);
70
+ --sidebar-foreground: oklch(0.145 0 0);
71
+ --sidebar-primary: oklch(0.205 0 0);
72
+ --sidebar-primary-foreground: oklch(0.985 0 0);
73
+ --sidebar-accent: oklch(0.97 0 0);
74
+ --sidebar-accent-foreground: oklch(0.205 0 0);
75
+ --sidebar-border: oklch(0.922 0 0);
76
+ --sidebar-ring: oklch(0.708 0 0);
77
+ --avatar-0: oklch(0.85 0.08 240);
78
+ --avatar-1: oklch(0.88 0.1 340);
79
+ --avatar-2: oklch(0.85 0.07 180);
80
+ --avatar-3: oklch(0.9 0.09 40);
81
+ --avatar-4: oklch(0.87 0.08 300);
82
+ --avatar-5: oklch(0.85 0.08 150);
83
+ --avatar-6: oklch(0.87 0.08 200);
84
+ --avatar-7: oklch(0.88 0.09 10);
85
+ --avatar-8: oklch(0.92 0.08 80);
86
+ --avatar-9: oklch(0.86 0.09 270);
87
+ }
88
+
89
+ .dark {
90
+ --background: oklch(0.145 0 0);
91
+ --foreground: oklch(0.985 0 0);
92
+ --card: oklch(0.205 0 0);
93
+ --card-foreground: oklch(0.985 0 0);
94
+ --popover: oklch(0.205 0 0);
95
+ --popover-foreground: oklch(0.985 0 0);
96
+ --primary: oklch(0.922 0 0);
97
+ --primary-foreground: oklch(0.205 0 0);
98
+ --secondary: oklch(0.269 0 0);
99
+ --secondary-foreground: oklch(0.985 0 0);
100
+ --muted: oklch(0.269 0 0);
101
+ --muted-foreground: oklch(0.708 0 0);
102
+ --accent: oklch(0.269 0 0);
103
+ --accent-foreground: oklch(0.985 0 0);
104
+ --destructive: oklch(0.704 0.191 22.216);
105
+ --border: oklch(1 0 0 / 15%);
106
+ --input: oklch(1 0 0 / 15%);
107
+ --ring: oklch(0.556 0 0);
108
+ --chart-1: oklch(0.488 0.243 264.376);
109
+ --chart-2: oklch(0.696 0.17 162.48);
110
+ --chart-3: oklch(0.769 0.188 70.08);
111
+ --chart-4: oklch(0.627 0.265 303.9);
112
+ --chart-5: oklch(0.645 0.246 16.439);
113
+ --sidebar: oklch(0.205 0 0);
114
+ --sidebar-foreground: oklch(0.985 0 0);
115
+ --sidebar-primary: oklch(0.488 0.243 264.376);
116
+ --sidebar-primary-foreground: oklch(0.985 0 0);
117
+ --sidebar-accent: oklch(0.269 0 0);
118
+ --sidebar-accent-foreground: oklch(0.985 0 0);
119
+ --sidebar-border: oklch(1 0 0 / 10%);
120
+ --sidebar-ring: oklch(0.556 0 0);
121
+ --avatar-0: oklch(0.35 0.12 240);
122
+ --avatar-1: oklch(0.38 0.14 340);
123
+ --avatar-2: oklch(0.35 0.11 180);
124
+ --avatar-3: oklch(0.38 0.13 40);
125
+ --avatar-4: oklch(0.36 0.12 300);
126
+ --avatar-5: oklch(0.35 0.11 150);
127
+ --avatar-6: oklch(0.37 0.12 200);
128
+ --avatar-7: oklch(0.38 0.14 10);
129
+ --avatar-8: oklch(0.4 0.11 80);
130
+ --avatar-9: oklch(0.36 0.13 270);
131
+ }
132
+
133
+ a,
134
+ button {
135
+ cursor: pointer;
136
+ }
137
+
138
+ input {
139
+ cursor: text;
140
+ }
141
+
142
+ a[aria-disabled="true"],
143
+ button[aria-disabled="true"],
144
+ button:disabled,
145
+ input[aria-disabled="true"],
146
+ input:disabled {
147
+ cursor: not-allowed;
148
+ }
149
+
150
+ input[type="date"],
151
+ input[type="datetime-local"],
152
+ input[type="month"],
153
+ input[type="time"] {
154
+ position: relative;
155
+ }
156
+
157
+ .dark ::-webkit-calendar-picker-indicator {
158
+ filter: invert(1);
159
+ position: absolute;
160
+ right: 0.75rem;
161
+ }
162
+
163
+ @layer base {
164
+ * {
165
+ @apply border-border outline-ring/50;
166
+ }
167
+ body {
168
+ @apply bg-background text-foreground;
169
+ }
170
+ }
@@ -0,0 +1,22 @@
1
+ import type { BaseFieldProps } from "ra-core";
2
+ import type { ReactNode } from "react";
3
+
4
+ export interface FieldProps<
5
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
+ RecordType extends Record<string, any> = Record<string, any>,
7
+ > extends Omit<BaseFieldProps<RecordType>, "resource"> {
8
+ /**
9
+ * The component to display when the field value is empty. Defaults to empty string.
10
+ *
11
+ * @example
12
+ * const PostList = () => (
13
+ * <List>
14
+ * <DataTable>
15
+ * <TextField source="title" />
16
+ * <TextField source="author" empty="missing data" />
17
+ * </DataTable>
18
+ * </List>
19
+ * );
20
+ */
21
+ empty?: ReactNode;
22
+ }
@@ -0,0 +1,18 @@
1
+ import type { FunctionComponent } from "react";
2
+ import { memo } from "react";
3
+
4
+ /**
5
+ * A version of React.memo that preserves the original component type allowing it to accept generics.
6
+ * See {@link https://stackoverflow.com/a/70890101}
7
+ * @deprecated Use genericMemo from "ra-core" when available.
8
+ */
9
+ export function genericMemo<T>(component: T): T {
10
+ const result = memo(component as FunctionComponent);
11
+
12
+ // We have to set the displayName on both the field implementation and the memoized version.
13
+ // On the implementation so that the memoized version can pick them up and users may reference the defaultProps in their components.
14
+ // On the memoized version so that components that inspect their children props may read them.
15
+ // @ts-expect-error: genericMemo does not have a displayName property
16
+ result.displayName = component.displayName?.replace("Impl", "");
17
+ return result as unknown as T;
18
+ }
@@ -0,0 +1,9 @@
1
+ import defaultMessages from "ra-language-english";
2
+ import polyglotI18nProvider from "ra-i18n-polyglot";
3
+
4
+ export const i18nProvider = polyglotI18nProvider(
5
+ () => defaultMessages,
6
+ "en",
7
+ [{ name: "en", value: "English" }],
8
+ { allowMissing: true },
9
+ );
@@ -0,0 +1,46 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ export const sanitizeInputRestProps = ({
3
+ afterSubmit,
4
+ allowNull,
5
+ alwaysOn,
6
+ beforeSubmit,
7
+ component,
8
+ data,
9
+ defaultValue,
10
+ error,
11
+ format,
12
+ formatOnBlur,
13
+ initializeForm,
14
+ input,
15
+ isEqual,
16
+ isRequired,
17
+ label,
18
+ limitChoicesToValue,
19
+ locale,
20
+ meta,
21
+ multiple,
22
+ name,
23
+ options,
24
+ optionText,
25
+ optionValue,
26
+ parse,
27
+ record,
28
+ ref,
29
+ refetch,
30
+ render,
31
+ resource,
32
+ setFilter,
33
+ setPagination,
34
+ setSort,
35
+ shouldUnregister,
36
+ source,
37
+ submitError,
38
+ subscription,
39
+ textAlign,
40
+ translate,
41
+ translateChoice,
42
+ validate,
43
+ validateFields,
44
+ value,
45
+ ...rest
46
+ }: any) => rest;
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Supabase Configuration Management
3
+ *
4
+ * Handles storing and retrieving Supabase connection details
5
+ * Priority: localStorage > environment variables
6
+ */
7
+
8
+ export interface SupabaseConfig {
9
+ url: string;
10
+ anonKey: string;
11
+ configuredAt?: string;
12
+ }
13
+
14
+ const STORAGE_KEY = 'realtimex_crm_supabase_config';
15
+
16
+ /**
17
+ * Get the current Supabase configuration
18
+ * Priority: localStorage override > environment variables
19
+ */
20
+ export function getSupabaseConfig(): SupabaseConfig | null {
21
+ // Try localStorage first (user-configured via UI)
22
+ const stored = localStorage.getItem(STORAGE_KEY);
23
+ if (stored) {
24
+ try {
25
+ return JSON.parse(stored);
26
+ } catch (e) {
27
+ console.error('Failed to parse stored Supabase config:', e);
28
+ localStorage.removeItem(STORAGE_KEY);
29
+ }
30
+ }
31
+
32
+ // Fallback to environment variables
33
+ const url = import.meta.env.VITE_SUPABASE_URL;
34
+ const anonKey = import.meta.env.VITE_SUPABASE_ANON_KEY;
35
+
36
+ if (url && anonKey) {
37
+ return { url, anonKey };
38
+ }
39
+
40
+ return null;
41
+ }
42
+
43
+ /**
44
+ * Save Supabase configuration to localStorage
45
+ */
46
+ export function saveSupabaseConfig(config: Omit<SupabaseConfig, 'configuredAt'>): void {
47
+ const configWithTimestamp: SupabaseConfig = {
48
+ ...config,
49
+ configuredAt: new Date().toISOString(),
50
+ };
51
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(configWithTimestamp));
52
+ }
53
+
54
+ /**
55
+ * Clear stored Supabase configuration
56
+ */
57
+ export function clearSupabaseConfig(): void {
58
+ localStorage.removeItem(STORAGE_KEY);
59
+ }
60
+
61
+ /**
62
+ * Check if Supabase is configured
63
+ */
64
+ export function isSupabaseConfigured(): boolean {
65
+ return getSupabaseConfig() !== null;
66
+ }
67
+
68
+ /**
69
+ * Validate Supabase connection
70
+ */
71
+ export async function validateSupabaseConnection(
72
+ url: string,
73
+ anonKey: string
74
+ ): Promise<{ valid: boolean; error?: string }> {
75
+ try {
76
+ // Basic URL validation
77
+ if (!url.startsWith('http://') && !url.startsWith('https://')) {
78
+ return { valid: false, error: 'Invalid URL format' };
79
+ }
80
+
81
+ // Basic anon key validation (JWT format)
82
+ if (!anonKey.startsWith('eyJ')) {
83
+ return { valid: false, error: 'Invalid anon key format' };
84
+ }
85
+
86
+ // Test connection by making a simple request
87
+ const response = await fetch(`${url}/rest/v1/`, {
88
+ method: 'GET',
89
+ headers: {
90
+ apikey: anonKey,
91
+ Authorization: `Bearer ${anonKey}`,
92
+ },
93
+ });
94
+
95
+ if (!response.ok) {
96
+ if (response.status === 401 || response.status === 403) {
97
+ return { valid: false, error: 'Invalid API key' };
98
+ }
99
+ return { valid: false, error: `Connection failed: ${response.statusText}` };
100
+ }
101
+
102
+ return { valid: true };
103
+ } catch (error) {
104
+ return {
105
+ valid: false,
106
+ error: error instanceof Error ? error.message : 'Connection failed',
107
+ };
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Get Supabase config source (for display purposes)
113
+ */
114
+ export function getConfigSource(): 'ui' | 'env' | 'none' {
115
+ const stored = localStorage.getItem(STORAGE_KEY);
116
+ if (stored) return 'ui';
117
+
118
+ const url = import.meta.env.VITE_SUPABASE_URL;
119
+ const anonKey = import.meta.env.VITE_SUPABASE_ANON_KEY;
120
+ if (url && anonKey) return 'env';
121
+
122
+ return 'none';
123
+ }
@@ -0,0 +1,6 @@
1
+ import { clsx, type ClassValue } from "clsx"
2
+ import { twMerge } from "tailwind-merge"
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs))
6
+ }
package/src/main.tsx ADDED
@@ -0,0 +1,10 @@
1
+ import { StrictMode } from "react";
2
+ import { createRoot } from "react-dom/client";
3
+ import "./index.css";
4
+ import App from "./App.tsx";
5
+
6
+ createRoot(document.getElementById("root")!).render(
7
+ <StrictMode>
8
+ <App />
9
+ </StrictMode>,
10
+ );
@@ -0,0 +1,5 @@
1
+ // jest-dom adds custom jest matchers for asserting on DOM nodes.
2
+ // allows you to do things like:
3
+ // expect(element).toHaveTextContent(/react/i)
4
+ // learn more: https://github.com/testing-library/jest-dom
5
+ import "@testing-library/jest-dom";
@@ -0,0 +1 @@
1
+ /// <reference types="vite/client" />