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,55 @@
1
+ import {
2
+ ScanFace,
3
+ BookOpenText,
4
+ ChevronsLeftRight,
5
+ Github,
6
+ } from "lucide-react";
7
+
8
+ /**
9
+ * Splash screen displayed when no resources are configured yet.
10
+ *
11
+ * Provides helpful links to documentation, demo, and GitHub repository.
12
+ * Automatically shown when the admin app has no Resource children defined.
13
+ *
14
+ * @see {@link https://marmelab.com/shadcn-admin-kit/docs/ready/ Ready documentation}
15
+ */
16
+ export const Ready = () => (
17
+ <div className="flex flex-col h-screen">
18
+ <div
19
+ className="flex-1 flex flex-col text-white text-center justify-center items-center"
20
+ style={{
21
+ background:
22
+ "linear-gradient(135deg, #00023b 0%, #00023b 50%, #313264 100%)",
23
+ }}
24
+ >
25
+ <ScanFace className="w-32 h-32 mb-4" />
26
+ <h1 className="text-3xl mb-4">Welcome to shadcn-admin-kit</h1>
27
+ <div className="text-lg opacity-75">
28
+ Your application is properly configured.
29
+ <br />
30
+ Now you can add a &lt;Resource&gt; as child of
31
+ &lt;Admin&gt;&lt;/Admin&gt;
32
+ </div>
33
+ </div>
34
+ <div className="flex h-[20vh] bg-zinc-100 text-black items-center justify-evenly">
35
+ <div className="text-xl">
36
+ <a href="https://marmelab.com/shadcn-admin-kit/docs">
37
+ <BookOpenText className="inline mr-4 w-10 h-10" />
38
+ Documentation
39
+ </a>
40
+ </div>
41
+ <div className="text-xl">
42
+ <a href="http://marmelab.com/shadcn-admin-kit/demo">
43
+ <ChevronsLeftRight className="inline mr-4 w-10 h-10" />
44
+ Demo
45
+ </a>
46
+ </div>
47
+ <div className="text-xl">
48
+ <a href="https://github.com/marmelab/shadcn-admin-kit">
49
+ <Github className="inline mr-4 w-10 h-10" />
50
+ GitHub
51
+ </a>
52
+ </div>
53
+ </div>
54
+ </div>
55
+ );
@@ -0,0 +1,132 @@
1
+ import type { ReactNode, ElementType, HTMLAttributes } from "react";
2
+ import { createElement } from "react";
3
+ import type { ExtractRecordPaths, HintedString } from "ra-core";
4
+ import {
5
+ FieldTitle,
6
+ useRecordContext,
7
+ useResourceContext,
8
+ useTranslate,
9
+ } from "ra-core";
10
+ import { cn } from "@/lib/utils";
11
+
12
+ import { TextField } from "@/components/admin/text-field";
13
+
14
+ /**
15
+ * Displays a labeled field-value pair with flexible rendering options.
16
+ *
17
+ * Supports either vertical or inline layout.
18
+ * It can render children, use a custom field component, or display a TextField by default.
19
+ * To be used with RecordContext, e.g. inside Show, or inside ArrayField to display array items.
20
+ *
21
+ * @see {@link https://marmelab.com/shadcn-admin-kit/docs/recordfield/ RecordField documentation}
22
+ *
23
+ * @example
24
+ * import { NumberField, RecordField, Show } from '@/components/admin';
25
+ *
26
+ * const PostShow = () => (
27
+ * <Show>
28
+ * <div className="flex flex-col gap-4">
29
+ * <RecordField source="reference" label="Ref." />
30
+ * <RecordField
31
+ * label="dimensions"
32
+ * render={record => `${record.width}x${record.height}`}
33
+ * />
34
+ * <RecordField source="price">
35
+ * <NumberField source="price" options={
36
+ * style: 'currency',
37
+ * currency: 'USD',
38
+ * }/>
39
+ * <RecordField source="status" variant="inline" />
40
+ * </div>
41
+ * </Show>
42
+ * );
43
+ */
44
+ export const RecordField = <
45
+ RecordType extends Record<string, any> = Record<string, any>,
46
+ >(
47
+ props: RecordFieldProps<RecordType>,
48
+ ) => {
49
+ const {
50
+ children,
51
+ className,
52
+ empty,
53
+ field,
54
+ label,
55
+ render,
56
+ resource: _,
57
+ source,
58
+ record: recordProp,
59
+ variant,
60
+ ...rest
61
+ } = props;
62
+ const resource = useResourceContext(props);
63
+ const record = useRecordContext<RecordType>({ recordProp });
64
+ const translate = useTranslate();
65
+
66
+ if (!source && !label && !render) return null;
67
+
68
+ return (
69
+ <div
70
+ className={cn(
71
+ className,
72
+ "flex",
73
+ variant === "inline" ? "flex-row" : "flex-col",
74
+ )}
75
+ {...rest}
76
+ >
77
+ {label !== "" && label !== false ? (
78
+ <div
79
+ className={cn(
80
+ variant === "inline" ? "block min-w-50" : "text-xs",
81
+ "text-muted-foreground",
82
+ )}
83
+ >
84
+ <FieldTitle
85
+ label={label}
86
+ source={source}
87
+ resource={resource}
88
+ isRequired={false}
89
+ />
90
+ </div>
91
+ ) : null}
92
+ {children ? (
93
+ <span className="flex-1">{children}</span>
94
+ ) : render ? (
95
+ record && (
96
+ <span className="flex-1">
97
+ {render(record) ||
98
+ (typeof empty === "string"
99
+ ? translate(empty, { _: empty })
100
+ : empty)}
101
+ </span>
102
+ )
103
+ ) : field ? (
104
+ createElement(field, {
105
+ source,
106
+ empty,
107
+ className: "flex-1",
108
+ })
109
+ ) : source ? (
110
+ <TextField source={source} empty={empty} className="flex-1" />
111
+ ) : null}
112
+ </div>
113
+ );
114
+ };
115
+
116
+ // FIXME remove custom type when using TypeScript >= 5.4 as it is now native
117
+ type NoInfer<T> = T extends infer U ? U : never;
118
+
119
+ export interface RecordFieldProps<
120
+ RecordType extends Record<string, any> = Record<string, any>,
121
+ > extends HTMLAttributes<HTMLDivElement> {
122
+ children?: ReactNode;
123
+ className?: string;
124
+ empty?: ReactNode;
125
+ field?: ElementType;
126
+ label?: ReactNode;
127
+ render?: (record: RecordType) => React.ReactNode;
128
+ resource?: string;
129
+ source?: NoInfer<HintedString<ExtractRecordPaths<RecordType>>>;
130
+ record?: RecordType;
131
+ variant?: "default" | "inline";
132
+ }
@@ -0,0 +1,152 @@
1
+ import type { ReactElement, ReactNode } from "react";
2
+ import { memo } from "react";
3
+ import type {
4
+ FilterPayload,
5
+ ListControllerResult,
6
+ RaRecord,
7
+ SortPayload,
8
+ ExtractRecordPaths,
9
+ HintedString,
10
+ } from "ra-core";
11
+ import { ReferenceArrayFieldBase, useListContext } from "ra-core";
12
+ import type { UseQueryOptions } from "@tanstack/react-query";
13
+ import { SingleFieldList } from "@/components/admin/single-field-list";
14
+
15
+ /**
16
+ * Displays multiple related records by following an array of foreign keys.
17
+ *
18
+ * This field fetches related records using an array of IDs and renders them using a child component (SingleFieldList by default).
19
+ * It supports custom sorting, filtering, and rendering with DataTable or other list components.
20
+ * To be used with RecordField or DataTable.Col components, or anywhere a RecordContext is available.
21
+ *
22
+ * @see {@link https://marmelab.com/shadcn-admin-kit/docs/referencearrayfield/ ReferenceArrayField documentation}
23
+ *
24
+ * @example
25
+ * import { List, DataTable, ReferenceArrayField } from '@/components/admin';
26
+ *
27
+ * export const PostList = () => (
28
+ * <List>
29
+ * <DataTable>
30
+ * <DataTable.Col source="id" />
31
+ * <DataTable.Col source="title" />
32
+ * <DataTable.Col source="tag_ids" label="Tags">
33
+ * <ReferenceArrayField reference="tags" source="tag_ids" />
34
+ * </DataTable.Col>
35
+ * <DataTable.Col>
36
+ * <EditButton />
37
+ * </DataTable.Col>
38
+ * </DataTable>
39
+ * </List>
40
+ * );
41
+ */
42
+ export const ReferenceArrayField = <
43
+ RecordType extends RaRecord = RaRecord,
44
+ ReferenceRecordType extends RaRecord = RaRecord,
45
+ >(
46
+ props: ReferenceArrayFieldProps<RecordType, ReferenceRecordType>,
47
+ ) => {
48
+ const {
49
+ filter,
50
+ page = 1,
51
+ perPage,
52
+ reference,
53
+ resource,
54
+ sort,
55
+ source,
56
+ queryOptions,
57
+ render,
58
+ ...rest
59
+ } = props;
60
+ return (
61
+ <ReferenceArrayFieldBase
62
+ filter={filter}
63
+ page={page}
64
+ perPage={perPage}
65
+ reference={reference}
66
+ resource={resource}
67
+ sort={sort}
68
+ source={source}
69
+ queryOptions={queryOptions}
70
+ render={render}
71
+ >
72
+ <PureReferenceArrayFieldView {...rest} />
73
+ </ReferenceArrayFieldBase>
74
+ );
75
+ };
76
+ export interface ReferenceArrayFieldProps<
77
+ RecordType extends RaRecord = RaRecord,
78
+ ReferenceRecordType extends RaRecord = RaRecord,
79
+ > extends ReferenceArrayFieldViewProps {
80
+ filter?: FilterPayload;
81
+ page?: number;
82
+ pagination?: ReactElement;
83
+ perPage?: number;
84
+ reference: string;
85
+ resource?: string;
86
+ source: NoInfer<HintedString<ExtractRecordPaths<RecordType>>>;
87
+ sort?: SortPayload;
88
+ queryOptions?: Omit<
89
+ UseQueryOptions<ReferenceRecordType[], Error>,
90
+ "queryFn" | "queryKey"
91
+ >;
92
+ render?: (props: ListControllerResult<ReferenceRecordType>) => ReactElement;
93
+ }
94
+
95
+ export interface ReferenceArrayFieldViewProps {
96
+ children?: ReactNode;
97
+ className?: string;
98
+ empty?: ReactNode;
99
+ error?: ReactNode;
100
+ loading?: ReactNode;
101
+ pagination?: ReactNode;
102
+ }
103
+
104
+ export const ReferenceArrayFieldView = (
105
+ props: ReferenceArrayFieldViewProps,
106
+ ) => {
107
+ const {
108
+ children = defaultChildren,
109
+ className,
110
+ empty,
111
+ error: errorElement,
112
+ loading,
113
+ pagination,
114
+ } = props;
115
+ const {
116
+ isPending,
117
+ error,
118
+ total,
119
+ hasPreviousPage,
120
+ hasNextPage,
121
+ data,
122
+ filterValues,
123
+ } = useListContext();
124
+
125
+ return (
126
+ <div className={className}>
127
+ {isPending && loading !== false ? (
128
+ loading
129
+ ) : error && errorElement !== false ? (
130
+ errorElement
131
+ ) : (total === 0 ||
132
+ (total == null &&
133
+ hasPreviousPage === false &&
134
+ hasNextPage === false &&
135
+ // @ts-expect-error FIXME total may be undefined when using partial pagination but the ListControllerResult type is wrong about it
136
+ data.length === 0 &&
137
+ // the user didn't set any filters
138
+ !Object.keys(filterValues).length)) &&
139
+ empty !== false ? (
140
+ empty
141
+ ) : (
142
+ <span>
143
+ {children}
144
+ {pagination && total !== undefined ? pagination : null}
145
+ </span>
146
+ )}
147
+ </div>
148
+ );
149
+ };
150
+
151
+ const defaultChildren = <SingleFieldList />;
152
+ const PureReferenceArrayFieldView = memo(ReferenceArrayFieldView);
@@ -0,0 +1,68 @@
1
+ import * as React from "react";
2
+ import type { ReactElement } from "react";
3
+ import type { InputProps, UseReferenceArrayInputParams } from "ra-core";
4
+ import {
5
+ useReferenceArrayInputController,
6
+ ResourceContextProvider,
7
+ ChoicesContextProvider,
8
+ } from "ra-core";
9
+ import { AutocompleteArrayInput } from "@/components/admin/autocomplete-array-input";
10
+
11
+ /**
12
+ * Form input for editing arrays of foreign key relationships with autocompletion.
13
+ *
14
+ * This component fetches related records from a reference resource and displays them
15
+ * in a searchable multi-select interface using AutocompleteArrayInput.
16
+ * Use it to edit one-to-many or many-to-many relationships, where the current record
17
+ * has an array of foreign keys to another resource.
18
+ *
19
+ * @see {@link https://marmelab.com/shadcn-admin-kit/docs/referencearrayinput/ ReferenceArrayInput documentation}
20
+ *
21
+ * @example
22
+ * import { Edit, SimpleForm, TextInput, ReferenceArrayInput } from '@/components/admin';
23
+ *
24
+ * const PostEdit = () => (
25
+ * <Edit>
26
+ * <SimpleForm>
27
+ * <TextInput source="title" />
28
+ * <ReferenceArrayInput source="tag_ids" reference="tags" />
29
+ * </SimpleForm>
30
+ * </Edit>
31
+ * );
32
+ */
33
+ export const ReferenceArrayInput = (props: ReferenceArrayInputProps) => {
34
+ const {
35
+ children = defaultChildren,
36
+ reference,
37
+ sort,
38
+ filter = defaultFilter,
39
+ } = props;
40
+ if (React.Children.count(children) !== 1) {
41
+ throw new Error(
42
+ "<ReferenceArrayInput> only accepts a single child (like <AutocompleteArrayInput>)",
43
+ );
44
+ }
45
+
46
+ const controllerProps = useReferenceArrayInputController({
47
+ ...props,
48
+ sort,
49
+ filter,
50
+ });
51
+
52
+ return (
53
+ <ResourceContextProvider value={reference}>
54
+ <ChoicesContextProvider value={controllerProps}>
55
+ {children}
56
+ </ChoicesContextProvider>
57
+ </ResourceContextProvider>
58
+ );
59
+ };
60
+
61
+ const defaultChildren = <AutocompleteArrayInput />;
62
+ const defaultFilter = {};
63
+
64
+ export interface ReferenceArrayInputProps
65
+ extends InputProps,
66
+ UseReferenceArrayInputParams {
67
+ children?: ReactElement;
68
+ }
@@ -0,0 +1,153 @@
1
+ import type {
2
+ ExtractRecordPaths,
3
+ LinkToType,
4
+ RaRecord,
5
+ UseReferenceFieldControllerResult,
6
+ } from "ra-core";
7
+ import {
8
+ ReferenceFieldBase,
9
+ useFieldValue,
10
+ useGetRecordRepresentation,
11
+ useReferenceFieldContext,
12
+ useTranslate,
13
+ } from "ra-core";
14
+ import type { MouseEvent, ReactNode } from "react";
15
+ import { Link } from "react-router";
16
+ import type { UseQueryOptions } from "@tanstack/react-query";
17
+
18
+ /**
19
+ * Displays a field from a related record by following a foreign key relationship.
20
+ *
21
+ * This field fetches the related record using the foreign key value and displays it using the record representation.
22
+ * It supports linking to the related record's show or edit page.
23
+ * To be used with RecordField or DataTable.Col components, or anywhere a RecordContext is available.
24
+ *
25
+ * @see {@link https://marmelab.com/shadcn-admin-kit/docs/referencefield/ ReferenceField documentation}
26
+ *
27
+ * @example
28
+ * import { List, DataTable, ReferenceField } from '@/components/admin';
29
+ *
30
+ * const PostList = () => (
31
+ * <List>
32
+ * <DataTable>
33
+ * <DataTable.Col source="title" />
34
+ * <DataTable.Col label="Author">
35
+ * <ReferenceField source="author_id" reference="authors" link="show" />
36
+ * </DataTable.Col>
37
+ * </DataTable>
38
+ * </List>
39
+ * );
40
+ */
41
+ export const ReferenceField = <
42
+ RecordType extends RaRecord = RaRecord,
43
+ ReferenceRecordType extends RaRecord = RaRecord,
44
+ >(
45
+ props: ReferenceFieldProps<RecordType, ReferenceRecordType>,
46
+ ) => {
47
+ const { loading, error, empty, render, ...rest } = props;
48
+ const id = useFieldValue<RecordType>(props);
49
+ const translate = useTranslate();
50
+
51
+ return id == null ? (
52
+ typeof empty === "string" ? (
53
+ <>{empty && translate(empty, { _: empty })}</>
54
+ ) : (
55
+ empty
56
+ )
57
+ ) : (
58
+ <ReferenceFieldBase {...rest}>
59
+ <ReferenceFieldView<ReferenceRecordType>
60
+ render={render}
61
+ loading={loading}
62
+ error={error}
63
+ {...rest}
64
+ />
65
+ </ReferenceFieldBase>
66
+ );
67
+ };
68
+
69
+ export interface ReferenceFieldProps<
70
+ RecordType extends RaRecord = RaRecord,
71
+ ReferenceRecordType extends RaRecord = RaRecord,
72
+ > extends Partial<ReferenceFieldViewProps<ReferenceRecordType>> {
73
+ children?: ReactNode;
74
+ queryOptions?: UseQueryOptions<RaRecord[], Error> & {
75
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
76
+ meta?: any;
77
+ };
78
+ record?: RecordType;
79
+ reference: string;
80
+ translateChoice?: ((record: ReferenceRecordType) => string) | boolean;
81
+ link?: LinkToType;
82
+ source: ExtractRecordPaths<RecordType>;
83
+ }
84
+
85
+ // useful to prevent click bubbling in a datagrid with rowClick
86
+ const stopPropagation = (e: MouseEvent<HTMLAnchorElement>) =>
87
+ e.stopPropagation();
88
+
89
+ export const ReferenceFieldView = <
90
+ ReferenceRecordType extends RaRecord = RaRecord,
91
+ >(
92
+ props: ReferenceFieldViewProps<ReferenceRecordType>,
93
+ ) => {
94
+ const {
95
+ children,
96
+ className,
97
+ empty,
98
+ error: errorElement,
99
+ render,
100
+ reference,
101
+ loading,
102
+ } = props;
103
+ const referenceFieldContext = useReferenceFieldContext();
104
+ const { error, link, isPending, referenceRecord } = referenceFieldContext;
105
+ const getRecordRepresentation = useGetRecordRepresentation(reference);
106
+ const translate = useTranslate();
107
+
108
+ if (error && errorElement !== false) {
109
+ return errorElement;
110
+ }
111
+ if (isPending && loading !== false) {
112
+ return loading;
113
+ }
114
+ if (!referenceRecord && empty !== false) {
115
+ return typeof empty === "string" ? (
116
+ <>{empty && translate(empty, { _: empty })}</>
117
+ ) : (
118
+ empty
119
+ );
120
+ }
121
+
122
+ const child = render
123
+ ? render(referenceFieldContext)
124
+ : children || <span>{getRecordRepresentation(referenceRecord)}</span>;
125
+
126
+ if (link) {
127
+ return (
128
+ <div className={className}>
129
+ <Link to={link} onClick={stopPropagation}>
130
+ {child}
131
+ </Link>
132
+ </div>
133
+ );
134
+ }
135
+
136
+ return <>{child}</>;
137
+ };
138
+
139
+ export interface ReferenceFieldViewProps<
140
+ ReferenceRecordType extends RaRecord = RaRecord,
141
+ > {
142
+ children?: ReactNode;
143
+ className?: string;
144
+ empty?: ReactNode;
145
+ loading?: ReactNode;
146
+ render?: (props: UseReferenceFieldControllerResult) => ReactNode;
147
+ reference: string;
148
+ source: string;
149
+ resource?: string;
150
+ translateChoice?: ((record: ReferenceRecordType) => string) | boolean;
151
+ resourceLinkPath?: LinkToType;
152
+ error?: ReactNode;
153
+ }
@@ -0,0 +1,46 @@
1
+ import type { ReferenceInputBaseProps } from "ra-core";
2
+ import { ReferenceInputBase } from "ra-core";
3
+ import { AutocompleteInput } from "./autocomplete-input";
4
+
5
+ /**
6
+ * Form input for editing foreign key relationships with autocompletion.
7
+ *
8
+ * This component fetches related records from a reference resource and displays them in a searchable dropdown using AutocompleteInput.
9
+ * Use it to edit many-to-one relationships, where the current record has a foreign key to another resource.
10
+ *
11
+ * @see {@link https://marmelab.com/shadcn-admin-kit/docs/referenceinput/ ReferenceInput documentation}
12
+ *
13
+ * @example
14
+ * import { Edit, SimpleForm, TextInput, ReferenceInput } from '@/components/admin';
15
+ *
16
+ * const ContactEdit = () => (
17
+ * <Edit>
18
+ * <SimpleForm>
19
+ * <TextInput source="first_name" />
20
+ * <TextInput source="last_name" />
21
+ * <TextInput source="title" />
22
+ * <ReferenceInput source="company_id" reference="companies" />
23
+ * </SimpleForm>
24
+ * </Edit>
25
+ * );
26
+ */
27
+ export const ReferenceInput = (props: ReferenceInputProps) => {
28
+ const { children = defaultChildren, ...rest } = props;
29
+
30
+ if (props.validate && process.env.NODE_ENV !== "production") {
31
+ throw new Error(
32
+ "<ReferenceInput> does not accept a validate prop. Set the validate prop on the child instead.",
33
+ );
34
+ }
35
+
36
+ return <ReferenceInputBase {...rest}>{children}</ReferenceInputBase>;
37
+ };
38
+
39
+ const defaultChildren = <AutocompleteInput />;
40
+
41
+ export interface ReferenceInputProps extends ReferenceInputBaseProps {
42
+ /**
43
+ * Call validate on the child component instead
44
+ */
45
+ validate?: never;
46
+ }
@@ -0,0 +1,92 @@
1
+ import type { RaRecord, SortPayload } from "ra-core";
2
+ import {
3
+ useCreatePath,
4
+ useRecordContext,
5
+ useReferenceManyFieldController,
6
+ } from "ra-core";
7
+ import { Link } from "react-router";
8
+
9
+ /**
10
+ * Displays the count of related records that reference the current record.
11
+ *
12
+ * Calls dataProvider.getList() to compute the the number of records in a related resource that have a foreign key pointing to the current record.
13
+ * It can optionally link to a filtered list of those records.
14
+ *
15
+ * @see {@link https://marmelab.com/shadcn-admin-kit/docs/referencemanycount/ ReferenceManyCount documentation}
16
+ *
17
+ * @example
18
+ * import { List, DataTable, ReferenceManyCount } from '@/components/admin';
19
+ *
20
+ * const AuthorList = () => (
21
+ * <List>
22
+ * <DataTable>
23
+ * <DataTable.Col source="name" />
24
+ * <DataTable.Col label="Number of Books">
25
+ * <ReferenceManyCount reference="books" target="author_id" link />
26
+ * </DataTable.Col>
27
+ * </DataTable>
28
+ * </List>
29
+ * );
30
+ */
31
+ export const ReferenceManyCount = <RecordType extends RaRecord = RaRecord>(
32
+ props: ReferenceManyCountProps<RecordType>,
33
+ ) => {
34
+ const {
35
+ reference,
36
+ target,
37
+ filter,
38
+ sort,
39
+ link,
40
+ resource,
41
+ source = "id",
42
+ } = props;
43
+ const record = useRecordContext<RecordType>(props);
44
+ const createPath = useCreatePath();
45
+
46
+ const { isLoading, error, total } =
47
+ useReferenceManyFieldController<RecordType>({
48
+ filter,
49
+ sort,
50
+ page: 1,
51
+ perPage: 1,
52
+ record,
53
+ reference,
54
+ resource,
55
+ source,
56
+ target,
57
+ });
58
+
59
+ const body = isLoading ? "" : error ? "error" : total;
60
+
61
+ return link && record ? (
62
+ <Link
63
+ to={{
64
+ pathname: createPath({ resource: reference, type: "list" }),
65
+ search: `filter=${JSON.stringify({
66
+ ...(filter || {}),
67
+ [target]: record[source],
68
+ })}`,
69
+ }}
70
+ onClick={(e) => e.stopPropagation()}
71
+ >
72
+ {body}
73
+ </Link>
74
+ ) : (
75
+ <span>{body}</span>
76
+ );
77
+ };
78
+
79
+ export interface ReferenceManyCountProps<
80
+ RecordType extends RaRecord = RaRecord,
81
+ > {
82
+ record?: RecordType;
83
+ reference: string;
84
+ resource?: string;
85
+ target: string;
86
+ source?: string;
87
+ sort?: SortPayload;
88
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
89
+ filter?: any;
90
+ link?: boolean;
91
+ timeout?: number;
92
+ }