@stacksjs/defaults 0.70.206 → 0.70.208

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 (408) hide show
  1. package/TODO.md +21 -0
  2. package/ai/AGENTS.md +79 -0
  3. package/ai/README.md +45 -0
  4. package/ai/claude/launch.json +12 -0
  5. package/ai/skills/stacks-actions/SKILL.md +128 -0
  6. package/ai/skills/stacks-ai/SKILL.md +276 -0
  7. package/ai/skills/stacks-alias/SKILL.md +94 -0
  8. package/ai/skills/stacks-analytics/SKILL.md +91 -0
  9. package/ai/skills/stacks-api/SKILL.md +738 -0
  10. package/ai/skills/stacks-arrays/SKILL.md +277 -0
  11. package/ai/skills/stacks-auth/SKILL.md +422 -0
  12. package/ai/skills/stacks-auto-imports/SKILL.md +138 -0
  13. package/ai/skills/stacks-brandkit/SKILL.md +811 -0
  14. package/ai/skills/stacks-browse/SKILL.md +127 -0
  15. package/ai/skills/stacks-browse/scripts/browse.ts +492 -0
  16. package/ai/skills/stacks-browser/SKILL.md +145 -0
  17. package/ai/skills/stacks-buddy/SKILL.md +676 -0
  18. package/ai/skills/stacks-build/SKILL.md +163 -0
  19. package/ai/skills/stacks-cache/SKILL.md +125 -0
  20. package/ai/skills/stacks-calendar/SKILL.md +113 -0
  21. package/ai/skills/stacks-chat/SKILL.md +371 -0
  22. package/ai/skills/stacks-cli/SKILL.md +112 -0
  23. package/ai/skills/stacks-cloud/SKILL.md +192 -0
  24. package/ai/skills/stacks-cms/SKILL.md +217 -0
  25. package/ai/skills/stacks-collections/SKILL.md +82 -0
  26. package/ai/skills/stacks-commerce/SKILL.md +114 -0
  27. package/ai/skills/stacks-composables/SKILL.md +161 -0
  28. package/ai/skills/stacks-config/SKILL.md +144 -0
  29. package/ai/skills/stacks-configuration/SKILL.md +154 -0
  30. package/ai/skills/stacks-cron/SKILL.md +123 -0
  31. package/ai/skills/stacks-crosswind/SKILL.md +190 -0
  32. package/ai/skills/stacks-dashboard/SKILL.md +173 -0
  33. package/ai/skills/stacks-database/SKILL.md +286 -0
  34. package/ai/skills/stacks-datetime/SKILL.md +269 -0
  35. package/ai/skills/stacks-dependencies/SKILL.md +111 -0
  36. package/ai/skills/stacks-deploy/SKILL.md +102 -0
  37. package/ai/skills/stacks-design-brutalist/SKILL.md +110 -0
  38. package/ai/skills/stacks-design-minimalist/SKILL.md +115 -0
  39. package/ai/skills/stacks-design-output/SKILL.md +55 -0
  40. package/ai/skills/stacks-design-soft/SKILL.md +156 -0
  41. package/ai/skills/stacks-design-taste/SKILL.md +1012 -0
  42. package/ai/skills/stacks-design-taste-codex/SKILL.md +294 -0
  43. package/ai/skills/stacks-desktop/SKILL.md +78 -0
  44. package/ai/skills/stacks-development/SKILL.md +298 -0
  45. package/ai/skills/stacks-dns/SKILL.md +149 -0
  46. package/ai/skills/stacks-docs/SKILL.md +109 -0
  47. package/ai/skills/stacks-email/SKILL.md +236 -0
  48. package/ai/skills/stacks-enums/SKILL.md +100 -0
  49. package/ai/skills/stacks-env/SKILL.md +181 -0
  50. package/ai/skills/stacks-error-handling/SKILL.md +137 -0
  51. package/ai/skills/stacks-events/SKILL.md +228 -0
  52. package/ai/skills/stacks-faker/SKILL.md +158 -0
  53. package/ai/skills/stacks-git/SKILL.md +158 -0
  54. package/ai/skills/stacks-guard/SKILL.md +98 -0
  55. package/ai/skills/stacks-health/SKILL.md +75 -0
  56. package/ai/skills/stacks-http/SKILL.md +316 -0
  57. package/ai/skills/stacks-i18n/SKILL.md +198 -0
  58. package/ai/skills/stacks-image-to-code/SKILL.md +629 -0
  59. package/ai/skills/stacks-imagegen-mobile/SKILL.md +1474 -0
  60. package/ai/skills/stacks-imagegen-web/SKILL.md +998 -0
  61. package/ai/skills/stacks-investigate/SKILL.md +119 -0
  62. package/ai/skills/stacks-jobs/SKILL.md +136 -0
  63. package/ai/skills/stacks-lint/SKILL.md +184 -0
  64. package/ai/skills/stacks-listeners/SKILL.md +99 -0
  65. package/ai/skills/stacks-logging/SKILL.md +78 -0
  66. package/ai/skills/stacks-mail/SKILL.md +120 -0
  67. package/ai/skills/stacks-middleware/SKILL.md +249 -0
  68. package/ai/skills/stacks-migrations/SKILL.md +105 -0
  69. package/ai/skills/stacks-models/SKILL.md +267 -0
  70. package/ai/skills/stacks-new-feature/SKILL.md +206 -0
  71. package/ai/skills/stacks-notifications/SKILL.md +210 -0
  72. package/ai/skills/stacks-objects/SKILL.md +205 -0
  73. package/ai/skills/stacks-office-hours/SKILL.md +134 -0
  74. package/ai/skills/stacks-orm/SKILL.md +342 -0
  75. package/ai/skills/stacks-path/SKILL.md +118 -0
  76. package/ai/skills/stacks-payments/SKILL.md +373 -0
  77. package/ai/skills/stacks-plan-review/SKILL.md +152 -0
  78. package/ai/skills/stacks-plugins/SKILL.md +149 -0
  79. package/ai/skills/stacks-push/SKILL.md +376 -0
  80. package/ai/skills/stacks-query-builder/SKILL.md +128 -0
  81. package/ai/skills/stacks-queue/SKILL.md +559 -0
  82. package/ai/skills/stacks-realtime/SKILL.md +442 -0
  83. package/ai/skills/stacks-redesign/SKILL.md +182 -0
  84. package/ai/skills/stacks-registry/SKILL.md +58 -0
  85. package/ai/skills/stacks-repl/SKILL.md +80 -0
  86. package/ai/skills/stacks-retro/SKILL.md +122 -0
  87. package/ai/skills/stacks-review/SKILL.md +135 -0
  88. package/ai/skills/stacks-router/SKILL.md +231 -0
  89. package/ai/skills/stacks-routes/SKILL.md +105 -0
  90. package/ai/skills/stacks-scaffolding/SKILL.md +162 -0
  91. package/ai/skills/stacks-scheduler/SKILL.md +363 -0
  92. package/ai/skills/stacks-search-engine/SKILL.md +112 -0
  93. package/ai/skills/stacks-security/SKILL.md +129 -0
  94. package/ai/skills/stacks-security-audit/SKILL.md +128 -0
  95. package/ai/skills/stacks-server/SKILL.md +458 -0
  96. package/ai/skills/stacks-shell/SKILL.md +62 -0
  97. package/ai/skills/stacks-slug/SKILL.md +87 -0
  98. package/ai/skills/stacks-sms/SKILL.md +385 -0
  99. package/ai/skills/stacks-socials/SKILL.md +303 -0
  100. package/ai/skills/stacks-storage/SKILL.md +576 -0
  101. package/ai/skills/stacks-strings/SKILL.md +416 -0
  102. package/ai/skills/stacks-stx/SKILL.md +176 -0
  103. package/ai/skills/stacks-technical-diagrams/LICENSE +22 -0
  104. package/ai/skills/stacks-technical-diagrams/SKILL.md +290 -0
  105. package/ai/skills/stacks-technical-diagrams/agents/openai.yaml +4 -0
  106. package/ai/skills/stacks-technical-diagrams/assets/template.html +1252 -0
  107. package/ai/skills/stacks-technical-diagrams/bin/technical-diagrams.mjs +289 -0
  108. package/ai/skills/stacks-technical-diagrams/bunfig.toml +1 -0
  109. package/ai/skills/stacks-technical-diagrams/examples/agent-run.lifecycle.json +64 -0
  110. package/ai/skills/stacks-technical-diagrams/examples/agent-tool-call.workflow.json +88 -0
  111. package/ai/skills/stacks-technical-diagrams/examples/cache-miss-request.sequence.json +75 -0
  112. package/ai/skills/stacks-technical-diagrams/examples/product-analytics.dataflow.json +70 -0
  113. package/ai/skills/stacks-technical-diagrams/examples/web-app.architecture.json +41 -0
  114. package/ai/skills/stacks-technical-diagrams/renderers/architecture/grid.mjs +62 -0
  115. package/ai/skills/stacks-technical-diagrams/renderers/architecture/render-architecture.mjs +371 -0
  116. package/ai/skills/stacks-technical-diagrams/renderers/dataflow/README.md +82 -0
  117. package/ai/skills/stacks-technical-diagrams/renderers/dataflow/render-dataflow.mjs +295 -0
  118. package/ai/skills/stacks-technical-diagrams/renderers/lifecycle/README.md +91 -0
  119. package/ai/skills/stacks-technical-diagrams/renderers/lifecycle/render-lifecycle.mjs +384 -0
  120. package/ai/skills/stacks-technical-diagrams/renderers/sequence/README.md +84 -0
  121. package/ai/skills/stacks-technical-diagrams/renderers/sequence/render-sequence.mjs +257 -0
  122. package/ai/skills/stacks-technical-diagrams/renderers/shared/cli.mjs +42 -0
  123. package/ai/skills/stacks-technical-diagrams/renderers/shared/generated-validators.mjs +13 -0
  124. package/ai/skills/stacks-technical-diagrams/renderers/shared/geometry.mjs +230 -0
  125. package/ai/skills/stacks-technical-diagrams/renderers/shared/layout-report.mjs +40 -0
  126. package/ai/skills/stacks-technical-diagrams/renderers/shared/utils.mjs +88 -0
  127. package/ai/skills/stacks-technical-diagrams/renderers/shared/validator.mjs +40 -0
  128. package/ai/skills/stacks-technical-diagrams/renderers/workflow/README.md +103 -0
  129. package/ai/skills/stacks-technical-diagrams/renderers/workflow/render-workflow.mjs +481 -0
  130. package/ai/skills/stacks-technical-diagrams/schemas/README.md +68 -0
  131. package/ai/skills/stacks-technical-diagrams/schemas/architecture.schema.json +121 -0
  132. package/ai/skills/stacks-technical-diagrams/schemas/common.schema.json +43 -0
  133. package/ai/skills/stacks-technical-diagrams/schemas/dataflow.schema.json +221 -0
  134. package/ai/skills/stacks-technical-diagrams/schemas/lifecycle.schema.json +241 -0
  135. package/ai/skills/stacks-technical-diagrams/schemas/sequence.schema.json +186 -0
  136. package/ai/skills/stacks-technical-diagrams/schemas/workflow.schema.json +332 -0
  137. package/ai/skills/stacks-technical-diagrams/scripts/check-render-output.mjs +297 -0
  138. package/ai/skills/stacks-technical-diagrams/scripts/render-examples.mjs +28 -0
  139. package/ai/skills/stacks-testing/SKILL.md +129 -0
  140. package/ai/skills/stacks-tunnel/SKILL.md +125 -0
  141. package/ai/skills/stacks-types/SKILL.md +178 -0
  142. package/ai/skills/stacks-ui/SKILL.md +246 -0
  143. package/ai/skills/stacks-utils/SKILL.md +444 -0
  144. package/ai/skills/stacks-validation/SKILL.md +371 -0
  145. package/ai/skills/stacks-whois/SKILL.md +315 -0
  146. package/assets/world-map-data.ts +121 -0
  147. package/bootstrap.ts +114 -0
  148. package/docs/api-examples.md +46 -0
  149. package/docs/index.md +24 -0
  150. package/docs/markdown-examples.md +87 -0
  151. package/functions/analytics.ts +97 -0
  152. package/functions/api.ts +143 -0
  153. package/functions/auth.ts +208 -0
  154. package/functions/billing/payments.ts +149 -0
  155. package/functions/blog.ts +120 -0
  156. package/functions/cms/categorizables.ts +107 -0
  157. package/functions/cms/pages.ts +108 -0
  158. package/functions/cms/posts.ts +100 -0
  159. package/functions/cms/taggables.ts +102 -0
  160. package/functions/commerce/coupons.ts +128 -0
  161. package/functions/commerce/customers.ts +128 -0
  162. package/functions/commerce/gift-cards.ts +119 -0
  163. package/functions/commerce/orders.ts +112 -0
  164. package/functions/commerce/payments.ts +119 -0
  165. package/functions/commerce/products/categories.ts +123 -0
  166. package/functions/commerce/products/manufacturers.ts +123 -0
  167. package/functions/commerce/products/products.ts +123 -0
  168. package/functions/commerce/products/reviews.ts +123 -0
  169. package/functions/commerce/products/units.ts +123 -0
  170. package/functions/commerce/products/variants.ts +123 -0
  171. package/functions/commerce/shippings/delivery-routes.ts +123 -0
  172. package/functions/commerce/shippings/digital-deliveries.ts +119 -0
  173. package/functions/commerce/shippings/drivers.ts +123 -0
  174. package/functions/commerce/shippings/license-keys.ts +123 -0
  175. package/functions/commerce/shippings/shipping-methods.ts +123 -0
  176. package/functions/commerce/shippings/shipping-rates.ts +119 -0
  177. package/functions/commerce/shippings/shipping-zones.ts +119 -0
  178. package/functions/commerce/taxes.ts +119 -0
  179. package/functions/commerce/waitlist/products.ts +123 -0
  180. package/functions/commerce/waitlist/restaurants.ts +123 -0
  181. package/functions/craft.ts +107 -0
  182. package/functions/dashboard.ts +153 -0
  183. package/functions/inbox.ts +95 -0
  184. package/functions/jobs.ts +86 -0
  185. package/functions/monitoring/errors.ts +295 -0
  186. package/functions/queue.ts +111 -0
  187. package/functions/realtime/websockets.ts +96 -0
  188. package/functions/realtime.ts +52 -0
  189. package/functions/releases.ts +49 -0
  190. package/functions/search.ts +126 -0
  191. package/functions/toasts.ts +95 -0
  192. package/functions/uploads.ts +216 -0
  193. package/ide/.gitignore +4 -0
  194. package/ide/cursor/rules/auto-imports.mdc +574 -0
  195. package/ide/cursor/rules/code-style.mdc +12 -0
  196. package/ide/cursor/rules/documentation.mdc +9 -0
  197. package/ide/cursor/rules/error-handling-validation.mdc +11 -0
  198. package/ide/cursor/rules/key-conventions.mdc +11 -0
  199. package/ide/cursor/rules/project-structure.mdc +169 -0
  200. package/ide/cursor/rules/readme.mdc +318 -0
  201. package/ide/cursor/rules/syntax-formatting.mdc +9 -0
  202. package/ide/cursor/rules/testing.mdc +10 -0
  203. package/ide/cursor/rules/typescript.mdc +9 -0
  204. package/ide/cursor/rules/ui-styling.mdc +0 -0
  205. package/ide/dictionary.txt +397 -0
  206. package/ide/jetbrains/.fleet/settings.json +4 -0
  207. package/ide/jetbrains/.idea/.gitignore +5 -0
  208. package/ide/jetbrains/.idea/.name +1 -0
  209. package/ide/jetbrains/.idea/inspectionProfiles/Project_Default.xml +6 -0
  210. package/ide/jetbrains/.idea/jsLinters/eslint.xml +7 -0
  211. package/ide/jetbrains/.idea/modules.xml +8 -0
  212. package/ide/jetbrains/.idea/stacks.iml +22 -0
  213. package/ide/jetbrains/.idea/vcs.xml +6 -0
  214. package/ide/jetbrains/.idea/webResources.xml +14 -0
  215. package/ide/jetbrains/IntelliJ IDEA Global Settings +0 -0
  216. package/ide/jetbrains/installed.txt +4 -0
  217. package/ide/jetbrains/options/github-copilot.xml +5 -0
  218. package/ide/jetbrains/options/nodejs.xml +7 -0
  219. package/ide/jetbrains/options/templates.xml +124 -0
  220. package/ide/jetbrains/templates/JavaScript.xml +6 -0
  221. package/ide/jetbrains/templates/Stacks.xml +8 -0
  222. package/ide/vscode/.vscode/README.md +23 -0
  223. package/ide/vscode/.vscode/extensions.json +5 -0
  224. package/ide/vscode/.vscode/settings.json +176 -0
  225. package/ide/vscode/.vscode/stacks.code-snippets +181 -0
  226. package/ide/vscode/LICENSE.md +21 -0
  227. package/ide/vscode/README.md +36 -0
  228. package/ide/vscode/logo.png +0 -0
  229. package/ide/vscode/package.json +79 -0
  230. package/ide/zed/.zed/settings.json +139 -0
  231. package/lang/README.md +28 -0
  232. package/lang/de.yml +14 -0
  233. package/lang/en.yml +15 -0
  234. package/package.json +19 -3
  235. package/project/bootstrap +161 -0
  236. package/project/buddy +175 -0
  237. package/project/storage/framework/tsconfig.app.json +50 -0
  238. package/project/storage/framework/tsconfig.base.json +58 -0
  239. package/routes/core.ts +78 -0
  240. package/routes/dashboard-api.ts +233 -0
  241. package/routes/dashboard.ts +739 -0
  242. package/routes/email.ts +129 -0
  243. package/stores/[name].stx +16 -0
  244. package/stores/git.ts +71 -0
  245. package/stores/payment.ts +474 -0
  246. package/stores/queue.ts +43 -0
  247. package/stores/user.ts +29 -0
  248. package/stx-components-plugin.ts +25 -0
  249. package/styles/design-tokens.css +597 -0
  250. package/types/dashboard.ts +70 -0
  251. package/types/defaults.ts +438 -0
  252. package/vcs/github/CODE_OF_CONDUCT.md +83 -0
  253. package/vcs/github/CONTRIBUTING.md +187 -0
  254. package/vcs/github/EXPLANATIONS.md +41 -0
  255. package/vcs/github/FUNDING.yml +1 -0
  256. package/vcs/github/ISSUE_TEMPLATE/bug_report.yml +49 -0
  257. package/vcs/github/ISSUE_TEMPLATE/config.yml +10 -0
  258. package/vcs/github/ISSUE_TEMPLATE/feature_request.yml +44 -0
  259. package/vcs/github/SECURITY.md +70 -0
  260. package/vcs/github/renovate.json +5 -0
  261. package/vcs/github/stale.yml +14 -0
  262. package/vcs/github/workflows/README.md +16 -0
  263. package/vcs/github/workflows/ci.yml +114 -0
  264. package/vcs/github/workflows/export-size.yml +25 -0
  265. package/vcs/github/workflows/labeler.yml +13 -0
  266. package/vcs/github/workflows/release.yml +219 -0
  267. package/views/[...all].stx +8 -0
  268. package/views/about.md +3 -0
  269. package/views/auth/login.stx +1 -0
  270. package/views/auth/signup.stx +85 -0
  271. package/views/dashboard/.discovered-models.json +542 -0
  272. package/views/dashboard/AUDIT.md +904 -0
  273. package/views/dashboard/[...all].stx +89 -0
  274. package/views/dashboard/access-tokens/index.stx +177 -0
  275. package/views/dashboard/actions/index.stx +129 -0
  276. package/views/dashboard/analytics/blog/index.stx +356 -0
  277. package/views/dashboard/analytics/browsers/index.stx +263 -0
  278. package/views/dashboard/analytics/commerce/sales/index.stx +329 -0
  279. package/views/dashboard/analytics/commerce/web/index.stx +379 -0
  280. package/views/dashboard/analytics/countries/index.stx +289 -0
  281. package/views/dashboard/analytics/devices/index.stx +305 -0
  282. package/views/dashboard/analytics/events/index.stx +536 -0
  283. package/views/dashboard/analytics/index.stx +88 -0
  284. package/views/dashboard/analytics/marketing/index.stx +315 -0
  285. package/views/dashboard/analytics/pages/index.stx +271 -0
  286. package/views/dashboard/analytics/referrers/index.stx +319 -0
  287. package/views/dashboard/analytics/web/index.stx +356 -0
  288. package/views/dashboard/buddy/index.stx +198 -0
  289. package/views/dashboard/ci/index.stx +462 -0
  290. package/views/dashboard/cloud/index.stx +452 -0
  291. package/views/dashboard/commands/index.stx +295 -0
  292. package/views/dashboard/commerce/categories/index.stx +406 -0
  293. package/views/dashboard/commerce/coupons/index.stx +485 -0
  294. package/views/dashboard/commerce/customers/index.stx +410 -0
  295. package/views/dashboard/commerce/dashboard/index.stx +287 -0
  296. package/views/dashboard/commerce/delivery/delivery-routes.stx +305 -0
  297. package/views/dashboard/commerce/delivery/digital-delivery.stx +332 -0
  298. package/views/dashboard/commerce/delivery/drivers.stx +397 -0
  299. package/views/dashboard/commerce/delivery/index.stx +18 -0
  300. package/views/dashboard/commerce/delivery/license-keys.stx +380 -0
  301. package/views/dashboard/commerce/delivery/shipping-methods.stx +346 -0
  302. package/views/dashboard/commerce/delivery/shipping-rates.stx +338 -0
  303. package/views/dashboard/commerce/delivery/shipping-zones.stx +302 -0
  304. package/views/dashboard/commerce/delivery/tabs.ts +25 -0
  305. package/views/dashboard/commerce/gift-cards/index.stx +561 -0
  306. package/views/dashboard/commerce/manufacturers/index.stx +308 -0
  307. package/views/dashboard/commerce/orders/index.stx +247 -0
  308. package/views/dashboard/commerce/payments/index.stx +535 -0
  309. package/views/dashboard/commerce/pos/index.stx +653 -0
  310. package/views/dashboard/commerce/printers/devices/index.stx +273 -0
  311. package/views/dashboard/commerce/printers/receipts/index.stx +308 -0
  312. package/views/dashboard/commerce/products/detail.stx +563 -0
  313. package/views/dashboard/commerce/products/index.stx +370 -0
  314. package/views/dashboard/commerce/reviews/index.stx +656 -0
  315. package/views/dashboard/commerce/reviews/index.ts +0 -0
  316. package/views/dashboard/commerce/taxes/index.stx +377 -0
  317. package/views/dashboard/commerce/units/index.stx +317 -0
  318. package/views/dashboard/commerce/variants/index.stx +319 -0
  319. package/views/dashboard/commerce/waitlist/products.stx +942 -0
  320. package/views/dashboard/commerce/waitlist/restaurant.stx +1024 -0
  321. package/views/dashboard/components/index.stx +330 -0
  322. package/views/dashboard/composables/index.ts +19 -0
  323. package/views/dashboard/composables/useChart.ts +77 -0
  324. package/views/dashboard/composables/useNavigation.ts +99 -0
  325. package/views/dashboard/composables/useRole.ts +58 -0
  326. package/views/dashboard/composables/useTheme.ts +74 -0
  327. package/views/dashboard/content/authors/index.stx +171 -0
  328. package/views/dashboard/content/blog/index.stx +493 -0
  329. package/views/dashboard/content/categories/index.stx +169 -0
  330. package/views/dashboard/content/comments/index.stx +189 -0
  331. package/views/dashboard/content/dashboard.stx +383 -0
  332. package/views/dashboard/content/files/index.stx +706 -0
  333. package/views/dashboard/content/pages/index.stx +174 -0
  334. package/views/dashboard/content/posts/index.stx +269 -0
  335. package/views/dashboard/content/seo/index.stx +240 -0
  336. package/views/dashboard/content/tags/index.stx +167 -0
  337. package/views/dashboard/data/activity/index.stx +261 -0
  338. package/views/dashboard/data/dashboard/index.stx +116 -0
  339. package/views/dashboard/data/subscribers.stx +270 -0
  340. package/views/dashboard/data/teams.stx +275 -0
  341. package/views/dashboard/data/users.stx +279 -0
  342. package/views/dashboard/dependencies/index.stx +178 -0
  343. package/views/dashboard/deployments/[id].stx +234 -0
  344. package/views/dashboard/deployments/index.stx +9 -0
  345. package/views/dashboard/dns/index.stx +163 -0
  346. package/views/dashboard/environment/index.stx +283 -0
  347. package/views/dashboard/errors/index.stx +274 -0
  348. package/views/dashboard/forgot-password.stx +57 -0
  349. package/views/dashboard/functions/index.stx +159 -0
  350. package/views/dashboard/health/index.stx +248 -0
  351. package/views/dashboard/inbox/activity.stx +350 -0
  352. package/views/dashboard/inbox/index.stx +452 -0
  353. package/views/dashboard/inbox/settings.stx +290 -0
  354. package/views/dashboard/index.stx +252 -0
  355. package/views/dashboard/insights/index.stx +529 -0
  356. package/views/dashboard/jobs/[id].stx +430 -0
  357. package/views/dashboard/jobs/history.stx +222 -0
  358. package/views/dashboard/jobs/index.stx +214 -0
  359. package/views/dashboard/kanban/[id].stx +899 -0
  360. package/views/dashboard/kanban/index.stx +260 -0
  361. package/views/dashboard/layouts/default.stx +565 -0
  362. package/views/dashboard/layouts/guest.stx +10 -0
  363. package/views/dashboard/login.stx +48 -0
  364. package/views/dashboard/logs/index.stx +540 -0
  365. package/views/dashboard/mailboxes/index.stx +149 -0
  366. package/views/dashboard/management/permissions/index.stx +490 -0
  367. package/views/dashboard/marketing/campaigns/index.stx +604 -0
  368. package/views/dashboard/marketing/lists/index.stx +514 -0
  369. package/views/dashboard/marketing/reviews/index.stx +475 -0
  370. package/views/dashboard/marketing/social-posts/index.stx +560 -0
  371. package/views/dashboard/models/[model].stx +195 -0
  372. package/views/dashboard/models/index.stx +159 -0
  373. package/views/dashboard/monitoring/errors/index.stx +415 -0
  374. package/views/dashboard/notifications/dashboard.stx +383 -0
  375. package/views/dashboard/notifications/email.stx +336 -0
  376. package/views/dashboard/notifications/history.stx +373 -0
  377. package/views/dashboard/notifications/sms.stx +332 -0
  378. package/views/dashboard/packages/index.stx +195 -0
  379. package/views/dashboard/queries/[id].stx +381 -0
  380. package/views/dashboard/queries/history.stx +227 -0
  381. package/views/dashboard/queries/index.stx +335 -0
  382. package/views/dashboard/queries/slow.stx +318 -0
  383. package/views/dashboard/queue/index.stx +427 -0
  384. package/views/dashboard/realtime/index.stx +429 -0
  385. package/views/dashboard/register.stx +46 -0
  386. package/views/dashboard/releases/index.stx +389 -0
  387. package/views/dashboard/requests/index.stx +462 -0
  388. package/views/dashboard/serverless/index.stx +475 -0
  389. package/views/dashboard/servers/[id].stx +299 -0
  390. package/views/dashboard/servers/index.stx +483 -0
  391. package/views/dashboard/settings/billing.stx +50 -0
  392. package/views/dashboard/settings/index.stx +256 -0
  393. package/views/dashboard/settings/mail.stx +252 -0
  394. package/views/dashboard/stores/auth.ts +123 -0
  395. package/views/dashboard/stores/ci.ts +342 -0
  396. package/views/dashboard/stores/index.ts +129 -0
  397. package/views/dashboard/stores/kanban.ts +723 -0
  398. package/views/dashboard/stores/rbac.ts +350 -0
  399. package/views/dashboard/stx.config.ts +34 -0
  400. package/views/dashboard/teams/[id].stx +170 -0
  401. package/views/forum/category.stx +92 -0
  402. package/views/forum/index.stx +209 -0
  403. package/views/forum/new-topic.stx +113 -0
  404. package/views/forum/profile.stx +1 -0
  405. package/views/forum/topic.stx +143 -0
  406. package/views/hello-world/[name].stx +47 -0
  407. package/views/index.stx +21 -0
  408. package/views/system-tray/index.stx +147 -0
@@ -0,0 +1,535 @@
1
+ @extends('layouts/default')
2
+
3
+ @section('content')
4
+ @title('Dashboard - Commerce Payments')
5
+ <PageLayout>
6
+ <div class="sm:flex sm:items-center sm:justify-between">
7
+ <PageHeader title="Payments" description="Manage payment transactions for your store" />
8
+ <div class="mt-4 sm:mt-0">
9
+ <button
10
+ type="button"
11
+ class="inline-flex items-center px-3 py-2 font-semibold text-sm text-white bg-blue-600 hover:bg-blue-500 rounded-md focus-visible:outline focus-visible:outline-2 focus-visible:outline-blue-600 focus-visible:outline-offset-2 shadow-sm"
12
+ >
13
+ <div class="mr-1 h-5 w-5 i-hugeicons-download-04"></div>
14
+ Export transactions
15
+ </button>
16
+ </div>
17
+ </div>
18
+
19
+ <!-- Time range selector -->
20
+ <div class="flex items-center justify-between mt-4">
21
+ <p class="text-gray-500 text-sm dark:text-neutral-400">
22
+ Overview of your payment transactions
23
+ </p>
24
+ <div class="relative">
25
+ <select x-model="timeRange" class="block pl-3 pr-10 py-1.5 w-full text-gray-900 sm:leading-6 sm:text-sm dark:text-white dark:bg-neutral-800 border-0 ring-1 ring-gray-300 ring-inset rounded-md dark:ring-neutral-700 focus:ring-2 focus:ring-blue-600">
26
+ @foreach(timeRanges as range)
27
+ <option value="{{ range }}">{{ range }}</option>
28
+ @endforeach
29
+ </select>
30
+ </div>
31
+ </div>
32
+
33
+ <!-- Stats -->
34
+ <dl class="grid gap-5 grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 mt-5">
35
+ <div class="overflow-hidden px-4 py-5 sm:p-6 bg-white dark:bg-neutral-800 rounded-lg shadow">
36
+ <dt class="font-medium text-gray-500 text-sm truncate dark:text-neutral-300">Total Transactions</dt>
37
+ <dd class="mt-1 font-semibold text-3xl text-gray-900 tracking-tight dark:text-white">{{ paymentStats().totalTransactions }}</dd>
38
+ <dd class="flex items-center mt-2 text-green-600 text-sm dark:text-green-400">
39
+ <div class="mr-1 h-4 w-4 i-hugeicons-analytics-up"></div>
40
+ <span>8.2% increase</span>
41
+ </dd>
42
+ </div>
43
+
44
+ <div class="overflow-hidden px-4 py-5 sm:p-6 bg-white dark:bg-neutral-800 rounded-lg shadow">
45
+ <dt class="font-medium text-gray-500 text-sm truncate dark:text-neutral-300">Success Rate</dt>
46
+ <dd class="mt-1 font-semibold text-3xl text-gray-900 tracking-tight dark:text-white">{{ paymentStats().successRate }}%</dd>
47
+ <dd class="flex items-center mt-2 text-green-600 text-sm dark:text-green-400">
48
+ <div class="mr-1 h-4 w-4 i-hugeicons-analytics-up"></div>
49
+ <span>1.2% increase</span>
50
+ </dd>
51
+ </div>
52
+
53
+ <div class="overflow-hidden px-4 py-5 sm:p-6 bg-white dark:bg-neutral-800 rounded-lg shadow">
54
+ <dt class="font-medium text-gray-500 text-sm truncate dark:text-neutral-300">Total Revenue</dt>
55
+ <dd class="mt-1 font-semibold text-3xl text-gray-900 tracking-tight dark:text-white">${{ Number.parseFloat(paymentStats().totalAmount).toLocaleString() }}</dd>
56
+ <dd class="flex items-center mt-2 text-green-600 text-sm dark:text-green-400">
57
+ <div class="mr-1 h-4 w-4 i-hugeicons-analytics-up"></div>
58
+ <span>12.5% increase</span>
59
+ </dd>
60
+ </div>
61
+
62
+ <div class="overflow-hidden px-4 py-5 sm:p-6 bg-white dark:bg-neutral-800 rounded-lg shadow">
63
+ <dt class="font-medium text-gray-500 text-sm truncate dark:text-neutral-300">Avg. Transaction</dt>
64
+ <dd class="mt-1 font-semibold text-3xl text-gray-900 tracking-tight dark:text-white">${{ paymentStats().avgTransactionValue }}</dd>
65
+ <dd class="flex items-center mt-2 text-green-600 text-sm dark:text-green-400">
66
+ <div class="mr-1 h-4 w-4 i-hugeicons-analytics-up"></div>
67
+ <span>3.7% increase</span>
68
+ </dd>
69
+ </div>
70
+ </dl>
71
+
72
+ <!-- Charts -->
73
+ <div class="grid gap-5 grid-cols-1 lg:grid-cols-2 mt-8">
74
+ <div class="overflow-hidden bg-white dark:bg-neutral-800 rounded-lg shadow">
75
+ <div class="p-6">
76
+ <h3 class="font-semibold leading-6 text-base text-gray-900 dark:text-white">Transaction Count</h3>
77
+ <div class="mt-2 h-80">
78
+ <canvas id="chart_1"></canvas>
79
+ </div>
80
+ </div>
81
+ </div>
82
+
83
+ <div class="overflow-hidden bg-white dark:bg-neutral-800 rounded-lg shadow">
84
+ <div class="p-6">
85
+ <h3 class="font-semibold leading-6 text-base text-gray-900 dark:text-white">Revenue</h3>
86
+ <div class="mt-2 h-80">
87
+ <canvas id="chart_2"></canvas>
88
+ </div>
89
+ </div>
90
+ </div>
91
+ </div>
92
+
93
+ <!-- Filters -->
94
+ <div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between mt-8">
95
+ <div class="relative max-w-sm">
96
+ <div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
97
+ <div class="h-5 w-5 text-gray-400 i-hugeicons-search-01"></div>
98
+ </div>
99
+ <input
100
+ x-model="searchQuery"
101
+ type="text"
102
+ class="block pl-10 pr-3 py-1.5 w-full text-gray-900 sm:leading-6 sm:text-sm dark:text-white placeholder:text-gray-400 dark:placeholder:text-neutral-500 dark:bg-neutral-800 border-0 ring-1 ring-gray-300 ring-inset rounded-md dark:ring-neutral-700 focus:ring-2 focus:ring-blue-600 focus:ring-inset"
103
+ placeholder="Search transactions..."
104
+ />
105
+ </div>
106
+
107
+ <div class="flex flex-col gap-4 sm:flex-row">
108
+ <select
109
+ x-model="statusFilter"
110
+ class="block pl-3 pr-10 py-1.5 w-full text-gray-900 sm:leading-6 sm:text-sm dark:text-white dark:bg-neutral-800 border-0 ring-1 ring-gray-300 ring-inset rounded-md dark:ring-neutral-700 focus:ring-2 focus:ring-blue-600 focus:ring-inset"
111
+ >
112
+ @foreach(statuses as status)
113
+ <option value="{{ status }}">{{ status === 'all' ? 'All Statuses' : status }}</option>
114
+ @endforeach
115
+ </select>
116
+
117
+ <select
118
+ x-model="methodFilter"
119
+ class="block pl-3 pr-10 py-1.5 w-full text-gray-900 sm:leading-6 sm:text-sm dark:text-white dark:bg-neutral-800 border-0 ring-1 ring-gray-300 ring-inset rounded-md dark:ring-neutral-700 focus:ring-2 focus:ring-blue-600 focus:ring-inset"
120
+ >
121
+ @foreach(methods as method)
122
+ <option value="{{ method }}">{{ method === 'all' ? 'All Payment Methods' : method }}</option>
123
+ @endforeach
124
+ </select>
125
+ </div>
126
+ </div>
127
+
128
+ <!-- Transactions table -->
129
+ <div class="flow-root mt-6">
130
+ <div class="sm:flex sm:items-center sm:justify-between mb-4">
131
+ <h3 class="font-semibold leading-6 text-base text-gray-900 dark:text-white">All Transactions</h3>
132
+ <p class="mt-1 text-gray-500 text-sm dark:text-neutral-400">
133
+ A list of all payment transactions including order ID, customer, amount, and status.
134
+ </p>
135
+ </div>
136
+ <div class="overflow-x-auto -mx-4 -my-2 sm:-mx-6 lg:-mx-8">
137
+ <div class="inline-block py-2 sm:px-6 lg:px-8 min-w-full align-middle">
138
+ <div class="overflow-hidden ring-1 ring-black ring-opacity-5 sm:rounded-lg shadow">
139
+ <table class="min-w-full divide-gray-300 divide-y dark:divide-neutral-700">
140
+ <thead class="bg-gray-50 dark:bg-neutral-700">
141
+ <tr>
142
+ <th scope="col" class="pl-4 pr-3 py-3.5 sm:pl-6 font-semibold text-gray-900 text-left text-sm dark:text-neutral-200">
143
+ <button @click="toggleSort('orderId')" class="inline-flex items-center group">
144
+ Order ID
145
+ <span class="group-focus:visible group-hover:visible flex-none ml-2 text-gray-400 rounded">
146
+ <div class="h-4 w-4 {{ sortBy() === 'orderId' ? (sortOrder() === 'asc' ? 'i-hugeicons-arrow-up-02' : 'i-hugeicons-arrow-down-02') : 'i-hugeicons-arrows-up-down' }}"></div>
147
+ </span>
148
+ </button>
149
+ </th>
150
+ <th scope="col" class="px-3 py-3.5 font-semibold text-gray-900 text-left text-sm dark:text-neutral-200">
151
+ <button @click="toggleSort('customer')" class="inline-flex items-center group">
152
+ Customer
153
+ <span class="group-focus:visible group-hover:visible flex-none ml-2 text-gray-400 rounded">
154
+ <div class="h-4 w-4 {{ sortBy() === 'customer' ? (sortOrder() === 'asc' ? 'i-hugeicons-arrow-up-02' : 'i-hugeicons-arrow-down-02') : 'i-hugeicons-arrows-up-down' }}"></div>
155
+ </span>
156
+ </button>
157
+ </th>
158
+ <th scope="col" class="px-3 py-3.5 font-semibold text-gray-900 text-left text-sm dark:text-neutral-200">
159
+ <button @click="toggleSort('amount')" class="inline-flex items-center group">
160
+ Amount
161
+ <span class="group-focus:visible group-hover:visible flex-none ml-2 text-gray-400 rounded">
162
+ <div class="h-4 w-4 {{ sortBy() === 'amount' ? (sortOrder() === 'asc' ? 'i-hugeicons-arrow-up-02' : 'i-hugeicons-arrow-down-02') : 'i-hugeicons-arrows-up-down' }}"></div>
163
+ </span>
164
+ </button>
165
+ </th>
166
+ <th scope="col" class="px-3 py-3.5 font-semibold text-gray-900 text-left text-sm dark:text-neutral-200">Method</th>
167
+ <th scope="col" class="px-3 py-3.5 font-semibold text-gray-900 text-left text-sm dark:text-neutral-200">Status</th>
168
+ <th scope="col" class="px-3 py-3.5 font-semibold text-gray-900 text-left text-sm dark:text-neutral-200">
169
+ <button @click="toggleSort('date')" class="inline-flex items-center group">
170
+ Date
171
+ <span class="group-focus:visible group-hover:visible flex-none ml-2 text-gray-400 rounded">
172
+ <div class="h-4 w-4 {{ sortBy() === 'date' ? (sortOrder() === 'asc' ? 'i-hugeicons-arrow-up-02' : 'i-hugeicons-arrow-down-02') : 'i-hugeicons-arrows-up-down' }}"></div>
173
+ </span>
174
+ </button>
175
+ </th>
176
+ <th scope="col" class="relative pl-3 pr-4 py-3.5 sm:pr-6">
177
+ <span class="sr-only">Actions</span>
178
+ </th>
179
+ </tr>
180
+ </thead>
181
+ <tbody class="bg-white dark:bg-neutral-800 divide-gray-200 divide-y dark:divide-neutral-700">
182
+ <template :for="transaction in paginatedTransactions">
183
+ <tr>
184
+ <td class="pl-4 pr-3 py-4 sm:pl-6 font-medium text-gray-900 text-sm whitespace-nowrap dark:text-white">
185
+ {{ transaction.orderId }}
186
+ </td>
187
+ <td class="px-3 py-4 text-gray-500 text-sm dark:text-neutral-300">
188
+ <div>{{ transaction.customer }}</div>
189
+ <div class="text-gray-400 text-xs">{{ transaction.email }}</div>
190
+ </td>
191
+ <td class="px-3 py-4 font-medium text-gray-900 text-sm whitespace-nowrap dark:text-white">
192
+ ${{ transaction.amount.toFixed(2) }}
193
+ </td>
194
+ <td class="px-3 py-4 text-gray-500 text-sm whitespace-nowrap dark:text-neutral-300">
195
+ <div class="flex items-center">
196
+ <div class="{{ getPaymentMethodIcon(transaction.method) }} h-5 w-5 mr-1.5 text-gray-500 dark:text-neutral-400"></div>
197
+ <span>{{ transaction.method }}</span>
198
+ @if(transaction.last4)
199
+ <span class="ml-1 text-gray-400 text-xs">
200
+ ({{ transaction.cardType }} •••• {{ transaction.last4 }})
201
+ </span>
202
+ @endif
203
+ </div>
204
+ </td>
205
+ <td class="px-3 py-4 text-sm whitespace-nowrap">
206
+ <span class="inline-flex items-center px-2 py-1 font-medium text-xs rounded-md {{ getStatusClass(transaction.status) }}">
207
+ {{ transaction.status }}
208
+ </span>
209
+ </td>
210
+ <td class="px-3 py-4 text-gray-500 text-sm whitespace-nowrap dark:text-neutral-300">
211
+ {{ transaction.date }}
212
+ </td>
213
+ <td class="relative pl-3 pr-4 py-4 sm:pr-6 font-medium text-right text-sm whitespace-nowrap">
214
+ <div class="flex items-center justify-end space-x-2">
215
+ <button type="button" class="text-blue-600 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300">
216
+ <div class="h-5 w-5 i-hugeicons-view"></div>
217
+ </button>
218
+ <button type="button" class="text-blue-600 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300">
219
+ <div class="h-5 w-5 i-hugeicons-receipt-dollar"></div>
220
+ </button>
221
+ </div>
222
+ </td>
223
+ </tr>
224
+ </template>
225
+ @if(paginatedTransactions().length === 0)
226
+ <tr>
227
+ <td colspan="7" class="px-6 py-4 text-center text-gray-500 text-sm dark:text-neutral-400">
228
+ No transactions found matching your criteria
229
+ </td>
230
+ </tr>
231
+ @endif
232
+ </tbody>
233
+ </table>
234
+ </div>
235
+ </div>
236
+ </div>
237
+ </div>
238
+
239
+ <!-- Pagination -->
240
+ <div :show="totalPages() > 1" class="flex items-center justify-between mt-6">
241
+ <div class="flex sm:hidden flex-1 justify-between">
242
+ <button
243
+ @click="changePage(Math.max(1, currentPage() - 1))"
244
+ :disabled="currentPage() === 1"
245
+ class="{{ currentPage() === 1 ? 'cursor-not-allowed opacity-50' : '' }} relative inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 dark:border-neutral-600 dark:bg-neutral-800 dark:text-neutral-200 dark:hover:bg-neutral-700"
246
+ >
247
+ Previous
248
+ </button>
249
+ <button
250
+ @click="changePage(Math.min(totalPages(), currentPage() + 1))"
251
+ :disabled="currentPage() === totalPages()"
252
+ class="{{ currentPage() === totalPages() ? 'cursor-not-allowed opacity-50' : '' }} relative ml-3 inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 dark:border-neutral-600 dark:bg-neutral-800 dark:text-neutral-200 dark:hover:bg-neutral-700"
253
+ >
254
+ Next
255
+ </button>
256
+ </div>
257
+ <div class="hidden sm:flex sm:flex-1 sm:items-center sm:justify-between">
258
+ <div>
259
+ <p class="text-gray-700 text-sm dark:text-neutral-300">
260
+ Showing <span class="font-medium">{{ ((currentPage() - 1) * itemsPerPage()) + 1 }}</span> to <span class="font-medium">{{ Math.min(currentPage() * itemsPerPage(), filteredTransactions().length) }}</span> of <span class="font-medium">{{ filteredTransactions().length }}</span> results
261
+ </p>
262
+ </div>
263
+ <div>
264
+ <nav class="inline-flex -space-x-px rounded-md shadow-sm isolate" aria-label="Pagination">
265
+ <button
266
+ @click="changePage(Math.max(1, currentPage() - 1))"
267
+ :disabled="currentPage() === 1"
268
+ class="inline-flex relative focus:z-20 items-center px-2 py-2 text-gray-400 hover:bg-gray-50 dark:hover:bg-neutral-700 ring-1 ring-gray-300 ring-inset rounded-l-md dark:ring-neutral-600 focus:outline-offset-0 {{ currentPage() === 1 ? 'cursor-not-allowed opacity-50' : '' }}"
269
+ >
270
+ <span class="sr-only">Previous</span>
271
+ <div class="h-5 w-5 i-hugeicons-arrow-left-01"></div>
272
+ </button>
273
+
274
+ <template :for="page in visiblePages">
275
+ @if(page === '...')
276
+ <span class="inline-flex relative items-center px-4 py-2 font-semibold text-gray-700 text-sm dark:text-neutral-400 ring-1 ring-gray-300 ring-inset dark:ring-neutral-600 focus:outline-offset-0">
277
+ ...
278
+ </span>
279
+ @else
280
+ <button
281
+ @click="changePage(page)"
282
+ class="{{ page === currentPage() ? 'relative z-10 inline-flex items-center bg-blue-600 px-4 py-2 text-sm font-semibold text-white focus:z-20 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600' : 'relative inline-flex items-center px-4 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-20 focus:outline-offset-0 dark:text-neutral-200 dark:ring-neutral-600 dark:hover:bg-neutral-700' }}"
283
+ >
284
+ {{ page }}
285
+ </button>
286
+ @endif
287
+ </template>
288
+
289
+ <button
290
+ @click="changePage(Math.min(totalPages(), currentPage() + 1))"
291
+ :disabled="currentPage() === totalPages()"
292
+ class="inline-flex relative focus:z-20 items-center px-2 py-2 text-gray-400 hover:bg-gray-50 dark:hover:bg-neutral-700 ring-1 ring-gray-300 ring-inset rounded-r-md dark:ring-neutral-600 focus:outline-offset-0 {{ currentPage() === totalPages() ? 'cursor-not-allowed opacity-50' : '' }}"
293
+ >
294
+ <span class="sr-only">Next</span>
295
+ <div class="h-5 w-5 i-hugeicons-arrow-right-01"></div>
296
+ </button>
297
+ </nav>
298
+ </div>
299
+ </div>
300
+ </div>
301
+ </PageLayout>
302
+ <script client>
303
+ // Filter options — moved out of the former `<script server>` block
304
+ // (stacksjs/stacks#1838).
305
+ const statuses = ['all', 'Completed', 'Pending', 'Failed', 'Refunded'] as const
306
+ const methods = ['all', 'Credit Card', 'PayPal', 'Apple Pay', 'Google Pay', 'Bank Transfer'] as const
307
+ const timeRanges = ['Today', 'Last 7 days', 'Last 30 days', 'Last 90 days', 'Last year', 'All time'] as const
308
+
309
+ interface PaymentTransaction {
310
+ id: number
311
+ orderId: string
312
+ customer: string
313
+ email: string
314
+ amount: number
315
+ method: string
316
+ status: string
317
+ date: string
318
+ cardType?: string
319
+ last4?: string
320
+ }
321
+
322
+ const initialTransactions: PaymentTransaction[] = [
323
+ { id: 1, orderId: 'ORD-12345', customer: 'John Smith', email: 'john.smith@example.com', amount: 129.99, method: 'Credit Card', status: 'Completed', date: '2023-11-15', cardType: 'Visa', last4: '4242' },
324
+ { id: 2, orderId: 'ORD-12346', customer: 'Emily Davis', email: 'emily.davis@example.com', amount: 79.50, method: 'PayPal', status: 'Completed', date: '2023-11-16' },
325
+ { id: 3, orderId: 'ORD-12347', customer: 'Michael Johnson', email: 'mjohnson@example.com', amount: 249.99, method: 'Credit Card', status: 'Failed', date: '2023-11-17', cardType: 'Mastercard', last4: '5678' },
326
+ { id: 4, orderId: 'ORD-12348', customer: 'Sarah Williams', email: 'swilliams@example.com', amount: 59.99, method: 'Credit Card', status: 'Pending', date: '2023-11-18', cardType: 'Amex', last4: '9876' },
327
+ { id: 5, orderId: 'ORD-12349', customer: 'David Brown', email: 'dbrown@example.com', amount: 149.95, method: 'Apple Pay', status: 'Completed', date: '2023-11-19' },
328
+ ]
329
+
330
+ const transactions = state(initialTransactions)
331
+ const timeRange = state<string>('Last 30 days')
332
+ const searchQuery = state('')
333
+ const sortBy = state<'orderId' | 'customer' | 'amount' | 'date'>('date')
334
+ const sortOrder = state<'asc' | 'desc'>('desc')
335
+ const statusFilter = state<string>('all')
336
+ const methodFilter = state<string>('all')
337
+ const currentPage = state(1)
338
+ const itemsPerPage = state(10)
339
+
340
+ const chartOptions = {
341
+ responsive: true,
342
+ maintainAspectRatio: false,
343
+ plugins: { legend: { display: false } },
344
+ scales: {
345
+ y: { beginAtZero: true, grid: { display: true, color: 'rgba(0, 0, 0, 0.05)' } },
346
+ x: { grid: { display: false } },
347
+ },
348
+ }
349
+
350
+ function monthlyChartData(): { transactionCountChartData: unknown, revenueChartData: unknown } {
351
+ const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
352
+ const transactionCountData = [45, 52, 49, 60, 72, 68, 80, 91, 87, 94, 102, 110]
353
+ const revenueData = [5500, 6200, 5900, 7500, 8800, 8200, 9600, 11000, 10500, 11800, 12500, 13800]
354
+
355
+ return {
356
+ transactionCountChartData: {
357
+ labels: months,
358
+ datasets: [{
359
+ label: 'Transaction Count',
360
+ backgroundColor: 'rgba(59, 130, 246, 0.2)',
361
+ borderColor: 'rgba(59, 130, 246, 1)',
362
+ borderWidth: 2,
363
+ pointBackgroundColor: 'rgba(59, 130, 246, 1)',
364
+ pointBorderColor: '#fff',
365
+ pointHoverBackgroundColor: '#fff',
366
+ pointHoverBorderColor: 'rgba(59, 130, 246, 1)',
367
+ fill: true,
368
+ tension: 0.4,
369
+ data: transactionCountData,
370
+ }],
371
+ },
372
+ revenueChartData: {
373
+ labels: months,
374
+ datasets: [{
375
+ label: 'Revenue',
376
+ backgroundColor: 'rgba(16, 185, 129, 0.8)',
377
+ borderColor: 'rgba(16, 185, 129, 1)',
378
+ borderWidth: 1,
379
+ borderRadius: 4,
380
+ data: revenueData,
381
+ }],
382
+ },
383
+ }
384
+ }
385
+
386
+ function paymentStats(): { totalTransactions: number, completedTransactions: number, pendingTransactions: number, failedTransactions: number, totalAmount: string, avgTransactionValue: string, successRate: string, mostPopularMethod: string } {
387
+ const list = transactions()
388
+ const completedTransactions = list.filter(t => t.status === 'Completed').length
389
+ const pendingTransactions = list.filter(t => t.status === 'Pending').length
390
+ const failedTransactions = list.filter(t => t.status === 'Failed').length
391
+
392
+ const totalAmount = list.reduce(
393
+ (sum, t) => t.status === 'Completed' ? sum + t.amount : sum,
394
+ 0,
395
+ )
396
+ const avgTransactionValue = completedTransactions > 0
397
+ ? (totalAmount / completedTransactions).toFixed(2)
398
+ : '0.00'
399
+ const totalProcessed = completedTransactions + failedTransactions
400
+ const successRate = totalProcessed > 0
401
+ ? ((completedTransactions / totalProcessed) * 100).toFixed(1)
402
+ : '0.0'
403
+
404
+ const methodCounts = list.reduce<Record<string, number>>((counts, t) => {
405
+ counts[t.method] = (counts[t.method] || 0) + 1
406
+ return counts
407
+ }, {})
408
+ let mostPopularMethod = 'Credit Card'
409
+ let maxCount = 0
410
+ for (const [method, count] of Object.entries(methodCounts)) {
411
+ if (count > maxCount) { maxCount = count; mostPopularMethod = method }
412
+ }
413
+
414
+ return {
415
+ totalTransactions: list.length,
416
+ completedTransactions,
417
+ pendingTransactions,
418
+ failedTransactions,
419
+ totalAmount: totalAmount.toFixed(2),
420
+ avgTransactionValue,
421
+ successRate,
422
+ mostPopularMethod,
423
+ }
424
+ }
425
+
426
+ const filteredTransactions = derived(() => {
427
+ const q = searchQuery().toLowerCase()
428
+ const sFilter = statusFilter()
429
+ const mFilter = methodFilter()
430
+ const by = sortBy()
431
+ const dir = sortOrder()
432
+
433
+ return transactions()
434
+ .filter((t) => {
435
+ const matchesSearch
436
+ = t.orderId.toLowerCase().includes(q)
437
+ || t.customer.toLowerCase().includes(q)
438
+ || t.email.toLowerCase().includes(q)
439
+ const matchesStatus = sFilter === 'all' || t.status === sFilter
440
+ const matchesMethod = mFilter === 'all' || t.method === mFilter
441
+ return matchesSearch && matchesStatus && matchesMethod
442
+ })
443
+ .sort((a, b) => {
444
+ let cmp = 0
445
+ if (by === 'date')
446
+ cmp = new Date(a.date).getTime() - new Date(b.date).getTime()
447
+ else if (by === 'amount')
448
+ cmp = a.amount - b.amount
449
+ else if (by === 'orderId')
450
+ cmp = a.orderId.localeCompare(b.orderId)
451
+ else if (by === 'customer')
452
+ cmp = a.customer.localeCompare(b.customer)
453
+ return dir === 'asc' ? cmp : -cmp
454
+ })
455
+ })
456
+
457
+ const totalPages = derived(() => Math.ceil(filteredTransactions().length / itemsPerPage()))
458
+
459
+ const paginatedTransactions = derived(() => {
460
+ const start = (currentPage() - 1) * itemsPerPage()
461
+ return filteredTransactions().slice(start, start + itemsPerPage())
462
+ })
463
+
464
+ // Page numbers to render in the desktop pagination — first/last + a window
465
+ // of 3 around current, with '…' ellipsis where the gap is bigger than 1.
466
+ const visiblePages = derived<(number | '...')[]>(() => {
467
+ const total = totalPages()
468
+ const cur = currentPage()
469
+ const out: (number | '...')[] = []
470
+ for (let p = 1; p <= total; p++) {
471
+ if (p === cur || p === 1 || p === total || (p >= cur - 1 && p <= cur + 1)) {
472
+ out.push(p)
473
+ }
474
+ else if ((p === cur - 2 && cur > 3) || (p === cur + 2 && cur < total - 2)) {
475
+ out.push('...')
476
+ }
477
+ }
478
+ return out
479
+ })
480
+
481
+ function toggleSort(column: 'orderId' | 'customer' | 'amount' | 'date'): void {
482
+ if (sortBy() === column) {
483
+ sortOrder.update(d => d === 'asc' ? 'desc' : 'asc')
484
+ }
485
+ else {
486
+ sortBy.set(column)
487
+ sortOrder.set('desc')
488
+ }
489
+ }
490
+
491
+ function changePage(page: number): void {
492
+ currentPage.set(page)
493
+ }
494
+
495
+ function getStatusClass(status: string): string {
496
+ switch (status) {
497
+ case 'Completed':
498
+ return 'bg-green-50 text-green-700 ring-1 ring-inset ring-green-600/20 dark:bg-green-900/30 dark:text-green-400'
499
+ case 'Pending':
500
+ return 'bg-yellow-50 text-yellow-700 ring-1 ring-inset ring-yellow-600/20 dark:bg-yellow-900/30 dark:text-yellow-400'
501
+ case 'Failed':
502
+ return 'bg-red-50 text-red-700 ring-1 ring-inset ring-red-600/20 dark:bg-red-900/30 dark:text-red-400'
503
+ case 'Refunded':
504
+ return 'bg-blue-50 text-blue-700 ring-1 ring-inset ring-blue-600/20 dark:bg-blue-900/30 dark:text-blue-400'
505
+ default:
506
+ return 'bg-gray-50 text-gray-700 ring-1 ring-inset ring-gray-600/20 dark:bg-neutral-900/30 dark:text-neutral-400'
507
+ }
508
+ }
509
+
510
+ function getPaymentMethodIcon(method: string): string {
511
+ switch (method) {
512
+ case 'Credit Card': return 'i-hugeicons-credit-card'
513
+ case 'PayPal': return 'i-hugeicons-paypal'
514
+ case 'Apple Pay': return 'i-hugeicons-apple'
515
+ case 'Google Pay': return 'i-hugeicons-google'
516
+ case 'Bank Transfer': return 'i-hugeicons-bank'
517
+ default: return 'i-hugeicons-credit-card'
518
+ }
519
+ }
520
+
521
+ const { Chart, registerables } = await import('@stacksjs/charts')
522
+ Chart.register(...registerables)
523
+
524
+ const chartData = monthlyChartData()
525
+ const { destroyAll } = useCharts([
526
+ { Chart, id: 'chart_1', type: 'line', data: chartData.transactionCountChartData, options: chartOptions },
527
+ { Chart, id: 'chart_2', type: 'bar', data: chartData.revenueChartData, options: chartOptions },
528
+ ])
529
+
530
+ onDestroy(() => {
531
+ destroyAll()
532
+ })
533
+ </script>
534
+
535
+ @endsection