@team-codeme/crud-forge 0.0.0-stage → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (415) hide show
  1. package/.cursor/agents/generator-engineer.md +31 -0
  2. package/.cursor/agents/keycloak-engineer.md +33 -0
  3. package/.cursor/agents/qa-engineer.md +32 -0
  4. package/.cursor/agents/security-reviewer.md +30 -0
  5. package/.cursor/mcp.json +13 -0
  6. package/.cursor/rules/crudforge-precautions.mdc +16 -0
  7. package/.cursor/rules/playwright-browser.mdc +30 -0
  8. package/.cursor/rules/readme-todo-sync.mdc +13 -0
  9. package/.env.qa.example +19 -0
  10. package/.github/workflows/qa-live.yml +32 -0
  11. package/.github/workflows/qa.yml +27 -0
  12. package/.vscode/settings.json +32 -0
  13. package/QA/IAM-PLAN.md +25 -0
  14. package/QA/IAM-RESULTS.md +39 -0
  15. package/QA/IAM-TESTCASES.md +36 -0
  16. package/QA/IAM-TODO.md +7 -0
  17. package/QA/KEYCLOAK-BOOTSTRAP.md +105 -0
  18. package/QA/PLAN.md +43 -0
  19. package/QA/RESULTS.md +59 -0
  20. package/QA/TESTCASES.md +65 -0
  21. package/QA/TODO.md +14 -0
  22. package/QA/pmb-dev/README.md +49 -0
  23. package/QA/pmb-dev/config/config.yml +152 -0
  24. package/QA/pmb-dev/gdl/i.gdl +17 -0
  25. package/README.md +851 -2
  26. package/Todo.md +207 -0
  27. package/assets/branding/crudforge-logo.png +0 -0
  28. package/assets/branding/crudforge-mark.png +0 -0
  29. package/branding/poster-crudforge.jpg +0 -0
  30. package/chat/last-chat/Investigating Mock Data Configuration.md +428 -0
  31. package/cli.js +167 -0
  32. package/config/default-config.yml +245 -0
  33. package/docs/performance/README.md +217 -0
  34. package/docs/performance/after.json +111 -0
  35. package/docs/performance/before.json +111 -0
  36. package/docs/quality/README.md +276 -0
  37. package/e2e/crudforge.e2e.yml +47 -0
  38. package/e2e/crudforge.field-profile.yml +33 -0
  39. package/e2e/crudforge.iam-live.yml +124 -0
  40. package/e2e/crudforge.iam.yml +62 -0
  41. package/e2e/tests/field-profile.spec.js +152 -0
  42. package/e2e/tests/generated-crud.spec.js +251 -0
  43. package/e2e/tests/iam-live.spec.js +149 -0
  44. package/e2e/tests/iam-pack.spec.js +151 -0
  45. package/e2e/tests/list-state.spec.js +73 -0
  46. package/features.csv +27 -0
  47. package/fuse-starter-pack/branding/crudforge-mark-source.jpg +0 -0
  48. package/fuse-starter-pack/branding/crudforge-mark-source.png +0 -0
  49. package/fuse-starter-pack/branding/crudforge-mark.png +0 -0
  50. package/fuse-starter-pack/branding/crudforge-wordmark-source.jpg +0 -0
  51. package/fuse-starter-pack/branding/crudforge-wordmark-source.png +0 -0
  52. package/fuse-starter-pack/branding/crudforge-wordmark.png +0 -0
  53. package/fuse-starter-pack/fuse-v21.1/Dockerfile +14 -0
  54. package/fuse-starter-pack/fuse-v21.1/LICENSE.md +6 -0
  55. package/fuse-starter-pack/fuse-v21.1/README.md +59 -0
  56. package/fuse-starter-pack/fuse-v21.1/angular.json +113 -0
  57. package/fuse-starter-pack/fuse-v21.1/eslint.config.ts +150 -0
  58. package/fuse-starter-pack/fuse-v21.1/nginx.conf +23 -0
  59. package/fuse-starter-pack/fuse-v21.1/nginx.dev.conf +18 -0
  60. package/fuse-starter-pack/fuse-v21.1/package-lock.json +11513 -0
  61. package/fuse-starter-pack/fuse-v21.1/package.json +69 -0
  62. package/fuse-starter-pack/fuse-v21.1/postcss.config.json +5 -0
  63. package/fuse-starter-pack/fuse-v21.1/prettier.config.ts +15 -0
  64. package/fuse-starter-pack/fuse-v21.1/proxy.conf.json +8 -0
  65. package/fuse-starter-pack/fuse-v21.1/proxy.dev.conf.json +8 -0
  66. package/fuse-starter-pack/fuse-v21.1/public/favicon.png +0 -0
  67. package/fuse-starter-pack/fuse-v21.1/public/fonts/geist/Geist-Italic.woff2 +0 -0
  68. package/fuse-starter-pack/fuse-v21.1/public/fonts/geist/Geist.woff2 +0 -0
  69. package/fuse-starter-pack/fuse-v21.1/public/fonts/geist/GeistMono-Italic.woff2 +0 -0
  70. package/fuse-starter-pack/fuse-v21.1/public/fonts/geist/GeistMono.woff2 +0 -0
  71. package/fuse-starter-pack/fuse-v21.1/public/i18n/en.json +8 -0
  72. package/fuse-starter-pack/fuse-v21.1/public/i18n/es.json +8 -0
  73. package/fuse-starter-pack/fuse-v21.1/public/images/flags/ES.svg +79 -0
  74. package/fuse-starter-pack/fuse-v21.1/public/images/flags/US.svg +14 -0
  75. package/fuse-starter-pack/fuse-v21.1/public/images/flags/where-to-find-other-flags.txt +5 -0
  76. package/fuse-starter-pack/fuse-v21.1/public/images/logo/logo-mark.png +0 -0
  77. package/fuse-starter-pack/fuse-v21.1/public/images/logo/logo.png +0 -0
  78. package/fuse-starter-pack/fuse-v21.1/push.sh +27 -0
  79. package/fuse-starter-pack/fuse-v21.1/src/app/app.config.server.ts +10 -0
  80. package/fuse-starter-pack/fuse-v21.1/src/app/app.config.ts +64 -0
  81. package/fuse-starter-pack/fuse-v21.1/src/app/app.routes.server.ts +8 -0
  82. package/fuse-starter-pack/fuse-v21.1/src/app/app.routes.ts +39 -0
  83. package/fuse-starter-pack/fuse-v21.1/src/app/app.ts +22 -0
  84. package/fuse-starter-pack/fuse-v21.1/src/app/core/icons/index.ts +1 -0
  85. package/fuse-starter-pack/fuse-v21.1/src/app/core/icons/lucide.ts +1 -0
  86. package/fuse-starter-pack/fuse-v21.1/src/app/core/icons/provider.ts +23 -0
  87. package/fuse-starter-pack/fuse-v21.1/src/app/core/local-storage/index.ts +2 -0
  88. package/fuse-starter-pack/fuse-v21.1/src/app/core/local-storage/local-storage.ts +109 -0
  89. package/fuse-starter-pack/fuse-v21.1/src/app/core/local-storage/provider.ts +15 -0
  90. package/fuse-starter-pack/fuse-v21.1/src/app/core/media/index.ts +2 -0
  91. package/fuse-starter-pack/fuse-v21.1/src/app/core/media/media.ts +64 -0
  92. package/fuse-starter-pack/fuse-v21.1/src/app/core/media/provider.ts +15 -0
  93. package/fuse-starter-pack/fuse-v21.1/src/app/core/theming/index.ts +3 -0
  94. package/fuse-starter-pack/fuse-v21.1/src/app/core/theming/models/theming.ts +13 -0
  95. package/fuse-starter-pack/fuse-v21.1/src/app/core/theming/palette.ts +209 -0
  96. package/fuse-starter-pack/fuse-v21.1/src/app/core/theming/provider.ts +24 -0
  97. package/fuse-starter-pack/fuse-v21.1/src/app/core/theming/theming.ts +129 -0
  98. package/fuse-starter-pack/fuse-v21.1/src/app/core/transloco/transloco-http-loader.ts +12 -0
  99. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/data/navigation.ts +176 -0
  100. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/layout.ts +77 -0
  101. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/ui/language-switcher.ts +91 -0
  102. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/ui/navigation.ts +238 -0
  103. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/ui/notifications.ts +252 -0
  104. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/ui/scheme-switcher.ts +58 -0
  105. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/ui/sidebar.ts +31 -0
  106. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/ui/user.ts +132 -0
  107. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/academy/data/academy.ts +753 -0
  108. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/academy/data/model.ts +27 -0
  109. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/academy/features/course.ts +318 -0
  110. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/academy/features/courses.ts +228 -0
  111. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/academy/routes.ts +14 -0
  112. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/contacts/data/contacts.ts +4372 -0
  113. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/contacts/data/model.ts +34 -0
  114. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/contacts/features/contact.ts +239 -0
  115. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/contacts/features/contacts.ts +185 -0
  116. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/contacts/routes.ts +16 -0
  117. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/file-manager/data/file-manager.ts +261 -0
  118. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/file-manager/data/model.ts +12 -0
  119. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/file-manager/features/file-manager.ts +131 -0
  120. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/file-manager/routes.ts +15 -0
  121. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/file-manager/ui/list.ts +164 -0
  122. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/help-center/features/faq.ts +288 -0
  123. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/help-center/features/guide.ts +134 -0
  124. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/help-center/features/home.ts +219 -0
  125. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/help-center/features/support.ts +161 -0
  126. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/help-center/routes.ts +33 -0
  127. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/notes/data/model.ts +18 -0
  128. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/notes/data/notes.ts +324 -0
  129. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/notes/features/note.ts +152 -0
  130. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/notes/features/notes.ts +118 -0
  131. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/notes/routes.ts +16 -0
  132. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/tasks/data/model.ts +17 -0
  133. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/tasks/data/tasks.ts +562 -0
  134. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/tasks/features/task.ts +195 -0
  135. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/tasks/features/tasks.ts +271 -0
  136. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/tasks/routes.ts +16 -0
  137. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/data/analytics.ts +1620 -0
  138. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/data/finance.ts +1065 -0
  139. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/data/project.ts +376 -0
  140. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/features/analytics/analytics.ts +1096 -0
  141. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/features/finance/finance.ts +658 -0
  142. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/features/project/budget-table.ts +188 -0
  143. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/features/project/project.ts +565 -0
  144. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/routes.ts +23 -0
  145. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/documentation/features/changelog/changelog.ts +932 -0
  146. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/documentation/features/getting-started/building.ts +33 -0
  147. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/documentation/features/getting-started/development.ts +42 -0
  148. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/documentation/features/getting-started/installation.ts +47 -0
  149. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/documentation/layout.ts +9 -0
  150. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/documentation/routes.ts +45 -0
  151. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/error/features/error-page.ts +70 -0
  152. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/error/routes.ts +21 -0
  153. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/notifications/features/notifications.ts +262 -0
  154. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/notifications/routes.ts +10 -0
  155. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/features/account.ts +238 -0
  156. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/features/notifications.ts +134 -0
  157. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/features/plan-and-billing.ts +238 -0
  158. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/features/security.ts +211 -0
  159. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/features/team.ts +188 -0
  160. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/layout.ts +109 -0
  161. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/routes.ts +37 -0
  162. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/welcome/welcome.component.ts +22 -0
  163. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/routes.ts +95 -0
  164. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/forgot-password/forgot-password.html +54 -0
  165. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/forgot-password/forgot-password.ts +51 -0
  166. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/reset-password/reset-password.html +82 -0
  167. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/reset-password/reset-password.ts +69 -0
  168. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/sign-in/sign-in.html +132 -0
  169. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/sign-in/sign-in.ts +54 -0
  170. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/sign-up/sign-up.html +183 -0
  171. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/sign-up/sign-up.ts +56 -0
  172. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/layout.ts +9 -0
  173. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/routes.ts +34 -0
  174. package/fuse-starter-pack/fuse-v21.1/src/app/domains/coming-soon/features/coming-soon.ts +156 -0
  175. package/fuse-starter-pack/fuse-v21.1/src/app/domains/coming-soon/layout.ts +9 -0
  176. package/fuse-starter-pack/fuse-v21.1/src/app/domains/coming-soon/routes.ts +16 -0
  177. package/fuse-starter-pack/fuse-v21.1/src/app/domains/website/layout/layout.ts +9 -0
  178. package/fuse-starter-pack/fuse-v21.1/src/app/domains/website/modules/home/features/home.ts +23 -0
  179. package/fuse-starter-pack/fuse-v21.1/src/app/domains/website/modules/home/routes.ts +10 -0
  180. package/fuse-starter-pack/fuse-v21.1/src/app/domains/website/routes.ts +30 -0
  181. package/fuse-starter-pack/fuse-v21.1/src/environments/environment.mock.ts +5 -0
  182. package/fuse-starter-pack/fuse-v21.1/src/environments/environment.prod.ts +5 -0
  183. package/fuse-starter-pack/fuse-v21.1/src/environments/environment.ts +5 -0
  184. package/fuse-starter-pack/fuse-v21.1/src/index.html +66 -0
  185. package/fuse-starter-pack/fuse-v21.1/src/main.server.ts +11 -0
  186. package/fuse-starter-pack/fuse-v21.1/src/main.ts +5 -0
  187. package/fuse-starter-pack/fuse-v21.1/src/server.ts +70 -0
  188. package/fuse-starter-pack/fuse-v21.1/src/styles/base/base.css +63 -0
  189. package/fuse-starter-pack/fuse-v21.1/src/styles/base/typography.css +54 -0
  190. package/fuse-starter-pack/fuse-v21.1/src/styles/components/a.css +18 -0
  191. package/fuse-starter-pack/fuse-v21.1/src/styles/components/input.css +22 -0
  192. package/fuse-starter-pack/fuse-v21.1/src/styles/components/kbd.css +55 -0
  193. package/fuse-starter-pack/fuse-v21.1/src/styles/components/material.css +1149 -0
  194. package/fuse-starter-pack/fuse-v21.1/src/styles/styles.css +31 -0
  195. package/fuse-starter-pack/fuse-v21.1/src/styles/tailwind/theme.css +147 -0
  196. package/fuse-starter-pack/fuse-v21.1/src/styles/tailwind/utilities.css +563 -0
  197. package/fuse-starter-pack/fuse-v21.1/src/styles/tailwind/variants.css +4 -0
  198. package/fuse-starter-pack/fuse-v21.1/src/styles/third-party/lucide-icons.css +12 -0
  199. package/fuse-starter-pack/fuse-v21.1/tsconfig.app.json +16 -0
  200. package/fuse-starter-pack/fuse-v21.1/tsconfig.json +37 -0
  201. package/fuse-starter-pack/fuse-v21.1/tsconfig.spec.json +10 -0
  202. package/generator/README.md +12 -0
  203. package/generator/issues/.gitkeep +0 -0
  204. package/package.json +56 -4
  205. package/playwright.config.js +29 -0
  206. package/playwright.field-profile.config.js +6 -0
  207. package/playwright.iam-live.config.js +31 -0
  208. package/playwright.iam.config.js +29 -0
  209. package/playwright.list-state.config.js +6 -0
  210. package/playwright.performance.config.js +1 -0
  211. package/run-config-tests.sh +5 -0
  212. package/scripts/e2e-paths.js +89 -0
  213. package/scripts/e2e-prepare-field-profile.js +17 -0
  214. package/scripts/e2e-prepare-iam-live.js +135 -0
  215. package/scripts/e2e-prepare-iam.js +65 -0
  216. package/scripts/e2e-prepare.js +72 -0
  217. package/scripts/e2e-serve-iam-live.js +28 -0
  218. package/scripts/e2e-serve-iam.js +28 -0
  219. package/scripts/e2e-serve.js +28 -0
  220. package/scripts/performance/generate.js +17 -0
  221. package/scripts/performance/measure.js +55 -0
  222. package/scripts/postinstall.js +9 -0
  223. package/scripts/prepare-quality-apps.js +34 -0
  224. package/scripts/run-config-tests.js +63 -0
  225. package/src/assets/logo-with-lable.jpeg +0 -0
  226. package/src/assets/logo.jpeg +0 -0
  227. package/src/commands/bootstrap.js +92 -0
  228. package/src/commands/doctor.js +403 -0
  229. package/src/commands/generate.js +301 -0
  230. package/src/commands/init-config.js +310 -0
  231. package/src/commands/keycloak-options.js +182 -0
  232. package/src/commands/validate.js +52 -0
  233. package/src/config/auth-config.js +183 -0
  234. package/src/config/default-values.js +235 -0
  235. package/src/config/env-refs.js +71 -0
  236. package/src/config/field-preferences.js +99 -0
  237. package/src/config/input-sources.js +104 -0
  238. package/src/config/load-config.js +166 -0
  239. package/src/config/proxy-routes.js +44 -0
  240. package/src/generator/access-control-tools.js +334 -0
  241. package/src/generator/ai-docs.js +691 -0
  242. package/src/generator/application-tests.js +252 -0
  243. package/src/generator/auth-pack.js +965 -0
  244. package/src/generator/embed-config.js +431 -0
  245. package/src/generator/entity-layout.js +30 -0
  246. package/src/generator/fuse-build.js +57 -0
  247. package/src/generator/fuse-runtime.js +344 -0
  248. package/src/generator/generated-banner.js +137 -0
  249. package/src/generator/index.js +874 -0
  250. package/src/generator/project-output.js +126 -0
  251. package/src/generator/team-pack.js +220 -0
  252. package/src/index.js +68 -0
  253. package/src/parser/gdl-parser.js +169 -0
  254. package/src/parser/jdl-parser.js +171 -0
  255. package/src/presets/pmb-test.js +139 -0
  256. package/src/presets/static-source.js +73 -0
  257. package/src/presets/store.js +96 -0
  258. package/src/provision/admin-service.js +148 -0
  259. package/src/provision/bootstrap.js +147 -0
  260. package/src/provision/http.js +123 -0
  261. package/src/provision/keycloak-admin-rest.js +335 -0
  262. package/src/provision/state.js +51 -0
  263. package/src/provision/token.js +52 -0
  264. package/src/templates/angular/auth/access-control.service.ts.ejs +179 -0
  265. package/src/templates/angular/auth/access-ctrl.pipe.ts.ejs +20 -0
  266. package/src/templates/angular/auth/auth.guard.ts.ejs +27 -0
  267. package/src/templates/angular/auth/auth.interceptor.ts.ejs +53 -0
  268. package/src/templates/angular/auth/auth.service.ts.ejs +594 -0
  269. package/src/templates/angular/auth/auth.utils.ts.ejs +28 -0
  270. package/src/templates/angular/auth/current-user.ts.ejs +24 -0
  271. package/src/templates/angular/auth/disabled-account-overlay.component.css.ejs +95 -0
  272. package/src/templates/angular/auth/disabled-account-overlay.component.html.ejs +33 -0
  273. package/src/templates/angular/auth/disabled-account-overlay.component.ts.ejs +23 -0
  274. package/src/templates/angular/auth/fuse-account.ts.ejs +234 -0
  275. package/src/templates/angular/auth/fuse-user.ts.ejs +264 -0
  276. package/src/templates/angular/auth/has-permission.directive.ts.ejs +51 -0
  277. package/src/templates/angular/auth/index.ts.ejs +24 -0
  278. package/src/templates/angular/auth/keycloak-admin.service.ts.ejs +670 -0
  279. package/src/templates/angular/auth/landing.guard.ts.ejs +61 -0
  280. package/src/templates/angular/auth/no-auth.guard.ts.ejs +19 -0
  281. package/src/templates/angular/auth/permission-attribute.util.ts.ejs +182 -0
  282. package/src/templates/angular/auth/sign-in.ts.ejs +60 -0
  283. package/src/templates/angular/entity/_entity_.model.ts.ejs +64 -0
  284. package/src/templates/angular/entity/_entity_.routes.ts.ejs +9 -0
  285. package/src/templates/angular/entity/components/forms/form/_entity_-form.component.html.ejs +168 -0
  286. package/src/templates/angular/entity/components/forms/form/_entity_-form.component.ts.ejs +175 -0
  287. package/src/templates/angular/entity/components/forms/form-page/_entity_-form-page.component.html.ejs +10 -0
  288. package/src/templates/angular/entity/components/forms/form-page/_entity_-form-page.component.ts.ejs +86 -0
  289. package/src/templates/angular/entity/components/forms/update/_entity_-form.service.ts.ejs +136 -0
  290. package/src/templates/angular/entity/components/interaction/actions/_entity_-actions.component.html.ejs +68 -0
  291. package/src/templates/angular/entity/components/interaction/actions/_entity_-actions.component.ts.ejs +69 -0
  292. package/src/templates/angular/entity/components/interaction/filter/_entity_-filter.component.html.ejs +111 -0
  293. package/src/templates/angular/entity/components/interaction/filter/_entity_-filter.component.ts.ejs +102 -0
  294. package/src/templates/angular/entity/components/presentation/card/_entity_-card.component.css.ejs +33 -0
  295. package/src/templates/angular/entity/components/presentation/card/_entity_-card.component.html.ejs +29 -0
  296. package/src/templates/angular/entity/components/presentation/card/_entity_-card.component.ts.ejs +93 -0
  297. package/src/templates/angular/entity/components/presentation/detail/_entity_-detail.component.css.ejs +54 -0
  298. package/src/templates/angular/entity/components/presentation/detail/_entity_-detail.component.html.ejs +58 -0
  299. package/src/templates/angular/entity/components/presentation/detail/_entity_-detail.component.ts.ejs +47 -0
  300. package/src/templates/angular/entity/components/presentation/list/_entity_-list.component.html.ejs +419 -0
  301. package/src/templates/angular/entity/components/presentation/list/_entity_-list.component.scss.ejs +48 -0
  302. package/src/templates/angular/entity/components/presentation/list/_entity_-list.component.ts.ejs +592 -0
  303. package/src/templates/angular/entity/service/_entity_.service.ts.ejs +153 -0
  304. package/src/templates/angular/entity/settings/_entity_.settings.ts.ejs +49 -0
  305. package/src/templates/angular/enums/_enum_.model.ts.ejs +11 -0
  306. package/src/templates/angular/iam/change-password.component.html.ejs +39 -0
  307. package/src/templates/angular/iam/change-password.component.ts.ejs +44 -0
  308. package/src/templates/angular/iam/no-access.component.ts.ejs +17 -0
  309. package/src/templates/angular/iam/role-list.component.html.ejs +331 -0
  310. package/src/templates/angular/iam/role-list.component.scss.ejs +107 -0
  311. package/src/templates/angular/iam/role-list.component.ts.ejs +597 -0
  312. package/src/templates/angular/iam/role-management/role-header.component.html.ejs +51 -0
  313. package/src/templates/angular/iam/role-management/role-header.component.ts.ejs +45 -0
  314. package/src/templates/angular/iam/role-management/role-inheritance.component.html.ejs +15 -0
  315. package/src/templates/angular/iam/role-management/role-inheritance.component.ts.ejs +19 -0
  316. package/src/templates/angular/iam/role-management/role-permissions-panel.component.css.ejs +24 -0
  317. package/src/templates/angular/iam/role-management/role-permissions-panel.component.html.ejs +108 -0
  318. package/src/templates/angular/iam/role-management/role-permissions-panel.component.ts.ejs +122 -0
  319. package/src/templates/angular/iam/role-management/role-users.component.html.ejs +104 -0
  320. package/src/templates/angular/iam/role-management/role-users.component.ts.ejs +53 -0
  321. package/src/templates/angular/iam/role-management/user-select-dialog.component.html.ejs +113 -0
  322. package/src/templates/angular/iam/role-management/user-select-dialog.component.ts.ejs +157 -0
  323. package/src/templates/angular/iam/role-permission-matrix.component.html.ejs +355 -0
  324. package/src/templates/angular/iam/role-permission-matrix.component.scss.ejs +217 -0
  325. package/src/templates/angular/iam/role-permission-matrix.component.ts.ejs +800 -0
  326. package/src/templates/angular/iam/screen-catalog.ts.ejs +147 -0
  327. package/src/templates/angular/iam/shared/confirm-dialog.component.ts.ejs +83 -0
  328. package/src/templates/angular/iam/shared/matrix-hierarchy.util.ts.ejs +196 -0
  329. package/src/templates/angular/iam/shared/permission-matrix-sound.ts.ejs +59 -0
  330. package/src/templates/angular/iam/shared/role-display.util.ts.ejs +43 -0
  331. package/src/templates/angular/iam/shared/role-permission-skeleton.component.ts.ejs +54 -0
  332. package/src/templates/angular/iam/shared/screen-matrix.util.ts.ejs +554 -0
  333. package/src/templates/angular/iam/shared/screen-navigation-map.ts.ejs +187 -0
  334. package/src/templates/angular/iam/shared/screen-navigation.registry.ts.ejs +64 -0
  335. package/src/templates/angular/iam/shared/text-highlight.pipe.ts.ejs +39 -0
  336. package/src/templates/angular/iam/user-access-matrix.component.html.ejs +212 -0
  337. package/src/templates/angular/iam/user-access-matrix.component.scss.ejs +34 -0
  338. package/src/templates/angular/iam/user-access-matrix.component.ts.ejs +239 -0
  339. package/src/templates/angular/iam/user-detail.component.html.ejs +143 -0
  340. package/src/templates/angular/iam/user-detail.component.ts.ejs +108 -0
  341. package/src/templates/angular/iam/user-form.component.html.ejs +63 -0
  342. package/src/templates/angular/iam/user-form.component.ts.ejs +100 -0
  343. package/src/templates/angular/iam/user-list.component.html.ejs +369 -0
  344. package/src/templates/angular/iam/user-list.component.scss.ejs +242 -0
  345. package/src/templates/angular/iam/user-list.component.ts.ejs +446 -0
  346. package/src/templates/angular/iam/user-management.routes.ts.ejs +47 -0
  347. package/src/templates/angular/iam/user-permission-matrix.component.html.ejs +231 -0
  348. package/src/templates/angular/iam/user-permission-matrix.component.scss.ejs +216 -0
  349. package/src/templates/angular/iam/user-permission-matrix.component.ts.ejs +516 -0
  350. package/src/templates/angular/shared/base/audit-user-name.pipe.ts.ejs +69 -0
  351. package/src/templates/angular/shared/base/base-filter.component.ts.ejs +245 -0
  352. package/src/templates/angular/shared/base/base-form.component.ts.ejs +109 -0
  353. package/src/templates/angular/shared/base/base-list.component.ts.ejs +507 -0
  354. package/src/templates/angular/shared/base/filter-types.ts.ejs +55 -0
  355. package/src/templates/angular/shared/base/input-format.directive.ts.ejs +47 -0
  356. package/src/templates/angular/shared/base/input-format.ts.ejs +15 -0
  357. package/src/templates/angular/shared/confirm-with-input-dialog.component.ts.ejs +91 -0
  358. package/src/templates/angular/shared/confirmation-dialog.component.ts.ejs +80 -0
  359. package/src/templates/angular/shared/list-styles.css.ejs +103 -0
  360. package/src/templates/angular/shared/loading-overlay.component.ts.ejs +24 -0
  361. package/src/templates/angular/shared/resizable.directive.ts.ejs +115 -0
  362. package/src/templates/angular/shared/snackbar-styles.css.ejs +11 -0
  363. package/src/templates/fuse-packs/access-control-tools/access-control-sync.js +819 -0
  364. package/src/templates/fuse-packs/access-control-tools/build-rename-map.js +67 -0
  365. package/src/templates/fuse-packs/access-control-tools/inject-qa-ids.js +14 -0
  366. package/src/templates/fuse-packs/access-control-tools/lib/hierarchy-scanner.js +628 -0
  367. package/src/templates/fuse-packs/access-control-tools/lib/hierarchy-scanner.test.js +323 -0
  368. package/src/templates/fuse-packs/access-control-tools/lib/html-scanner.js +362 -0
  369. package/src/templates/fuse-packs/access-control-tools/lib/id-rules.duplicate.test.js +136 -0
  370. package/src/templates/fuse-packs/access-control-tools/lib/id-rules.js +1095 -0
  371. package/src/templates/fuse-packs/access-control-tools/lib/ts-component-index.js +482 -0
  372. package/src/templates/fuse-packs/access-control-tools/output/.gitkeep +0 -0
  373. package/src/templates/fuse-packs/access-control-tools/run.sh +223 -0
  374. package/src/templates/fuse-packs/access-control-tools/scan-access-control.js +14 -0
  375. package/src/templates/fuse-packs/iam-assets/sound/apple-play.mp3 +0 -0
  376. package/src/templates/fuse-packs/iam-assets/sound/remove.mp3 +0 -0
  377. package/src/templates/generator/README.md +12 -0
  378. package/src/templates/testing/ci.cjs +45 -0
  379. package/src/templates/testing/mock.cjs +149 -0
  380. package/src/templates/testing/playwright.config.cjs +25 -0
  381. package/src/templates/testing/serve.cjs +22 -0
  382. package/src/templates/testing/smoke.spec.cjs +180 -0
  383. package/src/utils/branding.js +39 -0
  384. package/src/utils/colors.js +18 -0
  385. package/src/utils/diff.js +109 -0
  386. package/src/utils/merger.js +115 -0
  387. package/src/validator/backend-diagnostics.js +30 -0
  388. package/src/validator/blueprint-validator.js +276 -0
  389. package/src/validator/diagnostics.js +608 -0
  390. package/src/validator/pattern.js +28 -0
  391. package/test/auth-interceptor.js +84 -0
  392. package/test/auth-provision-checks.js +297 -0
  393. package/test/field-preferences.js +145 -0
  394. package/test/fixtures/field-profile.gdl +7 -0
  395. package/test/fixtures/mock.jdl +17 -0
  396. package/test/fixtures/mock.png +0 -0
  397. package/test/fixtures/performance/config.yml +33 -0
  398. package/test/fixtures/performance/large.gdl +199 -0
  399. package/test/fixtures/performance/small.gdl +7 -0
  400. package/test/fixtures/quality/custom.yml +22 -0
  401. package/test/fixtures/quality/go-duck.yml +22 -0
  402. package/test/fixtures/quality/jhipster.yml +30 -0
  403. package/test/fixtures/quality/representative.gdl +14 -0
  404. package/test/list-state.js +138 -0
  405. package/test/micro-functions-layout.js +95 -0
  406. package/test/performance-generation.js +32 -0
  407. package/test/pmb-preset.js +127 -0
  408. package/test/project-workflow.js +111 -0
  409. package/test/quality-features.js +250 -0
  410. package/test/verify-commands.js +83 -0
  411. package/test/verify.js +959 -0
  412. package/test-files/GDL/example.gdl +15 -0
  413. package/test-files/JDL/example.jdl +15 -0
  414. package/test-files/config/crudforge.config.yml +127 -0
  415. package/test-run.sh +272 -0
@@ -0,0 +1,658 @@
1
+ import { CurrencyPipe, DatePipe, NgClass } from '@angular/common';
2
+ import { afterNextRender, Component, inject, viewChild } from '@angular/core';
3
+ import { MatButtonModule } from '@angular/material/button';
4
+ import { MatCard } from '@angular/material/card';
5
+ import { MatDividerModule } from '@angular/material/divider';
6
+ import { MatIconModule } from '@angular/material/icon';
7
+ import { MatMenuModule } from '@angular/material/menu';
8
+ import { MatProgressBarModule } from '@angular/material/progress-bar';
9
+ import { MatSort, MatSortModule } from '@angular/material/sort';
10
+ import { MatTableDataSource, MatTableModule } from '@angular/material/table';
11
+ import { ApexOptions, NgApexchartsModule } from 'ng-apexcharts';
12
+ import {
13
+ FinanceDashboardService,
14
+ Transaction,
15
+ } from '@/app/domains/admin/modules/dashboards/data/finance';
16
+
17
+ @Component({
18
+ selector: 'finance-dashboard',
19
+ imports: [
20
+ MatButtonModule,
21
+ MatIconModule,
22
+ MatMenuModule,
23
+ MatDividerModule,
24
+ NgApexchartsModule,
25
+ MatTableModule,
26
+ MatSortModule,
27
+ NgClass,
28
+ MatProgressBarModule,
29
+ CurrencyPipe,
30
+ DatePipe,
31
+ MatCard,
32
+ ],
33
+ template: `
34
+ <div
35
+ class="@container mx-auto flex w-full max-w-7xl flex-auto flex-col gap-4 p-6 sm:gap-6 lg:p-10 lg:pt-8"
36
+ >
37
+ <!-- Header -->
38
+ <div class="flex items-center justify-between gap-x-3">
39
+ <div class="flex flex-col gap-y-0.5">
40
+ <div class="text-xl font-semibold tracking-tighter sm:text-2xl">
41
+ Finance
42
+ </div>
43
+ <div class="text-neutral-500">
44
+ Overview of your financial performance including revenue, expenses,
45
+ and profit trends.
46
+ </div>
47
+ </div>
48
+
49
+ <!-- Spacer -->
50
+ <div class="flex-auto"></div>
51
+
52
+ <!-- Actions -->
53
+ <div class="flex items-center gap-x-3">
54
+ <button
55
+ class="hidden sm:inline-flex"
56
+ matButton="outlined"
57
+ >
58
+ <mat-icon svgIcon="file-chart-column" />
59
+ Reports
60
+ </button>
61
+ <button
62
+ class="hidden sm:inline-flex"
63
+ matButton="outlined"
64
+ >
65
+ <mat-icon svgIcon="settings" />
66
+ Settings
67
+ </button>
68
+ <button
69
+ class="hidden sm:inline-flex"
70
+ mat-flat-button
71
+ >
72
+ <mat-icon svgIcon="upload" />
73
+ Export
74
+ </button>
75
+
76
+ <!-- Mobile actions menu -->
77
+ <div class="sm:hidden">
78
+ <button
79
+ matIconButton
80
+ [matMenuTriggerFor]="actionsMenu"
81
+ >
82
+ <mat-icon svgIcon="ellipsis" />
83
+ </button>
84
+ <mat-menu #actionsMenu="matMenu">
85
+ <button mat-menu-item>Export</button>
86
+ <button mat-menu-item>Reports</button>
87
+ <button mat-menu-item>Settings</button>
88
+ </mat-menu>
89
+ </div>
90
+ </div>
91
+ </div>
92
+
93
+ <div class="grid w-full grid-cols-1 gap-6 xl:grid-cols-2">
94
+ <div class="grid gap-8 sm:grid-flow-col xl:grid-flow-row">
95
+ <!-- Previous statement -->
96
+ <mat-card
97
+ class="overflow-hidden px-5 py-4"
98
+ appearance="outlined"
99
+ >
100
+ <div class="absolute right-0 bottom-0 -m-6 h-24 w-24">
101
+ <mat-icon
102
+ class="size-24 text-green-600/25 dark:text-green-500/25"
103
+ svgIcon="circle-check"
104
+ />
105
+ </div>
106
+ <div class="flex items-center">
107
+ <div class="flex flex-col">
108
+ <div class="truncate text-lg font-medium tracking-tight">
109
+ Previous Statement
110
+ </div>
111
+ <div class="text-sm font-medium text-green-600">
112
+ Paid on {{ data.previousStatement.date }}
113
+ </div>
114
+ </div>
115
+ <div class="-mt-2 ml-auto">
116
+ <button
117
+ mat-icon-button
118
+ [matMenuTriggerFor]="previousStatementMenu"
119
+ >
120
+ <mat-icon svgIcon="ellipsis" />
121
+ </button>
122
+ <mat-menu #previousStatementMenu="matMenu">
123
+ <button mat-menu-item>View statement</button>
124
+ <button mat-menu-item>Spending breakdown</button>
125
+ <button mat-menu-item>Tax breakdown</button>
126
+ <mat-divider />
127
+ <button mat-menu-item>Print statement</button>
128
+ <button mat-menu-item>Email statement</button>
129
+ </mat-menu>
130
+ </div>
131
+ </div>
132
+ <div class="mt-4 flex flex-row flex-wrap gap-6">
133
+ <div class="flex flex-col">
134
+ <div class="text-sm font-medium text-neutral-500">
135
+ Card Limit
136
+ </div>
137
+ <div class="text-3xl font-medium">
138
+ {{ data.previousStatement.limit | currency: 'USD' }}
139
+ </div>
140
+ </div>
141
+ <div class="flex flex-col">
142
+ <div class="text-sm font-medium text-neutral-500">Spent</div>
143
+ <div class="text-3xl font-medium">
144
+ {{ data.previousStatement.spent | currency: 'USD' }}
145
+ </div>
146
+ </div>
147
+ <div class="flex flex-col">
148
+ <div class="text-sm font-medium text-neutral-500">Minimum</div>
149
+ <div class="text-3xl font-medium">
150
+ {{ data.previousStatement.minimum | currency: 'USD' }}
151
+ </div>
152
+ </div>
153
+ </div>
154
+ </mat-card>
155
+
156
+ <!-- Current statement -->
157
+ <mat-card
158
+ class="overflow-hidden px-5 py-4"
159
+ appearance="outlined"
160
+ >
161
+ <div class="absolute right-0 bottom-0 -m-6 h-24 w-24">
162
+ <mat-icon
163
+ class="size-24 text-red-600/25 dark:text-red-500/25"
164
+ svgIcon="circle-alert"
165
+ />
166
+ </div>
167
+ <div class="flex items-center">
168
+ <div class="flex flex-col">
169
+ <div class="truncate text-lg font-medium tracking-tight">
170
+ Current Statement
171
+ </div>
172
+ <div class="text-sm font-medium text-red-600">
173
+ Must be paid before
174
+ {{ data.currentStatement.date }}
175
+ </div>
176
+ </div>
177
+ <div class="-mt-2 ml-auto">
178
+ <button
179
+ mat-icon-button
180
+ [matMenuTriggerFor]="currentStatementMenu"
181
+ >
182
+ <mat-icon svgIcon="ellipsis" />
183
+ </button>
184
+ <mat-menu #currentStatementMenu="matMenu">
185
+ <button mat-menu-item>View statement</button>
186
+ <button mat-menu-item>Spending breakdown</button>
187
+ <button mat-menu-item>Tax breakdown</button>
188
+ <mat-divider />
189
+ <button mat-menu-item>Print statement</button>
190
+ <button mat-menu-item>Email statement</button>
191
+ </mat-menu>
192
+ </div>
193
+ </div>
194
+ <div class="mt-4 flex flex-row flex-wrap gap-6">
195
+ <div class="flex flex-col">
196
+ <div class="text-sm font-medium text-neutral-500">
197
+ Card Limit
198
+ </div>
199
+ <div class="text-3xl font-medium">
200
+ {{ data.currentStatement.limit | currency: 'USD' }}
201
+ </div>
202
+ </div>
203
+ <div class="flex flex-col">
204
+ <div class="text-sm font-medium text-neutral-500">Spent</div>
205
+ <div class="text-3xl font-medium">
206
+ {{ data.currentStatement.spent | currency: 'USD' }}
207
+ </div>
208
+ </div>
209
+ <div class="flex flex-col">
210
+ <div class="text-sm font-medium text-neutral-500">Minimum</div>
211
+ <div class="text-3xl font-medium">
212
+ {{ data.currentStatement.minimum | currency: 'USD' }}
213
+ </div>
214
+ </div>
215
+ </div>
216
+ </mat-card>
217
+ </div>
218
+
219
+ <!-- Account balance -->
220
+ <mat-card
221
+ class="overflow-hidden"
222
+ appearance="outlined"
223
+ >
224
+ <div class="flex flex-col px-5 py-4">
225
+ <div class="flex flex-col">
226
+ <div class="mr-4 truncate text-lg font-medium tracking-tight">
227
+ Account Balance
228
+ </div>
229
+ <div class="font-medium text-neutral-500">
230
+ Monthly balance growth and avg. monthly income
231
+ </div>
232
+ </div>
233
+
234
+ <div class="mt-6 mr-2 flex items-start">
235
+ <div class="flex flex-col">
236
+ <div
237
+ class="text-3xl font-semibold tracking-tighter md:text-4xl"
238
+ >
239
+ {{ data.accountBalance.growRate }}%
240
+ </div>
241
+ <div class="text-sm font-medium text-neutral-500">
242
+ Average Monthly Growth
243
+ </div>
244
+ </div>
245
+ <div class="ml-8 flex flex-col md:ml-16">
246
+ <div
247
+ class="text-3xl font-semibold tracking-tighter md:text-4xl"
248
+ >
249
+ {{ data.accountBalance.ami | currency: 'USD' }}
250
+ </div>
251
+ <div class="text-sm font-medium text-neutral-500">
252
+ Average Monthly Income
253
+ </div>
254
+ </div>
255
+ </div>
256
+ </div>
257
+ <div class="flex flex-auto flex-col">
258
+ <apx-chart
259
+ class="h-full w-full flex-auto"
260
+ [chart]="accountBalanceChart.chart!"
261
+ [colors]="accountBalanceChart.colors!"
262
+ [fill]="accountBalanceChart.fill!"
263
+ [series]="accountBalanceChart.series!"
264
+ [stroke]="accountBalanceChart.stroke!"
265
+ [tooltip]="accountBalanceChart.tooltip!"
266
+ [xaxis]="accountBalanceChart.xaxis!"
267
+ ></apx-chart>
268
+ </div>
269
+ </mat-card>
270
+ </div>
271
+
272
+ <div class="grid w-full grid-cols-1 gap-6">
273
+ <!-- Recent transactions table -->
274
+ <mat-card appearance="outlined">
275
+ <div class="p-6">
276
+ <div class="mr-4 truncate text-lg font-medium tracking-tight">
277
+ Recent transactions
278
+ </div>
279
+ <div class="font-medium text-neutral-500">
280
+ 1 pending, 4 completed
281
+ </div>
282
+ </div>
283
+ <div class="mx-6 overflow-x-auto">
284
+ <table
285
+ class="w-full bg-transparent"
286
+ mat-table
287
+ matSort
288
+ [dataSource]="recentTransactionsDataSource"
289
+ [trackBy]="trackBy"
290
+ #recentTransactionsTable
291
+ >
292
+ <!-- Transaction ID -->
293
+ <ng-container matColumnDef="transactionId">
294
+ <th
295
+ mat-header-cell
296
+ mat-sort-header
297
+ *matHeaderCellDef
298
+ >
299
+ Transaction ID
300
+ </th>
301
+ <td
302
+ mat-cell
303
+ *matCellDef="let transaction"
304
+ >
305
+ <span
306
+ class="pr-6 text-sm font-medium whitespace-nowrap text-neutral-500"
307
+ >
308
+ {{ transaction.transactionId }}
309
+ </span>
310
+ </td>
311
+ </ng-container>
312
+
313
+ <!-- Date -->
314
+ <ng-container matColumnDef="date">
315
+ <th
316
+ mat-header-cell
317
+ mat-sort-header
318
+ *matHeaderCellDef
319
+ >
320
+ Date
321
+ </th>
322
+ <td
323
+ mat-cell
324
+ *matCellDef="let transaction"
325
+ >
326
+ <span class="pr-6 whitespace-nowrap">
327
+ {{ transaction.date | date: 'MMM dd, y' }}
328
+ </span>
329
+ </td>
330
+ </ng-container>
331
+
332
+ <!-- Name -->
333
+ <ng-container matColumnDef="name">
334
+ <th
335
+ mat-header-cell
336
+ mat-sort-header
337
+ *matHeaderCellDef
338
+ >
339
+ Name
340
+ </th>
341
+ <td
342
+ mat-cell
343
+ *matCellDef="let transaction"
344
+ >
345
+ <span class="pr-6 whitespace-nowrap">
346
+ {{ transaction.name }}
347
+ </span>
348
+ </td>
349
+ </ng-container>
350
+
351
+ <!-- Amount -->
352
+ <ng-container matColumnDef="amount">
353
+ <th
354
+ mat-header-cell
355
+ mat-sort-header
356
+ *matHeaderCellDef
357
+ >
358
+ Amount
359
+ </th>
360
+ <td
361
+ mat-cell
362
+ *matCellDef="let transaction"
363
+ >
364
+ <span class="pr-6 font-medium whitespace-nowrap">
365
+ {{ transaction.amount | currency: 'USD' }}
366
+ </span>
367
+ </td>
368
+ </ng-container>
369
+
370
+ <!-- Status -->
371
+ <ng-container matColumnDef="status">
372
+ <th
373
+ mat-header-cell
374
+ mat-sort-header
375
+ *matHeaderCellDef
376
+ >
377
+ Status
378
+ </th>
379
+ <td
380
+ mat-cell
381
+ *matCellDef="let transaction"
382
+ >
383
+ <span
384
+ class="inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-bold tracking-wide uppercase"
385
+ [ngClass]="{
386
+ 'bg-red-200 text-red-800 dark:bg-red-600 dark:text-red-50':
387
+ transaction.status === 'pending',
388
+ 'bg-green-200 text-green-800 dark:bg-green-600 dark:text-green-50':
389
+ transaction.status === 'completed',
390
+ }"
391
+ >
392
+ <span class="leading-relaxed whitespace-nowrap"
393
+ >{{ transaction.status }}
394
+ </span>
395
+ </span>
396
+ </td>
397
+ </ng-container>
398
+
399
+ <!-- Footer -->
400
+ <ng-container matColumnDef="recentOrdersTableFooter">
401
+ <td
402
+ class="border-0 px-0 py-6"
403
+ mat-footer-cell
404
+ *matFooterCellDef
405
+ colspan="6"
406
+ >
407
+ <button mat-stroked-button>See all transactions</button>
408
+ </td>
409
+ </ng-container>
410
+
411
+ <tr
412
+ mat-header-row
413
+ *matHeaderRowDef="recentTransactionsTableColumns"
414
+ ></tr>
415
+ <tr
416
+ class="order-row h-16"
417
+ mat-row
418
+ *matRowDef="let row; columns: recentTransactionsTableColumns"
419
+ ></tr>
420
+ <tr
421
+ class="h-16 border-0"
422
+ mat-footer-row
423
+ *matFooterRowDef="['recentOrdersTableFooter']"
424
+ ></tr>
425
+ </table>
426
+ </div>
427
+ </mat-card>
428
+
429
+ <!-- Budget -->
430
+ <mat-card
431
+ class="p-6"
432
+ appearance="outlined"
433
+ >
434
+ <div class="flex items-center">
435
+ <div class="flex flex-col">
436
+ <div class="mr-4 truncate text-lg font-medium tracking-tight">
437
+ Budget
438
+ </div>
439
+ <div class="font-medium text-neutral-500">
440
+ Monthly budget summary
441
+ </div>
442
+ </div>
443
+ <div class="-mt-2 -mr-2 ml-auto">
444
+ <button
445
+ mat-icon-button
446
+ [matMenuTriggerFor]="budgetMenu"
447
+ >
448
+ <mat-icon svgIcon="ellipsis" />
449
+ </button>
450
+ <mat-menu #budgetMenu="matMenu">
451
+ <button mat-menu-item>Expenses breakdown</button>
452
+ <button mat-menu-item>Savings breakdown</button>
453
+ <button mat-menu-item>Bills breakdown</button>
454
+ <mat-divider />
455
+ <button mat-menu-item>Print budget summary</button>
456
+ <button mat-menu-item>Email budget summary</button>
457
+ </mat-menu>
458
+ </div>
459
+ </div>
460
+ <div class="mt-6 text-sm">
461
+ Last month you had <strong>223</strong> expense transactions,
462
+ <strong>12</strong> savings entries and <strong>4</strong> bills.
463
+ </div>
464
+ <div class="my-8 space-y-8">
465
+ <div class="flex flex-col">
466
+ <div class="flex items-center">
467
+ <div
468
+ class="flex h-14 w-14 items-center justify-center rounded-lg bg-red-100 text-red-800 dark:bg-red-600 dark:text-red-50"
469
+ >
470
+ <mat-icon
471
+ class="size-6"
472
+ svgIcon="credit-card"
473
+ />
474
+ </div>
475
+ <div class="ml-4 flex-auto">
476
+ <div class="text-sm font-medium text-neutral-500">
477
+ Expenses
478
+ </div>
479
+ <div class="text-2xl font-medium">
480
+ {{ data.budget.expenses | currency: 'USD' }}
481
+ </div>
482
+ <mat-progress-bar
483
+ class="mt-2 rounded-full"
484
+ [color]="'error'"
485
+ [mode]="'determinate'"
486
+ [value]="
487
+ (data.budget.expenses * 100) / data.budget.expensesLimit
488
+ "
489
+ ></mat-progress-bar>
490
+ </div>
491
+ <div class="mt-auto ml-6 flex min-w-18 items-end justify-end">
492
+ <div class="font-medium">2.6%</div>
493
+ <mat-icon
494
+ class="ml-1 size-5 text-green-600"
495
+ svgIcon="arrow-down"
496
+ />
497
+ </div>
498
+ </div>
499
+ </div>
500
+
501
+ <div class="flex flex-col">
502
+ <div class="flex items-center">
503
+ <div
504
+ class="flex h-14 w-14 items-center justify-center rounded-lg bg-indigo-100 text-indigo-800 dark:bg-indigo-600 dark:text-indigo-50"
505
+ >
506
+ <mat-icon
507
+ class="size-6 text-current"
508
+ svgIcon="banknote"
509
+ />
510
+ </div>
511
+ <div class="ml-4 flex-auto">
512
+ <div class="text-sm font-medium text-neutral-500">
513
+ Savings
514
+ </div>
515
+ <div class="text-2xl font-medium">
516
+ {{ data.budget.savings | currency: 'USD' }}
517
+ </div>
518
+ <mat-progress-bar
519
+ class="mt-2 rounded-full"
520
+ [mode]="'determinate'"
521
+ [value]="
522
+ (data.budget.savings * 100) / data.budget.savingsGoal
523
+ "
524
+ ></mat-progress-bar>
525
+ </div>
526
+ <div class="mt-auto ml-6 flex min-w-18 items-end justify-end">
527
+ <div class="font-medium">12.7%</div>
528
+ <mat-icon
529
+ class="ml-1 size-5 text-red-600"
530
+ svgIcon="arrow-up"
531
+ />
532
+ </div>
533
+ </div>
534
+ </div>
535
+
536
+ <div class="flex flex-col">
537
+ <div class="flex items-center">
538
+ <div
539
+ class="flex h-14 w-14 items-center justify-center rounded-lg bg-teal-100 text-teal-800 dark:bg-teal-600 dark:text-teal-50"
540
+ >
541
+ <mat-icon
542
+ class="size-6 text-current"
543
+ svgIcon="plug"
544
+ />
545
+ </div>
546
+ <div class="ml-4 flex-auto leading-none">
547
+ <div class="text-sm font-medium text-neutral-500">Bills</div>
548
+ <div class="text-2xl font-medium">
549
+ {{ data.budget.bills | currency: 'USD' }}
550
+ </div>
551
+ <mat-progress-bar
552
+ class="mt-2 rounded-full"
553
+ [mode]="'determinate'"
554
+ [value]="(data.budget.bills * 100) / data.budget.billsLimit"
555
+ ></mat-progress-bar>
556
+ </div>
557
+ <div class="mt-auto ml-6 flex min-w-18 items-end justify-end">
558
+ <div class="font-medium">105.7%</div>
559
+ <mat-icon
560
+ class="ml-1 size-5 text-red-600"
561
+ svgIcon="arrow-up"
562
+ />
563
+ </div>
564
+ </div>
565
+ <div class="mt-3 text-neutral-500">
566
+ Exceeded your personal limit! Be careful next month.
567
+ </div>
568
+ </div>
569
+ </div>
570
+ <div class="mt-auto flex items-center">
571
+ <button
572
+ class="mt-2"
573
+ mat-stroked-button
574
+ >
575
+ Download Summary
576
+ </button>
577
+ </div>
578
+ </mat-card>
579
+ </div>
580
+ </div>
581
+ `,
582
+ })
583
+ export default class FinanceDashboard {
584
+ // Dependencies
585
+ private financeDashboardService = inject(FinanceDashboardService);
586
+
587
+ // Queries
588
+ readonly sort = viewChild(MatSort);
589
+
590
+ // State
591
+ protected data = this.financeDashboardService.data;
592
+ protected recentTransactionsDataSource = new MatTableDataSource(
593
+ this.data.recentTransactions
594
+ );
595
+ protected recentTransactionsTableColumns: string[] = [
596
+ 'transactionId',
597
+ 'date',
598
+ 'name',
599
+ 'amount',
600
+ 'status',
601
+ ];
602
+ protected accountBalanceChart: ApexOptions = {
603
+ chart: {
604
+ animations: {
605
+ speed: 400,
606
+ animateGradually: {
607
+ enabled: false,
608
+ },
609
+ },
610
+ fontFamily: 'inherit',
611
+ foreColor: 'inherit',
612
+ width: '100%',
613
+ height: '100%',
614
+ type: 'area',
615
+ offsetY: 1,
616
+ sparkline: {
617
+ enabled: true,
618
+ },
619
+ },
620
+ colors: ['var(--color-neutral-600)', 'var(--color-neutral-500)'],
621
+ fill: {
622
+ colors: [
623
+ 'light-dark(var(--color-neutral-200), var(--color-neutral-800))',
624
+ 'light-dark(var(--color-neutral-100), var(--color-neutral-700))',
625
+ ],
626
+ opacity: 0.2,
627
+ type: 'solid',
628
+ },
629
+ series: this.data.accountBalance.series,
630
+ stroke: {
631
+ curve: 'straight',
632
+ width: 2,
633
+ },
634
+ tooltip: {
635
+ followCursor: true,
636
+ theme: 'dark',
637
+ x: {
638
+ format: 'MMM dd, yyyy',
639
+ },
640
+ y: {
641
+ formatter: (value): string => value + '%',
642
+ },
643
+ },
644
+ xaxis: {
645
+ type: 'datetime',
646
+ },
647
+ };
648
+
649
+ constructor() {
650
+ afterNextRender(() => {
651
+ this.recentTransactionsDataSource.sort = this.sort() ?? null;
652
+ });
653
+ }
654
+
655
+ trackBy(_: number, item: Transaction) {
656
+ return item.id;
657
+ }
658
+ }