@stacksjs/defaults 0.70.54

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 (286) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +2 -0
  3. package/package.json +20 -0
  4. package/resources/assets/fonts/013717e9.woff +0 -0
  5. package/resources/assets/fonts/03355817.woff2 +0 -0
  6. package/resources/assets/fonts/0380de7e.woff2 +0 -0
  7. package/resources/assets/fonts/0ba5d32a.woff +0 -0
  8. package/resources/assets/fonts/0bd57ddf.woff2 +0 -0
  9. package/resources/assets/fonts/19de0a60.woff2 +0 -0
  10. package/resources/assets/fonts/20b87e84.woff +0 -0
  11. package/resources/assets/fonts/4bbc67e1.woff +0 -0
  12. package/resources/assets/fonts/576fb0d7.woff +0 -0
  13. package/resources/assets/fonts/5ea10ee5.woff2 +0 -0
  14. package/resources/assets/fonts/6413fc0a.woff +0 -0
  15. package/resources/assets/fonts/72c114cf.woff +0 -0
  16. package/resources/assets/fonts/73c57e73.woff2 +0 -0
  17. package/resources/assets/fonts/813dca6c.woff +0 -0
  18. package/resources/assets/fonts/8a9b0995.woff2 +0 -0
  19. package/resources/assets/fonts/90b4832f.woff +0 -0
  20. package/resources/assets/fonts/9394ab85.woff2 +0 -0
  21. package/resources/assets/fonts/9b3c7d7f.woff2 +0 -0
  22. package/resources/assets/fonts/Monaco.ttf +0 -0
  23. package/resources/assets/fonts/b1b36d74.woff +0 -0
  24. package/resources/assets/fonts/b5d74798.woff2 +0 -0
  25. package/resources/assets/fonts/b9f81a4d.woff +0 -0
  26. package/resources/assets/fonts/c9784008.woff2 +0 -0
  27. package/resources/assets/fonts/cf692227.woff +0 -0
  28. package/resources/assets/fonts/d1c6ab51.woff2 +0 -0
  29. package/resources/assets/fonts/e2eb62fc.woff +0 -0
  30. package/resources/assets/fonts/fe21f8d8.woff2 +0 -0
  31. package/resources/assets/fonts/nps/CampmateScript-Regular.woff2 +0 -0
  32. package/resources/assets/fonts/nps/NPS_2026-variable.woff2 +0 -0
  33. package/resources/assets/fonts/nps/RedwoodSerif-Regular.woff2 +0 -0
  34. package/resources/assets/fonts/nps/SequoiaSans-Regular.woff2 +0 -0
  35. package/resources/assets/fonts/nps/Switchback-Regular.woff2 +0 -0
  36. package/resources/assets/images/app-icon.png +0 -0
  37. package/resources/assets/images/bg-img.png +0 -0
  38. package/resources/assets/images/park-ridge.svg +15 -0
  39. package/resources/assets/images/topography.svg +1 -0
  40. package/resources/assets/scripts/main.ts +2153 -0
  41. package/resources/assets/styles/README.md +19 -0
  42. package/resources/assets/styles/docs/main.css +1 -0
  43. package/resources/assets/styles/docs/overrides.css +1 -0
  44. package/resources/assets/styles/docs/vars.css +8 -0
  45. package/resources/assets/styles/main.css +1419 -0
  46. package/resources/components/Button.stx +70 -0
  47. package/resources/components/Buttons/BaseButton.stx +39 -0
  48. package/resources/components/Buttons/Counter.stx +28 -0
  49. package/resources/components/Buttons/ToggleDark.stx +11 -0
  50. package/resources/components/Container.stx +10 -0
  51. package/resources/components/Dashboard/.gitkeep +0 -0
  52. package/resources/components/Dashboard/Auth/ForgotPassword.stx +127 -0
  53. package/resources/components/Dashboard/Auth/Login.stx +212 -0
  54. package/resources/components/Dashboard/Auth/Register.stx +306 -0
  55. package/resources/components/Dashboard/Avatar.stx +123 -0
  56. package/resources/components/Dashboard/Billing/ActivePlan.stx +57 -0
  57. package/resources/components/Dashboard/Billing/CardBrands.stx +32 -0
  58. package/resources/components/Dashboard/Billing/CardForm.stx +34 -0
  59. package/resources/components/Dashboard/Billing/OneTimePayment.stx +28 -0
  60. package/resources/components/Dashboard/Billing/PaymentForm.stx +33 -0
  61. package/resources/components/Dashboard/Billing/PaymentMethod.stx +66 -0
  62. package/resources/components/Dashboard/Billing/PaymentMethodList.stx +52 -0
  63. package/resources/components/Dashboard/Billing/Plans.stx +136 -0
  64. package/resources/components/Dashboard/Buttons/AppButton.stx +48 -0
  65. package/resources/components/Dashboard/Buttons/IconButton.stx +20 -0
  66. package/resources/components/Dashboard/Card.stx +78 -0
  67. package/resources/components/Dashboard/Chart.stx +75 -0
  68. package/resources/components/Dashboard/CodeEditor.stx +41 -0
  69. package/resources/components/Dashboard/Commerce/BulkActionBar.stx +70 -0
  70. package/resources/components/Dashboard/Commerce/CategoriesTable.stx +133 -0
  71. package/resources/components/Dashboard/Commerce/CouponsTable.stx +161 -0
  72. package/resources/components/Dashboard/Commerce/CustomersTable.stx +142 -0
  73. package/resources/components/Dashboard/Commerce/Delivery/DeliveryRoutesTable.stx +80 -0
  74. package/resources/components/Dashboard/Commerce/Delivery/DigitalDeliveryTable.stx +85 -0
  75. package/resources/components/Dashboard/Commerce/Delivery/DriversTable.stx +99 -0
  76. package/resources/components/Dashboard/Commerce/Delivery/LicenseKeysTable.stx +92 -0
  77. package/resources/components/Dashboard/Commerce/Delivery/LicenseTemplatesTable.stx +88 -0
  78. package/resources/components/Dashboard/Commerce/Delivery/Pagination.stx +122 -0
  79. package/resources/components/Dashboard/Commerce/Delivery/SearchFilter.stx +23 -0
  80. package/resources/components/Dashboard/Commerce/Delivery/ShippingMethodsTable.stx +80 -0
  81. package/resources/components/Dashboard/Commerce/Delivery/ShippingRatesTable.stx +59 -0
  82. package/resources/components/Dashboard/Commerce/Delivery/ShippingZonesTable.stx +71 -0
  83. package/resources/components/Dashboard/Commerce/Delivery/TabNavigation.stx +36 -0
  84. package/resources/components/Dashboard/Commerce/Forms/CouponsForm.stx +191 -0
  85. package/resources/components/Dashboard/Commerce/OrdersTable.stx +131 -0
  86. package/resources/components/Dashboard/Commerce/ProductsTable.stx +170 -0
  87. package/resources/components/Dashboard/CreateRecordModal.stx +363 -0
  88. package/resources/components/Dashboard/DashboardLayout.stx +155 -0
  89. package/resources/components/Dashboard/Deployments/ActivityFeed.stx +54 -0
  90. package/resources/components/Dashboard/Deployments/DeployScript.stx +23 -0
  91. package/resources/components/Dashboard/Deployments/DeploymentHistory.stx +97 -0
  92. package/resources/components/Dashboard/Deployments/DeploymentList.stx +94 -0
  93. package/resources/components/Dashboard/Deployments/LiveTerminalOutput.stx +18 -0
  94. package/resources/components/Dashboard/Elements/Dropdown.stx +57 -0
  95. package/resources/components/Dashboard/Email/EmailActivityChart.stx +111 -0
  96. package/resources/components/Dashboard/Email/EmailCompose.stx +72 -0
  97. package/resources/components/Dashboard/Email/EmailDetail.stx +105 -0
  98. package/resources/components/Dashboard/Email/EmailList.stx +117 -0
  99. package/resources/components/Dashboard/Email/EmailSearch.stx +40 -0
  100. package/resources/components/Dashboard/Email/EmailSidebar.stx +133 -0
  101. package/resources/components/Dashboard/GlobalSearch.stx +124 -0
  102. package/resources/components/Dashboard/MobileSidebar.stx +47 -0
  103. package/resources/components/Dashboard/Modals/BaseModal.stx +50 -0
  104. package/resources/components/Dashboard/Modals/Popups/Alert.stx +112 -0
  105. package/resources/components/Dashboard/Modals/Popups/Toast.stx +70 -0
  106. package/resources/components/Dashboard/Modals/ToastWrapper.stx +35 -0
  107. package/resources/components/Dashboard/Monitoring/ErrorDetailModal.stx +228 -0
  108. package/resources/components/Dashboard/Monitoring/ErrorsTable.stx +184 -0
  109. package/resources/components/Dashboard/Navbar.stx +194 -0
  110. package/resources/components/Dashboard/NavbarModern.stx +188 -0
  111. package/resources/components/Dashboard/NotificationErrorModal.stx +105 -0
  112. package/resources/components/Dashboard/NotificationStatusBadge.stx +20 -0
  113. package/resources/components/Dashboard/Pagination.stx +90 -0
  114. package/resources/components/Dashboard/Queue/QueueTable.stx +127 -0
  115. package/resources/components/Dashboard/Settings/Forms/AIForm.stx +126 -0
  116. package/resources/components/Dashboard/Settings/Forms/AnalyticsForm.stx +52 -0
  117. package/resources/components/Dashboard/Settings/Forms/AppForm.stx +157 -0
  118. package/resources/components/Dashboard/Settings/Forms/CLIForm.stx +66 -0
  119. package/resources/components/Dashboard/Settings/Forms/CacheForm.stx +253 -0
  120. package/resources/components/Dashboard/Settings/Forms/CloudForm.stx +441 -0
  121. package/resources/components/Dashboard/Settings/Forms/DNSForm.stx +307 -0
  122. package/resources/components/Dashboard/Settings/Forms/DatabaseForm.stx +168 -0
  123. package/resources/components/Dashboard/Settings/Forms/EmailForm.stx +100 -0
  124. package/resources/components/Dashboard/Settings/Forms/FileSystemForm.stx +259 -0
  125. package/resources/components/Dashboard/Settings/Forms/HashingForm.stx +119 -0
  126. package/resources/components/Dashboard/Settings/Forms/LibraryForm.stx +389 -0
  127. package/resources/components/Dashboard/Settings/Forms/QueueForm.stx +219 -0
  128. package/resources/components/Dashboard/Settings/Forms/SearchEngineForm.stx +48 -0
  129. package/resources/components/Dashboard/Settings/Forms/SecurityForm.stx +143 -0
  130. package/resources/components/Dashboard/Settings/Forms/ServicesForm.stx +194 -0
  131. package/resources/components/Dashboard/Settings/Forms/StorageForm.stx +191 -0
  132. package/resources/components/Dashboard/Settings/Forms/TeamsForm.stx +33 -0
  133. package/resources/components/Dashboard/Settings/SettingsFormManager.stx +181 -0
  134. package/resources/components/Dashboard/SettingsHeader.stx +88 -0
  135. package/resources/components/Dashboard/SettingsSidebar.stx +234 -0
  136. package/resources/components/Dashboard/Sidebar.stx +23 -0
  137. package/resources/components/Dashboard/SidebarModern.stx +249 -0
  138. package/resources/components/Dashboard/Skeleton/LoadingCard.stx +15 -0
  139. package/resources/components/Dashboard/Skeleton/LoadingDetails.stx +26 -0
  140. package/resources/components/Dashboard/Table.stx +82 -0
  141. package/resources/components/Dashboard/TerminalContainer.stx +97 -0
  142. package/resources/components/Dashboard/Tooltip.stx +166 -0
  143. package/resources/components/Dashboard/Transaction/index.stx +88 -0
  144. package/resources/components/Dashboard/UI/ActivityTable.stx +54 -0
  145. package/resources/components/Dashboard/UI/Avatar.stx +102 -0
  146. package/resources/components/Dashboard/UI/Badge.stx +66 -0
  147. package/resources/components/Dashboard/UI/Button.stx +73 -0
  148. package/resources/components/Dashboard/UI/Card.stx +51 -0
  149. package/resources/components/Dashboard/UI/ChartCard.stx +36 -0
  150. package/resources/components/Dashboard/UI/Checkbox.stx +74 -0
  151. package/resources/components/Dashboard/UI/ConfirmDialog.stx +74 -0
  152. package/resources/components/Dashboard/UI/DataTable.stx +45 -0
  153. package/resources/components/Dashboard/UI/Dropdown.stx +72 -0
  154. package/resources/components/Dashboard/UI/DropdownItem.stx +80 -0
  155. package/resources/components/Dashboard/UI/EmptyState.stx +50 -0
  156. package/resources/components/Dashboard/UI/FilterBar.stx +48 -0
  157. package/resources/components/Dashboard/UI/Input.stx +77 -0
  158. package/resources/components/Dashboard/UI/Modal.stx +75 -0
  159. package/resources/components/Dashboard/UI/PageHeader.stx +69 -0
  160. package/resources/components/Dashboard/UI/PageLayout.stx +84 -0
  161. package/resources/components/Dashboard/UI/Pagination.stx +126 -0
  162. package/resources/components/Dashboard/UI/QuickLinks.stx +31 -0
  163. package/resources/components/Dashboard/UI/RouterLink.stx +31 -0
  164. package/resources/components/Dashboard/UI/Select.stx +84 -0
  165. package/resources/components/Dashboard/UI/ServiceHealth.stx +38 -0
  166. package/resources/components/Dashboard/UI/StatsCard.stx +79 -0
  167. package/resources/components/Dashboard/UI/Table.stx +143 -0
  168. package/resources/components/Dashboard/UI/Tabs.stx +45 -0
  169. package/resources/components/Dashboard/UI/Textarea.stx +93 -0
  170. package/resources/components/Dashboard/UI/Toggle.stx +84 -0
  171. package/resources/components/Dashboard/UI/WindowControls.stx +135 -0
  172. package/resources/components/Dashboard/Widget.stx +89 -0
  173. package/resources/components/Dashboard/WindowControls.stx +119 -0
  174. package/resources/components/Dashboard/index.ts +106 -0
  175. package/resources/components/Docs/Demo/ComboboxCode.md +114 -0
  176. package/resources/components/Docs/Demo/ComboboxDemo.stx +91 -0
  177. package/resources/components/Docs/Demo/DialogCode.md +42 -0
  178. package/resources/components/Docs/Demo/DialogDemo.stx +76 -0
  179. package/resources/components/Docs/Demo/DocsPlayground.stx +39 -0
  180. package/resources/components/Docs/Demo/DropdownCode.md +109 -0
  181. package/resources/components/Docs/Demo/DropdownDemo.stx +82 -0
  182. package/resources/components/Docs/Demo/Hero.stx +100 -0
  183. package/resources/components/Docs/Demo/ListboxCode.md +87 -0
  184. package/resources/components/Docs/Demo/ListboxDemo.stx +59 -0
  185. package/resources/components/Docs/Demo/NotificationCode.md +173 -0
  186. package/resources/components/Docs/Demo/NotificationDemo.stx +99 -0
  187. package/resources/components/Docs/Demo/PopoverCode.md +161 -0
  188. package/resources/components/Docs/Demo/PopoverDemo.stx +96 -0
  189. package/resources/components/Docs/Demo/RadioGroupCode.md +98 -0
  190. package/resources/components/Docs/Demo/RadioGroupDemo.stx +53 -0
  191. package/resources/components/Docs/Demo/StepperCode.md +216 -0
  192. package/resources/components/Docs/Demo/StepperDemo.stx +137 -0
  193. package/resources/components/Docs/Demo/SwitchCode.md +24 -0
  194. package/resources/components/Docs/Demo/SwitchDemo.stx +28 -0
  195. package/resources/components/Docs/Home.stx +7 -0
  196. package/resources/components/Docs/HomeContributors.stx +23 -0
  197. package/resources/components/Docs/HomeSponsors.stx +17 -0
  198. package/resources/components/Docs/HomeTeam.stx +18 -0
  199. package/resources/components/Docs/TeamMember.stx +79 -0
  200. package/resources/components/Email/EmailButton.stx +32 -0
  201. package/resources/components/Email/EmailDivider.stx +20 -0
  202. package/resources/components/Email/EmailImage.stx +24 -0
  203. package/resources/components/Email/EmailLayout.stx +55 -0
  204. package/resources/components/Email/EmailLink.stx +22 -0
  205. package/resources/components/Email/EmailSection.stx +20 -0
  206. package/resources/components/Email/EmailText.stx +30 -0
  207. package/resources/components/Forum/ForumBreadcrumb.stx +38 -0
  208. package/resources/components/Forum/ForumCategory.stx +16 -0
  209. package/resources/components/Forum/ForumCategoryItem.stx +46 -0
  210. package/resources/components/Forum/ForumLayout.stx +36 -0
  211. package/resources/components/Forum/ForumPagination.stx +39 -0
  212. package/resources/components/Forum/ForumPost.stx +71 -0
  213. package/resources/components/Forum/ForumReplyForm.stx +76 -0
  214. package/resources/components/Forum/ForumSidebar.stx +86 -0
  215. package/resources/components/Forum/ForumTopicItem.stx +77 -0
  216. package/resources/components/Forum/ForumTopicList.stx +23 -0
  217. package/resources/components/HelloWorld.stx +253 -0
  218. package/resources/components/Logo.stx +10 -0
  219. package/resources/components/Marketing/CallToAction.stx +30 -0
  220. package/resources/components/Marketing/ComingSoon.stx +155 -0
  221. package/resources/components/Marketing/Faqs.stx +99 -0
  222. package/resources/components/Marketing/Feature.stx +32 -0
  223. package/resources/components/Marketing/Fields.stx +28 -0
  224. package/resources/components/Marketing/Footer.stx +33 -0
  225. package/resources/components/Marketing/Header.stx +51 -0
  226. package/resources/components/Marketing/Hero.stx +46 -0
  227. package/resources/components/Marketing/Layout.stx +26 -0
  228. package/resources/components/Marketing/NavLink.stx +13 -0
  229. package/resources/components/Marketing/Plan.stx +43 -0
  230. package/resources/components/Marketing/Pricing.stx +120 -0
  231. package/resources/components/Marketing/PrimaryFeatures.stx +80 -0
  232. package/resources/components/Marketing/PrimaryFeatures2.stx +98 -0
  233. package/resources/components/Marketing/SecondaryFeatures.stx +80 -0
  234. package/resources/components/Marketing/Testimonials.stx +120 -0
  235. package/resources/components/Pagination.stx +149 -0
  236. package/resources/components/Playground.stx +9 -0
  237. package/resources/components/README.md +87 -0
  238. package/resources/components/Storefront/AnnouncementBar.stx +17 -0
  239. package/resources/components/Storefront/CartDrawer.stx +227 -0
  240. package/resources/components/Storefront/CheckoutSteps.stx +50 -0
  241. package/resources/components/Storefront/Footer.stx +81 -0
  242. package/resources/components/Storefront/Header.stx +66 -0
  243. package/resources/components/Storefront/OrderSummary.stx +79 -0
  244. package/resources/components/Storefront/ProductCard.stx +63 -0
  245. package/resources/components/Storefront/ProductGallery.stx +88 -0
  246. package/resources/components/Storefront/QuantitySelector.stx +97 -0
  247. package/resources/components/index.ts +13 -0
  248. package/resources/emails/email-verification.stx +46 -0
  249. package/resources/emails/layouts/base.html +113 -0
  250. package/resources/emails/password-changed.stx +55 -0
  251. package/resources/emails/password-reset.stx +43 -0
  252. package/resources/emails/subscription-confirmation.stx +99 -0
  253. package/resources/emails/welcome.stx +48 -0
  254. package/resources/functions/README.md +28 -0
  255. package/resources/functions/counter.ts +13 -0
  256. package/resources/functions/dark.ts +4 -0
  257. package/resources/functions/dashboard/analytics.ts +238 -0
  258. package/resources/functions/dashboard/config-io.ts +316 -0
  259. package/resources/functions/dashboard/data.ts +375 -0
  260. package/resources/functions/dashboard/library.ts +250 -0
  261. package/resources/functions/dashboard/sidebar.ts +537 -0
  262. package/resources/functions/dashboard/system.ts +150 -0
  263. package/resources/layouts/403.stx +188 -0
  264. package/resources/layouts/404.stx +34 -0
  265. package/resources/layouts/README.md +14 -0
  266. package/resources/layouts/dashboard/default.stx +20 -0
  267. package/resources/layouts/dashboard/guest.stx +10 -0
  268. package/resources/layouts/default.stx +3 -0
  269. package/resources/layouts/maintenance.stx +11 -0
  270. package/resources/layouts/storefront.stx +73 -0
  271. package/resources/layouts/system-tray/default.stx +3 -0
  272. package/resources/modules/.gitkeep +0 -0
  273. package/resources/plugins/.gitkeep +0 -0
  274. package/resources/plugins/preloader.ts +308 -0
  275. package/resources/types/README.md +3 -0
  276. package/resources/views/cart.stx +149 -0
  277. package/resources/views/checkout/contact.stx +101 -0
  278. package/resources/views/checkout/payment.stx +114 -0
  279. package/resources/views/checkout/shipping.stx +120 -0
  280. package/resources/views/coming-soon.stx +9 -0
  281. package/resources/views/dashboard/custom-page.stx +45 -0
  282. package/resources/views/dashboard/index.stx +24 -0
  283. package/resources/views/emails/welcome.stx +0 -0
  284. package/resources/views/errors/tester.stx +26 -0
  285. package/resources/views/index.stx +2865 -0
  286. package/resources/views/orders/[id].stx +130 -0
@@ -0,0 +1,114 @@
1
+ @extends('layouts/storefront')
2
+
3
+ @section('title', 'Checkout — Payment')
4
+
5
+ <script server>
6
+ const Database = require('bun:sqlite').Database
7
+ const path = require('path')
8
+
9
+ const dbPath = path.resolve(process.cwd(), process.env.DB_DATABASE_PATH || 'database/stacks.sqlite')
10
+ const db = new Database(dbPath, { readonly: true })
11
+
12
+ const token = (typeof requestContext !== 'undefined') ? requestContext.cookie('stacks_cart') : null
13
+ let items = []
14
+ let cart = null
15
+
16
+ if (token) {
17
+ cart = db.query(`SELECT * FROM carts WHERE session_token = ?1 AND status = 'active' LIMIT 1`).get(token)
18
+ if (cart) {
19
+ items = db.query(`
20
+ SELECT product_name, quantity, total_price
21
+ FROM cart_items WHERE cart_id = ?1 ORDER BY id ASC
22
+ `).all(cart.id).map((row) => {
23
+ const qty = Number(row.quantity)
24
+ const lineTotal = Number(row.total_price)
25
+ return {
26
+ name: row.product_name,
27
+ qty,
28
+ lineTotal,
29
+ lineTotalLabel: `$${lineTotal.toFixed(2)}`,
30
+ }
31
+ })
32
+ }
33
+ }
34
+
35
+ const FREE_SHIPPING_THRESHOLD = Number(process.env.STOREFRONT_FREE_SHIPPING_THRESHOLD ?? 40) || 40
36
+ const FLAT_SHIPPING = Number(process.env.STOREFRONT_FLAT_SHIPPING ?? 5) || 5
37
+ const subtotal = items.reduce((s, i) => s + i.lineTotal, 0)
38
+ const shipping = subtotal <= 0 ? 0 : (subtotal >= FREE_SHIPPING_THRESHOLD ? 0 : FLAT_SHIPPING)
39
+ const total = subtotal + shipping
40
+ const remainingForFree = Math.max(0, FREE_SHIPPING_THRESHOLD - subtotal)
41
+
42
+ const subtotalLabel = `$${subtotal.toFixed(2)}`
43
+ const shippingLabel = shipping === 0 ? 'Free' : `$${shipping.toFixed(2)}`
44
+ const totalLabel = `$${total.toFixed(2)}`
45
+ const freeShippingNote = (shipping > 0 && remainingForFree > 0)
46
+ ? `Add $${remainingForFree.toFixed(2)} more for free shipping.`
47
+ : ''
48
+
49
+ const ready = !!cart?.email && !!cart?.shipping_name && !!cart?.shipping_address
50
+ </script>
51
+
52
+ @section('content')
53
+ <div class="mx-auto px-6 py-12 max-w-5xl">
54
+ <CheckoutSteps current="payment" />
55
+
56
+ @if (items.length === 0 || !ready)
57
+ <div class="p-12 text-center border border-dashed border-stone-300 rounded-3xl">
58
+ <p class="text-stone-500">Finish the earlier steps first.</p>
59
+ <a href="/checkout/contact" class="inline-flex mt-6 px-6 py-3 font-semibold text-sm text-stone-50 bg-stone-900 hover:bg-stone-800 rounded-full">Go to contact</a>
60
+ </div>
61
+ @else
62
+ <div class="grid gap-10 items-start md:grid-cols-[1fr_360px]">
63
+ <div>
64
+ <h1 class="font-bold text-3xl text-stone-900 tracking-tight">Payment</h1>
65
+ <p class="mt-2 text-stone-600">No card is charged — this is a demo store. Swap in Stripe at <code class="px-1.5 py-0.5 text-xs bg-stone-100 rounded">Actions/Storefront/PlaceOrderAction.ts</code>.</p>
66
+
67
+ <!-- Mock card form. The fields aren't actually submitted —
68
+ the real submit goes to /api/checkout/place which uses
69
+ the cart row state set in earlier steps. We render the
70
+ fields anyway so the experience matches a real store. -->
71
+ <form action="/api/checkout/place" method="POST" class="mt-8 space-y-5">
72
+ <div>
73
+ <label class="font-semibold text-stone-500 text-xs tracking-wider uppercase">Card number</label>
74
+ <input type="text" inputmode="numeric" placeholder="4242 4242 4242 4242" autocomplete="cc-number" class="mt-1 px-4 py-3 w-full text-sm border border-stone-300 rounded-2xl focus:border-stone-900 focus:outline-none">
75
+ </div>
76
+ <div class="grid gap-4 grid-cols-2">
77
+ <div>
78
+ <label class="font-semibold text-stone-500 text-xs tracking-wider uppercase">Expiry</label>
79
+ <input type="text" inputmode="numeric" placeholder="MM / YY" autocomplete="cc-exp" class="mt-1 px-4 py-3 w-full text-sm border border-stone-300 rounded-2xl focus:border-stone-900 focus:outline-none">
80
+ </div>
81
+ <div>
82
+ <label class="font-semibold text-stone-500 text-xs tracking-wider uppercase">CVC</label>
83
+ <input type="text" inputmode="numeric" placeholder="123" autocomplete="cc-csc" class="mt-1 px-4 py-3 w-full text-sm border border-stone-300 rounded-2xl focus:border-stone-900 focus:outline-none">
84
+ </div>
85
+ </div>
86
+
87
+ <div class="p-4 text-sm bg-stone-50 border border-stone-200 rounded-xl">
88
+ <p class="font-semibold text-stone-500 text-xs tracking-wider uppercase">Ship to</p>
89
+ <p class="mt-1 text-stone-900">{{ cart.shipping_name }}</p>
90
+ <p class="text-stone-700 whitespace-pre-line">{{ cart.shipping_address }}, {{ cart.shipping_city }}, {{ cart.shipping_state }} {{ cart.shipping_zip }}</p>
91
+ <p class="mt-2 text-stone-500 text-xs">{{ cart.email }}</p>
92
+ </div>
93
+
94
+ <div class="flex gap-4 items-center justify-between pt-2">
95
+ <a href="/checkout/shipping" class="text-sm text-stone-500 hover:text-stone-900">← Back</a>
96
+ <button type="submit" class="px-6 py-3 font-semibold text-sm text-stone-50 bg-stone-900 hover:bg-stone-800 rounded-full transition-colors">
97
+ Place order — {{ totalLabel }}
98
+ </button>
99
+ </div>
100
+ </form>
101
+ </div>
102
+
103
+ <OrderSummary
104
+ :items="items"
105
+ subtotalLabel="{{ subtotalLabel }}"
106
+ shippingLabel="{{ shippingLabel }}"
107
+ totalLabel="{{ totalLabel }}"
108
+ freeShippingNote="{{ freeShippingNote }}"
109
+ :showItems="true"
110
+ />
111
+ </div>
112
+ @endif
113
+ </div>
114
+ @endsection
@@ -0,0 +1,120 @@
1
+ @extends('layouts/storefront')
2
+
3
+ @section('title', 'Checkout — Shipping')
4
+
5
+ <script server>
6
+ const Database = require('bun:sqlite').Database
7
+ const path = require('path')
8
+
9
+ const dbPath = path.resolve(process.cwd(), process.env.DB_DATABASE_PATH || 'database/stacks.sqlite')
10
+ const db = new Database(dbPath, { readonly: true })
11
+
12
+ const token = (typeof requestContext !== 'undefined') ? requestContext.cookie('stacks_cart') : null
13
+ let items = []
14
+ let cart = null
15
+
16
+ if (token) {
17
+ cart = db.query(`SELECT * FROM carts WHERE session_token = ?1 AND status = 'active' LIMIT 1`).get(token)
18
+ if (cart) {
19
+ items = db.query(`
20
+ SELECT product_name, quantity, total_price
21
+ FROM cart_items WHERE cart_id = ?1 ORDER BY id ASC
22
+ `).all(cart.id).map((row) => {
23
+ const qty = Number(row.quantity)
24
+ const lineTotal = Number(row.total_price)
25
+ return {
26
+ name: row.product_name,
27
+ qty,
28
+ lineTotal,
29
+ lineTotalLabel: `$${lineTotal.toFixed(2)}`,
30
+ }
31
+ })
32
+ }
33
+ }
34
+
35
+ const FREE_SHIPPING_THRESHOLD = Number(process.env.STOREFRONT_FREE_SHIPPING_THRESHOLD ?? 40) || 40
36
+ const FLAT_SHIPPING = Number(process.env.STOREFRONT_FLAT_SHIPPING ?? 5) || 5
37
+ const subtotal = items.reduce((s, i) => s + i.lineTotal, 0)
38
+ const shipping = subtotal <= 0 ? 0 : (subtotal >= FREE_SHIPPING_THRESHOLD ? 0 : FLAT_SHIPPING)
39
+ const total = subtotal + shipping
40
+ const remainingForFree = Math.max(0, FREE_SHIPPING_THRESHOLD - subtotal)
41
+
42
+ const subtotalLabel = `$${subtotal.toFixed(2)}`
43
+ const shippingLabel = shipping === 0 ? 'Free' : `$${shipping.toFixed(2)}`
44
+ const totalLabel = `$${total.toFixed(2)}`
45
+ const freeShippingNote = (shipping > 0 && remainingForFree > 0)
46
+ ? `Add $${remainingForFree.toFixed(2)} more for free shipping.`
47
+ : ''
48
+
49
+ const ship = {
50
+ name: cart?.shipping_name || '',
51
+ address: cart?.shipping_address || '',
52
+ city: cart?.shipping_city || '',
53
+ state: cart?.shipping_state || '',
54
+ zip: cart?.shipping_zip || '',
55
+ }
56
+ </script>
57
+
58
+ @section('content')
59
+ <div class="mx-auto px-6 py-12 max-w-5xl">
60
+ <CheckoutSteps current="shipping" />
61
+
62
+ @if (items.length === 0 || !cart?.email)
63
+ <div class="p-12 text-center border border-dashed border-stone-300 rounded-3xl">
64
+ <p class="text-stone-500">Start at the contact step.</p>
65
+ <a href="/checkout/contact" class="inline-flex mt-6 px-6 py-3 font-semibold text-sm text-stone-50 bg-stone-900 hover:bg-stone-800 rounded-full">Go to contact</a>
66
+ </div>
67
+ @else
68
+ <div class="grid gap-10 items-start md:grid-cols-[1fr_360px]">
69
+ <div>
70
+ <h1 class="font-bold text-3xl text-stone-900 tracking-tight">Shipping address</h1>
71
+ <p class="mt-2 text-stone-600">Where should we send the bowl?</p>
72
+
73
+ <form action="/api/checkout/shipping" method="POST" class="mt-8 space-y-5">
74
+ <div>
75
+ <label class="font-semibold text-stone-500 text-xs tracking-wider uppercase">Full name</label>
76
+ <input type="text" name="shipping_name" required autocomplete="name" value="{{ ship.name }}" class="mt-1 px-4 py-3 w-full text-sm border border-stone-300 rounded-2xl focus:border-stone-900 focus:outline-none">
77
+ </div>
78
+
79
+ <div>
80
+ <label class="font-semibold text-stone-500 text-xs tracking-wider uppercase">Street address</label>
81
+ <input type="text" name="shipping_address" required autocomplete="street-address" value="{{ ship.address }}" class="mt-1 px-4 py-3 w-full text-sm border border-stone-300 rounded-2xl focus:border-stone-900 focus:outline-none">
82
+ </div>
83
+
84
+ <div class="grid gap-4 grid-cols-2">
85
+ <div>
86
+ <label class="font-semibold text-stone-500 text-xs tracking-wider uppercase">City</label>
87
+ <input type="text" name="shipping_city" required autocomplete="address-level2" value="{{ ship.city }}" class="mt-1 px-4 py-3 w-full text-sm border border-stone-300 rounded-2xl focus:border-stone-900 focus:outline-none">
88
+ </div>
89
+ <div>
90
+ <label class="font-semibold text-stone-500 text-xs tracking-wider uppercase">State</label>
91
+ <input type="text" name="shipping_state" required autocomplete="address-level1" value="{{ ship.state }}" class="mt-1 px-4 py-3 w-full text-sm border border-stone-300 rounded-2xl focus:border-stone-900 focus:outline-none">
92
+ </div>
93
+ </div>
94
+
95
+ <div class="max-w-[200px]">
96
+ <label class="font-semibold text-stone-500 text-xs tracking-wider uppercase">ZIP / Postal</label>
97
+ <input type="text" name="shipping_zip" required autocomplete="postal-code" value="{{ ship.zip }}" class="mt-1 px-4 py-3 w-full text-sm border border-stone-300 rounded-2xl focus:border-stone-900 focus:outline-none">
98
+ </div>
99
+
100
+ <div class="flex gap-4 items-center justify-between pt-2">
101
+ <a href="/checkout/contact" class="text-sm text-stone-500 hover:text-stone-900">← Back</a>
102
+ <button type="submit" class="px-6 py-3 font-semibold text-sm text-stone-50 bg-stone-900 hover:bg-stone-800 rounded-full transition-colors">
103
+ Continue to payment
104
+ </button>
105
+ </div>
106
+ </form>
107
+ </div>
108
+
109
+ <OrderSummary
110
+ :items="items"
111
+ subtotalLabel="{{ subtotalLabel }}"
112
+ shippingLabel="{{ shippingLabel }}"
113
+ totalLabel="{{ totalLabel }}"
114
+ freeShippingNote="{{ freeShippingNote }}"
115
+ :showItems="true"
116
+ />
117
+ </div>
118
+ @endif
119
+ </div>
120
+ @endsection
@@ -0,0 +1,9 @@
1
+ <script>
2
+ defineOptions({
3
+ name: 'ComingSoonPage',
4
+ })
5
+ </script>
6
+
7
+ <main>
8
+ <ComingSoon />
9
+ </main>
@@ -0,0 +1,45 @@
1
+ <!--
2
+ Example Custom Dashboard Page
3
+
4
+ Create your own dashboard pages by adding .stx files here.
5
+ They will automatically be available at /dashboard/[filename]
6
+ -->
7
+
8
+ <script server>
9
+ const pageTitle = 'Custom Page'
10
+ const pageDescription = 'This is a custom dashboard page'
11
+
12
+ // Add your custom data fetching here
13
+ const customStats = [
14
+ { label: 'Custom Metric 1', value: '123' },
15
+ { label: 'Custom Metric 2', value: '456' },
16
+ ]
17
+ </script>
18
+ <div class="page-container">
19
+ <div class="page-header">
20
+ <div class="page-header-content">
21
+ <h1>{{ pageTitle }}</h1>
22
+ <p>{{ pageDescription }}</p>
23
+ </div>
24
+ </div>
25
+
26
+ <div class="page-content">
27
+ <div class="grid grid-2">
28
+ @foreach (customStats as stat)
29
+ <div class="stat-card">
30
+ <div class="stat-card-value">{{ stat }}</div>
31
+ <div class="stat-card-label">{{ stat.label }}</div>
32
+ </div>
33
+ @endforeach
34
+ </div>
35
+
36
+ <div class="card">
37
+ <div class="card-header">
38
+ <span class="card-title">Your Custom Content</span>
39
+ </div>
40
+ <div class="p-4">
41
+ <p>Add your custom dashboard content here.</p>
42
+ </div>
43
+ </div>
44
+ </div>
45
+ </div>
@@ -0,0 +1,24 @@
1
+ <!--
2
+ Dashboard View Extensions
3
+
4
+ This file allows you to customize the Stacks dashboard.
5
+ Add your custom dashboard views here to extend the default dashboard.
6
+
7
+ Example usage:
8
+ - Override default pages by matching the path
9
+ - Add new custom pages
10
+ - Include custom widgets and components
11
+ -->
12
+
13
+ <script server>
14
+ // Add your custom server-side data here
15
+ const customData = {
16
+ // Your custom dashboard data
17
+ }
18
+ </script>
19
+ <!--
20
+ Custom Dashboard Content
21
+
22
+ This template will be merged with the default dashboard.
23
+ You can add custom sections, widgets, or entirely new views.
24
+ -->
File without changes
@@ -0,0 +1,26 @@
1
+ <div class="mx-auto px-6 py-12 max-w-3xl">
2
+ <h1 class="mb-2 font-semibold text-3xl text-neutral-950 dark:text-white">Error Page Tester</h1>
3
+ <p class="mb-8 text-neutral-500 text-sm dark:text-neutral-400">
4
+ Laravel-style debug pages in development. Click a scenario to throw that exception and see the full trace.
5
+ </p>
6
+
7
+ <div class="grid gap-3">
8
+ @foreach(scenarios as scenario)
9
+ <a
10
+ href="{{ scenario.href }}"
11
+ class="block p-4 bg-white dark:bg-white/[2%] border border-neutral-200 rounded-lg dark:border-white/10 hover:border-rose-500 transition-colors"
12
+ >
13
+ <div class="flex gap-4 items-center justify-between mb-1">
14
+ <span class="font-semibold text-neutral-900 text-sm dark:text-white">{{ scenario.title }}</span>
15
+ <span class="px-2 py-0.5 font-semibold text-[11px] text-rose-900 tracking-wide uppercase dark:text-rose-100 bg-rose-200 dark:bg-rose-950 rounded">{{ scenario.status }}</span>
16
+ </div>
17
+ <p class="mb-2 text-neutral-600 text-xs dark:text-neutral-400">{{ scenario.description }}</p>
18
+ <code class="font-mono text-[11px] text-neutral-500">{{ scenario.href }}</code>
19
+ </a>
20
+ @endforeach
21
+ </div>
22
+
23
+ <div class="mt-8 p-4 text-neutral-500 text-xs dark:text-neutral-400 border border-dashed border-neutral-300 rounded-lg dark:border-white/15">
24
+ Requires <code class="font-mono">APP_ENV=development</code>. API clients with <code class="font-mono">Accept: application/json</code> receive JSON instead of HTML.
25
+ </div>
26
+ </div>