@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.
- package/LICENSE.md +21 -0
- package/README.md +2 -0
- package/package.json +20 -0
- package/resources/assets/fonts/013717e9.woff +0 -0
- package/resources/assets/fonts/03355817.woff2 +0 -0
- package/resources/assets/fonts/0380de7e.woff2 +0 -0
- package/resources/assets/fonts/0ba5d32a.woff +0 -0
- package/resources/assets/fonts/0bd57ddf.woff2 +0 -0
- package/resources/assets/fonts/19de0a60.woff2 +0 -0
- package/resources/assets/fonts/20b87e84.woff +0 -0
- package/resources/assets/fonts/4bbc67e1.woff +0 -0
- package/resources/assets/fonts/576fb0d7.woff +0 -0
- package/resources/assets/fonts/5ea10ee5.woff2 +0 -0
- package/resources/assets/fonts/6413fc0a.woff +0 -0
- package/resources/assets/fonts/72c114cf.woff +0 -0
- package/resources/assets/fonts/73c57e73.woff2 +0 -0
- package/resources/assets/fonts/813dca6c.woff +0 -0
- package/resources/assets/fonts/8a9b0995.woff2 +0 -0
- package/resources/assets/fonts/90b4832f.woff +0 -0
- package/resources/assets/fonts/9394ab85.woff2 +0 -0
- package/resources/assets/fonts/9b3c7d7f.woff2 +0 -0
- package/resources/assets/fonts/Monaco.ttf +0 -0
- package/resources/assets/fonts/b1b36d74.woff +0 -0
- package/resources/assets/fonts/b5d74798.woff2 +0 -0
- package/resources/assets/fonts/b9f81a4d.woff +0 -0
- package/resources/assets/fonts/c9784008.woff2 +0 -0
- package/resources/assets/fonts/cf692227.woff +0 -0
- package/resources/assets/fonts/d1c6ab51.woff2 +0 -0
- package/resources/assets/fonts/e2eb62fc.woff +0 -0
- package/resources/assets/fonts/fe21f8d8.woff2 +0 -0
- package/resources/assets/fonts/nps/CampmateScript-Regular.woff2 +0 -0
- package/resources/assets/fonts/nps/NPS_2026-variable.woff2 +0 -0
- package/resources/assets/fonts/nps/RedwoodSerif-Regular.woff2 +0 -0
- package/resources/assets/fonts/nps/SequoiaSans-Regular.woff2 +0 -0
- package/resources/assets/fonts/nps/Switchback-Regular.woff2 +0 -0
- package/resources/assets/images/app-icon.png +0 -0
- package/resources/assets/images/bg-img.png +0 -0
- package/resources/assets/images/park-ridge.svg +15 -0
- package/resources/assets/images/topography.svg +1 -0
- package/resources/assets/scripts/main.ts +2153 -0
- package/resources/assets/styles/README.md +19 -0
- package/resources/assets/styles/docs/main.css +1 -0
- package/resources/assets/styles/docs/overrides.css +1 -0
- package/resources/assets/styles/docs/vars.css +8 -0
- package/resources/assets/styles/main.css +1419 -0
- package/resources/components/Button.stx +70 -0
- package/resources/components/Buttons/BaseButton.stx +39 -0
- package/resources/components/Buttons/Counter.stx +28 -0
- package/resources/components/Buttons/ToggleDark.stx +11 -0
- package/resources/components/Container.stx +10 -0
- package/resources/components/Dashboard/.gitkeep +0 -0
- package/resources/components/Dashboard/Auth/ForgotPassword.stx +127 -0
- package/resources/components/Dashboard/Auth/Login.stx +212 -0
- package/resources/components/Dashboard/Auth/Register.stx +306 -0
- package/resources/components/Dashboard/Avatar.stx +123 -0
- package/resources/components/Dashboard/Billing/ActivePlan.stx +57 -0
- package/resources/components/Dashboard/Billing/CardBrands.stx +32 -0
- package/resources/components/Dashboard/Billing/CardForm.stx +34 -0
- package/resources/components/Dashboard/Billing/OneTimePayment.stx +28 -0
- package/resources/components/Dashboard/Billing/PaymentForm.stx +33 -0
- package/resources/components/Dashboard/Billing/PaymentMethod.stx +66 -0
- package/resources/components/Dashboard/Billing/PaymentMethodList.stx +52 -0
- package/resources/components/Dashboard/Billing/Plans.stx +136 -0
- package/resources/components/Dashboard/Buttons/AppButton.stx +48 -0
- package/resources/components/Dashboard/Buttons/IconButton.stx +20 -0
- package/resources/components/Dashboard/Card.stx +78 -0
- package/resources/components/Dashboard/Chart.stx +75 -0
- package/resources/components/Dashboard/CodeEditor.stx +41 -0
- package/resources/components/Dashboard/Commerce/BulkActionBar.stx +70 -0
- package/resources/components/Dashboard/Commerce/CategoriesTable.stx +133 -0
- package/resources/components/Dashboard/Commerce/CouponsTable.stx +161 -0
- package/resources/components/Dashboard/Commerce/CustomersTable.stx +142 -0
- package/resources/components/Dashboard/Commerce/Delivery/DeliveryRoutesTable.stx +80 -0
- package/resources/components/Dashboard/Commerce/Delivery/DigitalDeliveryTable.stx +85 -0
- package/resources/components/Dashboard/Commerce/Delivery/DriversTable.stx +99 -0
- package/resources/components/Dashboard/Commerce/Delivery/LicenseKeysTable.stx +92 -0
- package/resources/components/Dashboard/Commerce/Delivery/LicenseTemplatesTable.stx +88 -0
- package/resources/components/Dashboard/Commerce/Delivery/Pagination.stx +122 -0
- package/resources/components/Dashboard/Commerce/Delivery/SearchFilter.stx +23 -0
- package/resources/components/Dashboard/Commerce/Delivery/ShippingMethodsTable.stx +80 -0
- package/resources/components/Dashboard/Commerce/Delivery/ShippingRatesTable.stx +59 -0
- package/resources/components/Dashboard/Commerce/Delivery/ShippingZonesTable.stx +71 -0
- package/resources/components/Dashboard/Commerce/Delivery/TabNavigation.stx +36 -0
- package/resources/components/Dashboard/Commerce/Forms/CouponsForm.stx +191 -0
- package/resources/components/Dashboard/Commerce/OrdersTable.stx +131 -0
- package/resources/components/Dashboard/Commerce/ProductsTable.stx +170 -0
- package/resources/components/Dashboard/CreateRecordModal.stx +363 -0
- package/resources/components/Dashboard/DashboardLayout.stx +155 -0
- package/resources/components/Dashboard/Deployments/ActivityFeed.stx +54 -0
- package/resources/components/Dashboard/Deployments/DeployScript.stx +23 -0
- package/resources/components/Dashboard/Deployments/DeploymentHistory.stx +97 -0
- package/resources/components/Dashboard/Deployments/DeploymentList.stx +94 -0
- package/resources/components/Dashboard/Deployments/LiveTerminalOutput.stx +18 -0
- package/resources/components/Dashboard/Elements/Dropdown.stx +57 -0
- package/resources/components/Dashboard/Email/EmailActivityChart.stx +111 -0
- package/resources/components/Dashboard/Email/EmailCompose.stx +72 -0
- package/resources/components/Dashboard/Email/EmailDetail.stx +105 -0
- package/resources/components/Dashboard/Email/EmailList.stx +117 -0
- package/resources/components/Dashboard/Email/EmailSearch.stx +40 -0
- package/resources/components/Dashboard/Email/EmailSidebar.stx +133 -0
- package/resources/components/Dashboard/GlobalSearch.stx +124 -0
- package/resources/components/Dashboard/MobileSidebar.stx +47 -0
- package/resources/components/Dashboard/Modals/BaseModal.stx +50 -0
- package/resources/components/Dashboard/Modals/Popups/Alert.stx +112 -0
- package/resources/components/Dashboard/Modals/Popups/Toast.stx +70 -0
- package/resources/components/Dashboard/Modals/ToastWrapper.stx +35 -0
- package/resources/components/Dashboard/Monitoring/ErrorDetailModal.stx +228 -0
- package/resources/components/Dashboard/Monitoring/ErrorsTable.stx +184 -0
- package/resources/components/Dashboard/Navbar.stx +194 -0
- package/resources/components/Dashboard/NavbarModern.stx +188 -0
- package/resources/components/Dashboard/NotificationErrorModal.stx +105 -0
- package/resources/components/Dashboard/NotificationStatusBadge.stx +20 -0
- package/resources/components/Dashboard/Pagination.stx +90 -0
- package/resources/components/Dashboard/Queue/QueueTable.stx +127 -0
- package/resources/components/Dashboard/Settings/Forms/AIForm.stx +126 -0
- package/resources/components/Dashboard/Settings/Forms/AnalyticsForm.stx +52 -0
- package/resources/components/Dashboard/Settings/Forms/AppForm.stx +157 -0
- package/resources/components/Dashboard/Settings/Forms/CLIForm.stx +66 -0
- package/resources/components/Dashboard/Settings/Forms/CacheForm.stx +253 -0
- package/resources/components/Dashboard/Settings/Forms/CloudForm.stx +441 -0
- package/resources/components/Dashboard/Settings/Forms/DNSForm.stx +307 -0
- package/resources/components/Dashboard/Settings/Forms/DatabaseForm.stx +168 -0
- package/resources/components/Dashboard/Settings/Forms/EmailForm.stx +100 -0
- package/resources/components/Dashboard/Settings/Forms/FileSystemForm.stx +259 -0
- package/resources/components/Dashboard/Settings/Forms/HashingForm.stx +119 -0
- package/resources/components/Dashboard/Settings/Forms/LibraryForm.stx +389 -0
- package/resources/components/Dashboard/Settings/Forms/QueueForm.stx +219 -0
- package/resources/components/Dashboard/Settings/Forms/SearchEngineForm.stx +48 -0
- package/resources/components/Dashboard/Settings/Forms/SecurityForm.stx +143 -0
- package/resources/components/Dashboard/Settings/Forms/ServicesForm.stx +194 -0
- package/resources/components/Dashboard/Settings/Forms/StorageForm.stx +191 -0
- package/resources/components/Dashboard/Settings/Forms/TeamsForm.stx +33 -0
- package/resources/components/Dashboard/Settings/SettingsFormManager.stx +181 -0
- package/resources/components/Dashboard/SettingsHeader.stx +88 -0
- package/resources/components/Dashboard/SettingsSidebar.stx +234 -0
- package/resources/components/Dashboard/Sidebar.stx +23 -0
- package/resources/components/Dashboard/SidebarModern.stx +249 -0
- package/resources/components/Dashboard/Skeleton/LoadingCard.stx +15 -0
- package/resources/components/Dashboard/Skeleton/LoadingDetails.stx +26 -0
- package/resources/components/Dashboard/Table.stx +82 -0
- package/resources/components/Dashboard/TerminalContainer.stx +97 -0
- package/resources/components/Dashboard/Tooltip.stx +166 -0
- package/resources/components/Dashboard/Transaction/index.stx +88 -0
- package/resources/components/Dashboard/UI/ActivityTable.stx +54 -0
- package/resources/components/Dashboard/UI/Avatar.stx +102 -0
- package/resources/components/Dashboard/UI/Badge.stx +66 -0
- package/resources/components/Dashboard/UI/Button.stx +73 -0
- package/resources/components/Dashboard/UI/Card.stx +51 -0
- package/resources/components/Dashboard/UI/ChartCard.stx +36 -0
- package/resources/components/Dashboard/UI/Checkbox.stx +74 -0
- package/resources/components/Dashboard/UI/ConfirmDialog.stx +74 -0
- package/resources/components/Dashboard/UI/DataTable.stx +45 -0
- package/resources/components/Dashboard/UI/Dropdown.stx +72 -0
- package/resources/components/Dashboard/UI/DropdownItem.stx +80 -0
- package/resources/components/Dashboard/UI/EmptyState.stx +50 -0
- package/resources/components/Dashboard/UI/FilterBar.stx +48 -0
- package/resources/components/Dashboard/UI/Input.stx +77 -0
- package/resources/components/Dashboard/UI/Modal.stx +75 -0
- package/resources/components/Dashboard/UI/PageHeader.stx +69 -0
- package/resources/components/Dashboard/UI/PageLayout.stx +84 -0
- package/resources/components/Dashboard/UI/Pagination.stx +126 -0
- package/resources/components/Dashboard/UI/QuickLinks.stx +31 -0
- package/resources/components/Dashboard/UI/RouterLink.stx +31 -0
- package/resources/components/Dashboard/UI/Select.stx +84 -0
- package/resources/components/Dashboard/UI/ServiceHealth.stx +38 -0
- package/resources/components/Dashboard/UI/StatsCard.stx +79 -0
- package/resources/components/Dashboard/UI/Table.stx +143 -0
- package/resources/components/Dashboard/UI/Tabs.stx +45 -0
- package/resources/components/Dashboard/UI/Textarea.stx +93 -0
- package/resources/components/Dashboard/UI/Toggle.stx +84 -0
- package/resources/components/Dashboard/UI/WindowControls.stx +135 -0
- package/resources/components/Dashboard/Widget.stx +89 -0
- package/resources/components/Dashboard/WindowControls.stx +119 -0
- package/resources/components/Dashboard/index.ts +106 -0
- package/resources/components/Docs/Demo/ComboboxCode.md +114 -0
- package/resources/components/Docs/Demo/ComboboxDemo.stx +91 -0
- package/resources/components/Docs/Demo/DialogCode.md +42 -0
- package/resources/components/Docs/Demo/DialogDemo.stx +76 -0
- package/resources/components/Docs/Demo/DocsPlayground.stx +39 -0
- package/resources/components/Docs/Demo/DropdownCode.md +109 -0
- package/resources/components/Docs/Demo/DropdownDemo.stx +82 -0
- package/resources/components/Docs/Demo/Hero.stx +100 -0
- package/resources/components/Docs/Demo/ListboxCode.md +87 -0
- package/resources/components/Docs/Demo/ListboxDemo.stx +59 -0
- package/resources/components/Docs/Demo/NotificationCode.md +173 -0
- package/resources/components/Docs/Demo/NotificationDemo.stx +99 -0
- package/resources/components/Docs/Demo/PopoverCode.md +161 -0
- package/resources/components/Docs/Demo/PopoverDemo.stx +96 -0
- package/resources/components/Docs/Demo/RadioGroupCode.md +98 -0
- package/resources/components/Docs/Demo/RadioGroupDemo.stx +53 -0
- package/resources/components/Docs/Demo/StepperCode.md +216 -0
- package/resources/components/Docs/Demo/StepperDemo.stx +137 -0
- package/resources/components/Docs/Demo/SwitchCode.md +24 -0
- package/resources/components/Docs/Demo/SwitchDemo.stx +28 -0
- package/resources/components/Docs/Home.stx +7 -0
- package/resources/components/Docs/HomeContributors.stx +23 -0
- package/resources/components/Docs/HomeSponsors.stx +17 -0
- package/resources/components/Docs/HomeTeam.stx +18 -0
- package/resources/components/Docs/TeamMember.stx +79 -0
- package/resources/components/Email/EmailButton.stx +32 -0
- package/resources/components/Email/EmailDivider.stx +20 -0
- package/resources/components/Email/EmailImage.stx +24 -0
- package/resources/components/Email/EmailLayout.stx +55 -0
- package/resources/components/Email/EmailLink.stx +22 -0
- package/resources/components/Email/EmailSection.stx +20 -0
- package/resources/components/Email/EmailText.stx +30 -0
- package/resources/components/Forum/ForumBreadcrumb.stx +38 -0
- package/resources/components/Forum/ForumCategory.stx +16 -0
- package/resources/components/Forum/ForumCategoryItem.stx +46 -0
- package/resources/components/Forum/ForumLayout.stx +36 -0
- package/resources/components/Forum/ForumPagination.stx +39 -0
- package/resources/components/Forum/ForumPost.stx +71 -0
- package/resources/components/Forum/ForumReplyForm.stx +76 -0
- package/resources/components/Forum/ForumSidebar.stx +86 -0
- package/resources/components/Forum/ForumTopicItem.stx +77 -0
- package/resources/components/Forum/ForumTopicList.stx +23 -0
- package/resources/components/HelloWorld.stx +253 -0
- package/resources/components/Logo.stx +10 -0
- package/resources/components/Marketing/CallToAction.stx +30 -0
- package/resources/components/Marketing/ComingSoon.stx +155 -0
- package/resources/components/Marketing/Faqs.stx +99 -0
- package/resources/components/Marketing/Feature.stx +32 -0
- package/resources/components/Marketing/Fields.stx +28 -0
- package/resources/components/Marketing/Footer.stx +33 -0
- package/resources/components/Marketing/Header.stx +51 -0
- package/resources/components/Marketing/Hero.stx +46 -0
- package/resources/components/Marketing/Layout.stx +26 -0
- package/resources/components/Marketing/NavLink.stx +13 -0
- package/resources/components/Marketing/Plan.stx +43 -0
- package/resources/components/Marketing/Pricing.stx +120 -0
- package/resources/components/Marketing/PrimaryFeatures.stx +80 -0
- package/resources/components/Marketing/PrimaryFeatures2.stx +98 -0
- package/resources/components/Marketing/SecondaryFeatures.stx +80 -0
- package/resources/components/Marketing/Testimonials.stx +120 -0
- package/resources/components/Pagination.stx +149 -0
- package/resources/components/Playground.stx +9 -0
- package/resources/components/README.md +87 -0
- package/resources/components/Storefront/AnnouncementBar.stx +17 -0
- package/resources/components/Storefront/CartDrawer.stx +227 -0
- package/resources/components/Storefront/CheckoutSteps.stx +50 -0
- package/resources/components/Storefront/Footer.stx +81 -0
- package/resources/components/Storefront/Header.stx +66 -0
- package/resources/components/Storefront/OrderSummary.stx +79 -0
- package/resources/components/Storefront/ProductCard.stx +63 -0
- package/resources/components/Storefront/ProductGallery.stx +88 -0
- package/resources/components/Storefront/QuantitySelector.stx +97 -0
- package/resources/components/index.ts +13 -0
- package/resources/emails/email-verification.stx +46 -0
- package/resources/emails/layouts/base.html +113 -0
- package/resources/emails/password-changed.stx +55 -0
- package/resources/emails/password-reset.stx +43 -0
- package/resources/emails/subscription-confirmation.stx +99 -0
- package/resources/emails/welcome.stx +48 -0
- package/resources/functions/README.md +28 -0
- package/resources/functions/counter.ts +13 -0
- package/resources/functions/dark.ts +4 -0
- package/resources/functions/dashboard/analytics.ts +238 -0
- package/resources/functions/dashboard/config-io.ts +316 -0
- package/resources/functions/dashboard/data.ts +375 -0
- package/resources/functions/dashboard/library.ts +250 -0
- package/resources/functions/dashboard/sidebar.ts +537 -0
- package/resources/functions/dashboard/system.ts +150 -0
- package/resources/layouts/403.stx +188 -0
- package/resources/layouts/404.stx +34 -0
- package/resources/layouts/README.md +14 -0
- package/resources/layouts/dashboard/default.stx +20 -0
- package/resources/layouts/dashboard/guest.stx +10 -0
- package/resources/layouts/default.stx +3 -0
- package/resources/layouts/maintenance.stx +11 -0
- package/resources/layouts/storefront.stx +73 -0
- package/resources/layouts/system-tray/default.stx +3 -0
- package/resources/modules/.gitkeep +0 -0
- package/resources/plugins/.gitkeep +0 -0
- package/resources/plugins/preloader.ts +308 -0
- package/resources/types/README.md +3 -0
- package/resources/views/cart.stx +149 -0
- package/resources/views/checkout/contact.stx +101 -0
- package/resources/views/checkout/payment.stx +114 -0
- package/resources/views/checkout/shipping.stx +120 -0
- package/resources/views/coming-soon.stx +9 -0
- package/resources/views/dashboard/custom-page.stx +45 -0
- package/resources/views/dashboard/index.stx +24 -0
- package/resources/views/emails/welcome.stx +0 -0
- package/resources/views/errors/tester.stx +26 -0
- package/resources/views/index.stx +2865 -0
- 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,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>
|