@stacksjs/defaults 0.70.362 → 0.70.365
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/ai/skills/stacks-browse/SKILL.md +2 -1
- package/ai/skills/stacks-browse/scripts/browse.ts +20 -2
- package/ai/skills/stacks-dashboard/SKILL.md +4 -0
- package/app/Actions/Auth/LogoutAction.ts +11 -4
- package/app/Actions/Auth/LogoutAllAction.ts +8 -4
- package/app/Actions/Dashboard/Models/ModelShowAction.ts +4 -1
- package/app/Actions/Dashboard/Models/model-write.ts +5 -0
- package/ide/vscode/package.json +1 -1
- package/package.json +1 -1
- package/resources/components/Buttons/Counter.stx +1 -1
- package/resources/components/Buttons/ToggleDark.stx +1 -1
- package/resources/components/Dashboard/App/RequestDetailsDialog.stx +42 -0
- package/resources/components/Dashboard/App/RequestsOverview.stx +1 -21
- package/resources/components/Dashboard/Auth/AccessTokenCreateDialog.stx +155 -0
- package/resources/components/Dashboard/Auth/AccessTokens.stx +41 -129
- package/resources/components/Dashboard/Ci/CiDashboard.stx +1 -157
- package/resources/components/Dashboard/Ci/CiRunHistoryDrawer.stx +127 -0
- package/resources/components/Dashboard/Commerce/CommerceCategoryDeleteDialog.stx +10 -8
- package/resources/components/Dashboard/Commerce/CommerceCategoryDetailsDialog.stx +22 -17
- package/resources/components/Dashboard/Commerce/CommerceCategoryDialog.stx +14 -13
- package/resources/components/Dashboard/Commerce/CommerceCouponDeleteDialog.stx +10 -7
- package/resources/components/Dashboard/Commerce/CommerceCouponDetailsDialog.stx +25 -19
- package/resources/components/Dashboard/Commerce/CommerceCouponDialog.stx +14 -11
- package/resources/components/Dashboard/Commerce/CommerceCustomerDeleteDialog.stx +10 -8
- package/resources/components/Dashboard/Commerce/CommerceCustomerDetailsDialog.stx +24 -16
- package/resources/components/Dashboard/Commerce/CommerceCustomerDialog.stx +14 -13
- package/resources/components/Dashboard/Commerce/CommerceGiftCardDeleteDialog.stx +10 -8
- package/resources/components/Dashboard/Commerce/CommerceGiftCardDetailsDialog.stx +16 -14
- package/resources/components/Dashboard/Commerce/CommerceGiftCardDialog.stx +17 -16
- package/resources/components/Dashboard/Commerce/CommerceManufacturerDeleteDialog.stx +14 -16
- package/resources/components/Dashboard/Commerce/CommerceManufacturerDialog.stx +17 -16
- package/resources/components/Dashboard/Commerce/CommerceOrderDeleteDialog.stx +10 -8
- package/resources/components/Dashboard/Commerce/CommerceOrderDetailsDialog.stx +15 -10
- package/resources/components/Dashboard/Commerce/CommerceOrderDialog.stx +14 -13
- package/resources/components/Dashboard/Commerce/CommercePosCheckoutDialog.stx +30 -25
- package/resources/components/Dashboard/Commerce/CommercePosReceiptDialog.stx +27 -20
- package/resources/components/Dashboard/Commerce/CommerceProductDeleteDialog.stx +14 -14
- package/resources/components/Dashboard/Commerce/CommerceProductDialog.stx +14 -13
- package/resources/components/Dashboard/Commerce/CommerceReviewDeleteDialog.stx +10 -18
- package/resources/components/Dashboard/Commerce/CommerceReviewEditDialog.stx +17 -16
- package/resources/components/Dashboard/Commerce/CommerceTaxDeleteDialog.stx +14 -14
- package/resources/components/Dashboard/Commerce/CommerceTaxDialog.stx +17 -16
- package/resources/components/Dashboard/Commerce/CommerceTaxesTable.stx +1 -1
- package/resources/components/Dashboard/Commerce/CommerceUnitDeleteDialog.stx +14 -17
- package/resources/components/Dashboard/Commerce/CommerceUnitDialog.stx +17 -16
- package/resources/components/Dashboard/Commerce/CommerceVariantDeleteDialog.stx +10 -8
- package/resources/components/Dashboard/Commerce/CommerceVariantDialog.stx +17 -16
- package/resources/components/Dashboard/Commerce/Delivery/DeliveryRouteDeleteDialog.stx +11 -15
- package/resources/components/Dashboard/Commerce/Delivery/DeliveryRouteDialog.stx +17 -16
- package/resources/components/Dashboard/Commerce/Delivery/DigitalDeliveryDeleteDialog.stx +11 -15
- package/resources/components/Dashboard/Commerce/Delivery/DigitalDeliveryDialog.stx +17 -16
- package/resources/components/Dashboard/Commerce/Delivery/DriverDeleteDialog.stx +11 -15
- package/resources/components/Dashboard/Commerce/Delivery/DriverDialog.stx +17 -16
- package/resources/components/Dashboard/Commerce/Delivery/LicenseKeyDeleteDialog.stx +11 -15
- package/resources/components/Dashboard/Commerce/Delivery/LicenseKeyDialog.stx +17 -16
- package/resources/components/Dashboard/Commerce/Delivery/ShippingMethodDeleteDialog.stx +11 -15
- package/resources/components/Dashboard/Commerce/Delivery/ShippingMethodDialog.stx +17 -16
- package/resources/components/Dashboard/Commerce/Delivery/ShippingRateDeleteDialog.stx +11 -15
- package/resources/components/Dashboard/Commerce/Delivery/ShippingRateDialog.stx +17 -16
- package/resources/components/Dashboard/Commerce/Delivery/ShippingZoneDeleteDialog.stx +11 -15
- package/resources/components/Dashboard/Commerce/Delivery/ShippingZoneDialog.stx +17 -16
- package/resources/components/Dashboard/Commerce/PaymentDetailsDialog.stx +16 -15
- package/resources/components/Dashboard/Commerce/PaymentRefundDialog.stx +16 -15
- package/resources/components/Dashboard/Commerce/PrintDeviceDeleteDialog.stx +10 -11
- package/resources/components/Dashboard/Commerce/PrintDeviceDetailsDialog.stx +16 -14
- package/resources/components/Dashboard/Commerce/PrintDeviceDialog.stx +17 -16
- package/resources/components/Dashboard/Commerce/PrintLogDeleteDialog.stx +10 -7
- package/resources/components/Dashboard/Commerce/PrintLogDetailsDialog.stx +13 -10
- package/resources/components/Dashboard/Commerce/ProductWaitlistDeleteDialog.stx +10 -18
- package/resources/components/Dashboard/Commerce/ProductWaitlistEntryDialog.stx +96 -105
- package/resources/components/Dashboard/Commerce/RestaurantWaitlistDeleteDialog.stx +10 -18
- package/resources/components/Dashboard/Commerce/RestaurantWaitlistEntryDialog.stx +92 -95
- package/resources/components/Dashboard/Content/AuthorEditorDialog.stx +94 -0
- package/resources/components/Dashboard/Content/AuthorsDashboard.stx +39 -31
- package/resources/components/Dashboard/Content/BlogDashboard.stx +87 -176
- package/resources/components/Dashboard/Content/BlogPostEditorDialog.stx +195 -0
- package/resources/components/Dashboard/Content/CommentsDashboard.stx +14 -4
- package/resources/components/Dashboard/Content/ContentTaxonomyDashboard.stx +40 -55
- package/resources/components/Dashboard/Content/CreateFolderDialog.stx +45 -0
- package/resources/components/Dashboard/Content/FileDetailsDrawer.stx +31 -0
- package/resources/components/Dashboard/Content/FileManagerDashboard.stx +47 -107
- package/resources/components/Dashboard/Content/FileUploadDialog.stx +89 -0
- package/resources/components/Dashboard/Content/PageEditorDialog.stx +93 -0
- package/resources/components/Dashboard/Content/PagesDashboard.stx +36 -26
- package/resources/components/Dashboard/Content/PostEditorDialog.stx +176 -0
- package/resources/components/Dashboard/Content/PostsDashboard.stx +40 -64
- package/resources/components/Dashboard/Content/SeoDashboard.stx +18 -84
- package/resources/components/Dashboard/Content/SeoEditorDialog.stx +108 -0
- package/resources/components/Dashboard/Content/TaxonomyEditorDialog.stx +106 -0
- package/resources/components/Dashboard/CreateRecordModal.stx +72 -83
- package/resources/components/Dashboard/Email/InboxMessageList.stx +1 -1
- package/resources/components/Dashboard/GlobalSearch.stx +3 -9
- package/resources/components/Dashboard/Infrastructure/CloudDetailsDialog.stx +2 -16
- package/resources/components/Dashboard/Infrastructure/DnsRecordDialog.stx +4 -16
- package/resources/components/Dashboard/Infrastructure/LogDetailsDialog.stx +4 -19
- package/resources/components/Dashboard/Infrastructure/MailboxDetailsDialog.stx +6 -16
- package/resources/components/Dashboard/Infrastructure/ServerInspectorDialog.stx +105 -0
- package/resources/components/Dashboard/Infrastructure/ServersDashboard.stx +5 -59
- package/resources/components/Dashboard/Jobs/JobHistory.stx +1 -11
- package/resources/components/Dashboard/Library/ComponentsDashboard.stx +11 -60
- package/resources/components/Dashboard/Library/FunctionsDashboard.stx +11 -15
- package/resources/components/Dashboard/Library/SourceScaffoldDialog.stx +95 -0
- package/resources/components/Dashboard/Management/AssignmentDrawer.stx +93 -0
- package/resources/components/Dashboard/Management/PermissionsDashboard.stx +47 -129
- package/resources/components/Dashboard/Marketing/CampaignDeliveryDialog.stx +5 -8
- package/resources/components/Dashboard/Marketing/CampaignDialog.stx +17 -17
- package/resources/components/Dashboard/Marketing/MarketingListDialog.stx +17 -17
- package/resources/components/Dashboard/Marketing/MarketingListsTable.stx +1 -1
- package/resources/components/Dashboard/Marketing/SocialPostDialog.stx +17 -16
- package/resources/components/Dashboard/Models/EditRecordModal.stx +81 -0
- package/resources/components/Dashboard/Models/ModelRecordActions.stx +30 -0
- package/resources/components/Dashboard/Models/ModelRecordsDashboard.stx +42 -94
- package/resources/components/Dashboard/Navbar.stx +5 -5
- package/resources/components/Dashboard/Notifications/NotificationDeliveryDialog.stx +40 -60
- package/resources/components/Dashboard/UI/Button.stx +4 -0
- package/resources/components/Dashboard/UI/ConfirmDialog.stx +4 -0
- package/resources/components/Dashboard/UI/Drawer.stx +114 -0
- package/resources/components/Dashboard/UI/Modal.stx +19 -12
- package/resources/components/Docs/Demo/ComboboxDemo.stx +4 -5
- package/resources/components/Docs/Demo/DropdownDemo.stx +12 -5
- package/resources/components/Docs/Demo/ListboxDemo.stx +14 -6
- package/resources/components/Docs/Demo/PopoverDemo.stx +10 -5
- package/resources/components/Docs/Demo/RadioGroupDemo.stx +14 -6
- package/resources/components/Docs/Demo/StepperDemo.stx +4 -5
- package/resources/components/Docs/TeamMember.stx +16 -9
- package/resources/components/Forum/ForumReplyForm.stx +7 -7
- package/resources/components/Forum/ForumSidebar.stx +10 -6
- package/resources/components/Marketing/Faqs.stx +5 -5
- package/resources/components/Marketing/Feature.stx +11 -6
- package/resources/components/Marketing/Layout.stx +12 -8
- package/resources/components/Marketing/Pricing.stx +11 -5
- package/resources/components/Marketing/PrimaryFeatures.stx +4 -5
- package/resources/components/Marketing/PrimaryFeatures2.stx +6 -5
- package/resources/components/Marketing/SecondaryFeatures.stx +10 -5
- package/resources/components/Marketing/Testimonials.stx +8 -5
- package/resources/views/index.stx +4 -4
- package/views/system-tray/index.stx +1 -1
|
@@ -47,12 +47,17 @@ function deleteRecord(): void {
|
|
|
47
47
|
}
|
|
48
48
|
</script>
|
|
49
49
|
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
50
|
+
<Modal
|
|
51
|
+
:isOpen="open()"
|
|
52
|
+
:title="`Order ${record()?.id || 'not recorded'}`"
|
|
53
|
+
:description="record()?.customerName || 'Unassigned customer'"
|
|
54
|
+
size="lg"
|
|
55
|
+
@close="emit('close')"
|
|
56
|
+
>
|
|
57
|
+
<template #header-trailing>
|
|
58
|
+
<span class="px-2 py-1 font-semibold text-gray-700 text-xs dark:text-neutral-200 bg-gray-100 dark:bg-neutral-700 rounded-full">{{ label(record()?.status || 'UNKNOWN') }}</span>
|
|
59
|
+
</template>
|
|
60
|
+
<dl class="grid gap-4 grid-cols-2">
|
|
56
61
|
<div><dt class="text-gray-400 text-xs dark:text-neutral-500">Total</dt><dd class="mt-1 font-semibold text-gray-900 text-sm dark:text-white">{{ formatMoney(record()?.totalAmount || 0, record()?.currency || 'USD') }}</dd></div>
|
|
57
62
|
<div><dt class="text-gray-400 text-xs dark:text-neutral-500">Order type</dt><dd class="mt-1 text-gray-900 text-sm dark:text-white">{{ label(record()?.orderType || 'UNKNOWN') }}</dd></div>
|
|
58
63
|
<div><dt class="text-gray-400 text-xs dark:text-neutral-500">Items</dt><dd class="mt-1 text-gray-900 text-sm dark:text-white">{{ record()?.itemCount || 0 }}</dd></div>
|
|
@@ -67,7 +72,7 @@ function deleteRecord(): void {
|
|
|
67
72
|
<div><dt class="text-gray-400 text-xs dark:text-neutral-500">Coupon relation ID</dt><dd class="mt-1 font-mono text-gray-900 text-sm dark:text-white">{{ record()?.couponId || 'Not linked' }}</dd></div>
|
|
68
73
|
<div><dt class="text-gray-400 text-xs dark:text-neutral-500">Applied coupon reference</dt><dd class="mt-1 font-mono text-gray-900 text-sm dark:text-white">{{ record()?.appliedCouponId || 'Not linked' }}</dd></div>
|
|
69
74
|
</dl>
|
|
70
|
-
|
|
71
|
-
<
|
|
72
|
-
</
|
|
73
|
-
</
|
|
75
|
+
<template #footer>
|
|
76
|
+
<div class="flex gap-2 justify-between w-full"><Button variant="danger" @click="deleteRecord()">Delete</Button><div class="flex gap-2"><Button variant="secondary" @click="emit('close')">Close</Button><Button @click="editRecord()">Edit order</Button></div></div>
|
|
77
|
+
</template>
|
|
78
|
+
</Modal>
|
|
@@ -107,17 +107,18 @@ function errorMessages(): string[] {
|
|
|
107
107
|
}
|
|
108
108
|
</script>
|
|
109
109
|
|
|
110
|
-
<
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
110
|
+
<Modal
|
|
111
|
+
:isOpen="open()"
|
|
112
|
+
:title="mode() === 'edit' ? 'Edit order' : 'Add order'"
|
|
113
|
+
description="Store fields and relationships declared by the native Order model."
|
|
114
|
+
size="xl"
|
|
115
|
+
@close="emit('close')"
|
|
116
|
+
>
|
|
117
|
+
<form id="order-form" @submit.prevent="submit">
|
|
118
|
+
<ul :if="errorMessages().length > 0" class="mb-5 p-3 space-y-1 text-red-700 text-sm dark:text-red-300 bg-red-50 dark:bg-red-950/30 border border-red-200 rounded-lg dark:border-red-900">
|
|
118
119
|
<template :for="message in errorMessages()" :key="message"><li>{{ message }}</li></template>
|
|
119
120
|
</ul>
|
|
120
|
-
<div class="grid gap-4 grid-cols-1 sm:grid-cols-2
|
|
121
|
+
<div class="grid gap-4 grid-cols-1 sm:grid-cols-2">
|
|
121
122
|
<label class="block"><span class="font-medium text-gray-700 text-sm dark:text-neutral-200">Customer</span><select x-model="customerId" class="mt-1 px-3 py-2 w-full text-gray-900 text-sm dark:text-white bg-white dark:bg-neutral-900 border border-gray-300 rounded-md dark:border-neutral-700"><option value="">Unassigned customer</option><template :for="option in customers()" :key="option.id"><option :value="option.id">{{ option.label }}</option></template></select></label>
|
|
122
123
|
<label class="block"><span class="font-medium text-gray-700 text-sm dark:text-neutral-200">Status</span><select x-model="status" required class="mt-1 px-3 py-2 w-full text-gray-900 text-sm dark:text-white bg-white dark:bg-neutral-900 border border-gray-300 rounded-md dark:border-neutral-700"><template :for="option in statuses()" :key="option"><option :value="option">{{ label(option) }}</option></template></select></label>
|
|
123
124
|
<label class="block"><span class="font-medium text-gray-700 text-sm dark:text-neutral-200">Order type</span><select x-model="orderType" required class="mt-1 px-3 py-2 w-full text-gray-900 text-sm dark:text-white bg-white dark:bg-neutral-900 border border-gray-300 rounded-md dark:border-neutral-700"><template :for="option in orderTypes()" :key="option"><option :value="option">{{ label(option) }}</option></template></select></label>
|
|
@@ -133,8 +134,8 @@ function errorMessages(): string[] {
|
|
|
133
134
|
<label class="block sm:col-span-2"><span class="font-medium text-gray-700 text-sm dark:text-neutral-200">Delivery address</span><textarea x-model="deliveryAddress" rows="3" class="mt-1 px-3 py-2 w-full text-gray-900 text-sm dark:text-white bg-white dark:bg-neutral-900 border border-gray-300 rounded-md dark:border-neutral-700"></textarea></label>
|
|
134
135
|
<label class="block sm:col-span-2"><span class="font-medium text-gray-700 text-sm dark:text-neutral-200">Special instructions</span><textarea x-model="specialInstructions" rows="3" class="mt-1 px-3 py-2 w-full text-gray-900 text-sm dark:text-white bg-white dark:bg-neutral-900 border border-gray-300 rounded-md dark:border-neutral-700"></textarea></label>
|
|
135
136
|
</div>
|
|
136
|
-
</div>
|
|
137
|
-
<footer class="flex gap-2 justify-end px-6 py-4 bg-gray-50 dark:bg-neutral-900/50 border-gray-200 border-t dark:border-neutral-700"><Button variant="secondary" :disabled="busy()" @click="emit('close')">Cancel</Button><Button type="submit" :loading="busy()" :disabled="!valid()">{{ mode() === 'edit' ? 'Save order' : 'Add order' }}</Button></footer>
|
|
138
137
|
</form>
|
|
139
|
-
|
|
140
|
-
</div>
|
|
138
|
+
<template #footer>
|
|
139
|
+
<div class="flex gap-2 justify-end w-full"><Button variant="secondary" :disabled="busy()" @click="emit('close')">Cancel</Button><Button type="submit" form="order-form" :loading="busy()" :disabled="!valid()">{{ mode() === 'edit' ? 'Save order' : 'Add order' }}</Button></div>
|
|
140
|
+
</template>
|
|
141
|
+
</Modal>
|
|
@@ -56,30 +56,35 @@ function submit(): void {
|
|
|
56
56
|
}
|
|
57
57
|
</script>
|
|
58
58
|
|
|
59
|
-
<
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
59
|
+
<Modal
|
|
60
|
+
:isOpen="open()"
|
|
61
|
+
title="Review cash sale"
|
|
62
|
+
description="The server will recompute prices and tax before the atomic write."
|
|
63
|
+
:closable="!busy()"
|
|
64
|
+
@close="emit('close')"
|
|
65
|
+
>
|
|
66
|
+
<form id="pos-checkout-form" @submit.prevent="submit">
|
|
67
|
+
<div :if="error()" class="mb-4 p-3 text-red-700 text-sm dark:text-red-300 bg-red-50 dark:bg-red-950/30 border border-red-200 rounded-lg dark:border-red-900">{{ error() }}</div>
|
|
67
68
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
69
|
+
<div class="grid gap-4 grid-cols-1 sm:grid-cols-2">
|
|
70
|
+
<label class="block sm:col-span-2"><span class="font-medium text-gray-700 text-sm dark:text-neutral-200">Customer</span><select x-model="customerId" class="mt-1 px-3 py-2 w-full text-gray-900 text-sm dark:text-white bg-white dark:bg-neutral-900 border border-gray-300 rounded-md dark:border-neutral-700"><option value="">Guest sale</option><template :for="customer in customers()" :key="customer.id"><option :value="customer.id">{{ customer.label }}{{ customer.email ? ' · ' + customer.email : '' }}</option></template></select></label>
|
|
71
|
+
<label class="block"><span class="font-medium text-gray-700 text-sm dark:text-neutral-200">Order type</span><select x-model="orderType" class="mt-1 px-3 py-2 w-full text-gray-900 text-sm dark:text-white bg-white dark:bg-neutral-900 border border-gray-300 rounded-md dark:border-neutral-700"><option value="TAKEOUT">Takeout</option><option value="DINE_IN">Dine in</option></select></label>
|
|
72
|
+
<label class="block"><span class="font-medium text-gray-700 text-sm dark:text-neutral-200">Payment</span><select x-model="paymentMethod" class="mt-1 px-3 py-2 w-full text-gray-900 text-sm dark:text-white bg-white dark:bg-neutral-900 border border-gray-300 rounded-md dark:border-neutral-700"><template :for="method in paymentMethods()" :key="method.id"><option :value="method.id">{{ method.label }}</option></template></select></label>
|
|
73
|
+
<label class="block sm:col-span-2"><span class="font-medium text-gray-700 text-sm dark:text-neutral-200">Order instructions</span><textarea x-model="specialInstructions" rows="3" maxlength="1000" placeholder="Optional instructions for the whole sale" class="mt-1 px-3 py-2 w-full text-gray-900 text-sm dark:text-white bg-white dark:bg-neutral-900 border border-gray-300 rounded-md dark:border-neutral-700"></textarea></label>
|
|
74
|
+
</div>
|
|
74
75
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
</
|
|
76
|
+
<dl class="mt-5 p-4 space-y-2 bg-gray-50 dark:bg-neutral-900/60 rounded-lg">
|
|
77
|
+
<div class="flex items-center justify-between text-gray-500 text-sm dark:text-neutral-400"><dt>Units</dt><dd>{{ unitCount() }}</dd></div>
|
|
78
|
+
<div class="flex items-center justify-between text-gray-500 text-sm dark:text-neutral-400"><dt>Subtotal</dt><dd>{{ formatMoney(subtotal()) }}</dd></div>
|
|
79
|
+
<div class="flex items-center justify-between text-gray-500 text-sm dark:text-neutral-400"><dt>Tax</dt><dd>{{ formatMoney(taxAmount()) }}</dd></div>
|
|
80
|
+
<div class="flex items-center justify-between pt-2 font-semibold text-gray-900 dark:text-white border-gray-200 border-t dark:border-neutral-700"><dt>Cash due</dt><dd>{{ formatMoney(totalAmount()) }}</dd></div>
|
|
81
|
+
</dl>
|
|
82
|
+
</form>
|
|
83
|
+
|
|
84
|
+
<template #footer>
|
|
85
|
+
<div class="flex gap-2 justify-end w-full">
|
|
86
|
+
<Button variant="secondary" :disabled="busy()" @click="emit('close')">Cancel</Button>
|
|
87
|
+
<Button type="submit" form="pos-checkout-form" :loading="busy()">Complete sale</Button>
|
|
88
|
+
</div>
|
|
89
|
+
</template>
|
|
90
|
+
</Modal>
|
|
@@ -44,25 +44,32 @@ function formatDate(value: string): string {
|
|
|
44
44
|
}
|
|
45
45
|
</script>
|
|
46
46
|
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
47
|
+
<Modal
|
|
48
|
+
:isOpen="open() && Boolean(receipt())"
|
|
49
|
+
title="Sale recorded"
|
|
50
|
+
:description="`Order ${receipt()?.orderId || ''} · ${formatDate(receipt()?.createdAt || '')}`"
|
|
51
|
+
size="sm"
|
|
52
|
+
@close="emit('close')"
|
|
53
|
+
>
|
|
54
|
+
<template #header-leading>
|
|
55
|
+
<div class="flex flex-shrink-0 items-center justify-center h-11 w-11 text-green-700 dark:text-green-300 bg-green-50 dark:bg-green-950/40 rounded-full">
|
|
56
|
+
<span class="h-6 w-6 i-hugeicons-checkmark-circle-02"></span>
|
|
57
|
+
</div>
|
|
58
|
+
</template>
|
|
55
59
|
|
|
56
|
-
|
|
57
|
-
<template :for="line in (receipt()?.lines || [])" :key="line.productId"><li class="py-3"><div class="flex gap-3 items-start justify-between"><div><p class="font-medium text-gray-900 text-sm dark:text-white">{{ line.quantity }} × {{ line.name }}</p><p :if="line.specialInstructions" class="mt-1 text-gray-500 text-xs dark:text-neutral-400">{{ line.specialInstructions }}</p></div><p class="font-medium text-gray-700 text-sm whitespace-nowrap dark:text-neutral-200">{{ formatMoney(line.lineTotal) }}</p></div></li></template>
|
|
58
|
-
</ul>
|
|
60
|
+
<p :if="receipt()?.referenceNumber" class="font-mono text-gray-400 text-xs dark:text-neutral-500">{{ receipt()?.referenceNumber }}</p>
|
|
59
61
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
</div>
|
|
66
|
-
<
|
|
67
|
-
|
|
68
|
-
</
|
|
62
|
+
<ul class="mt-5 divide-gray-100 divide-y dark:divide-neutral-700">
|
|
63
|
+
<template :for="line in (receipt()?.lines || [])" :key="line.productId"><li class="py-3"><div class="flex gap-3 items-start justify-between"><div><p class="font-medium text-gray-900 text-sm dark:text-white">{{ line.quantity }} × {{ line.name }}</p><p :if="line.specialInstructions" class="mt-1 text-gray-500 text-xs dark:text-neutral-400">{{ line.specialInstructions }}</p></div><p class="font-medium text-gray-700 text-sm whitespace-nowrap dark:text-neutral-200">{{ formatMoney(line.lineTotal) }}</p></div></li></template>
|
|
64
|
+
</ul>
|
|
65
|
+
|
|
66
|
+
<dl class="mt-4 p-4 space-y-2 bg-gray-50 dark:bg-neutral-900/60 rounded-lg">
|
|
67
|
+
<div class="flex items-center justify-between text-gray-500 text-sm dark:text-neutral-400"><dt>Subtotal</dt><dd>{{ formatMoney(receipt()?.subtotal || 0) }}</dd></div>
|
|
68
|
+
<div class="flex items-center justify-between text-gray-500 text-sm dark:text-neutral-400"><dt>Tax<span :if="receipt()?.taxRate"> ({{ receipt()?.taxRate }}%)</span></dt><dd>{{ formatMoney(receipt()?.taxAmount || 0) }}</dd></div>
|
|
69
|
+
<div class="flex items-center justify-between pt-2 font-semibold text-gray-900 dark:text-white border-gray-200 border-t dark:border-neutral-700"><dt>Cash paid</dt><dd>{{ formatMoney(receipt()?.totalAmount || 0) }}</dd></div>
|
|
70
|
+
</dl>
|
|
71
|
+
|
|
72
|
+
<template #footer>
|
|
73
|
+
<Button @click="emit('close')">Start next sale</Button>
|
|
74
|
+
</template>
|
|
75
|
+
</Modal>
|
|
@@ -5,19 +5,19 @@ const open = useReactiveProp('open', false)
|
|
|
5
5
|
const record = useReactiveProp('record', null as CommerceProductRecord | null)
|
|
6
6
|
const busy = useReactiveProp('busy', false)
|
|
7
7
|
const emit = defineEmits()
|
|
8
|
+
const description = derived(() => `Delete "${record()?.name || 'Unnamed product'}" permanently?`)
|
|
9
|
+
const warning = derived(() => record()?.variantCount || record()?.unitCount || record()?.reviewCount
|
|
10
|
+
? 'Related variants, units, or reviews may cause deletion to be rejected.'
|
|
11
|
+
: '')
|
|
8
12
|
</script>
|
|
9
13
|
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
<Button variant="danger" :loading="busy()" @click="emit('confirm')">Delete product</Button>
|
|
21
|
-
</footer>
|
|
22
|
-
</section>
|
|
23
|
-
</div>
|
|
14
|
+
<ConfirmDialog
|
|
15
|
+
:isOpen="open()"
|
|
16
|
+
title="Delete product"
|
|
17
|
+
:description="description()"
|
|
18
|
+
:warning="warning()"
|
|
19
|
+
confirmLabel="Delete product"
|
|
20
|
+
:busy="busy()"
|
|
21
|
+
@close="emit('close')"
|
|
22
|
+
@confirm="emit('confirm')"
|
|
23
|
+
/>
|
|
@@ -107,17 +107,18 @@ function errorMessages(): string[] {
|
|
|
107
107
|
}
|
|
108
108
|
</script>
|
|
109
109
|
|
|
110
|
-
<
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
110
|
+
<Modal
|
|
111
|
+
:isOpen="open()"
|
|
112
|
+
:title="mode() === 'edit' ? 'Edit product' : 'Add product'"
|
|
113
|
+
description="Store fields and belongs-to relationships declared by the native Product model."
|
|
114
|
+
size="xl"
|
|
115
|
+
@close="emit('close')"
|
|
116
|
+
>
|
|
117
|
+
<form id="product-form" @submit.prevent="submit">
|
|
118
|
+
<ul :if="errorMessages().length > 0" class="mb-5 p-3 space-y-1 text-red-700 text-sm dark:text-red-300 bg-red-50 dark:bg-red-950/30 border border-red-200 rounded-lg dark:border-red-900">
|
|
118
119
|
<template :for="message in errorMessages()" :key="message"><li>{{ message }}</li></template>
|
|
119
120
|
</ul>
|
|
120
|
-
<div class="grid gap-4 grid-cols-1 sm:grid-cols-2
|
|
121
|
+
<div class="grid gap-4 grid-cols-1 sm:grid-cols-2">
|
|
121
122
|
<label class="block sm:col-span-2"><span class="font-medium text-gray-700 text-sm dark:text-neutral-200">Name</span><input x-model="name" type="text" maxlength="100" required class="mt-1 px-3 py-2 w-full text-gray-900 text-sm dark:text-white bg-white dark:bg-neutral-900 border border-gray-300 rounded-md dark:border-neutral-700" /></label>
|
|
122
123
|
<label class="block sm:col-span-2"><span class="font-medium text-gray-700 text-sm dark:text-neutral-200">Description</span><textarea x-model="description" rows="3" class="mt-1 px-3 py-2 w-full text-gray-900 text-sm dark:text-white bg-white dark:bg-neutral-900 border border-gray-300 rounded-md dark:border-neutral-700"></textarea></label>
|
|
123
124
|
<label class="block"><span class="font-medium text-gray-700 text-sm dark:text-neutral-200">Price ({{ currency() }})</span><input x-model="price" type="number" min="1" step="0.01" required class="mt-1 px-3 py-2 w-full text-gray-900 text-sm dark:text-white bg-white dark:bg-neutral-900 border border-gray-300 rounded-md dark:border-neutral-700" /></label>
|
|
@@ -130,8 +131,8 @@ function errorMessages(): string[] {
|
|
|
130
131
|
<label class="block sm:col-span-2"><span class="font-medium text-gray-700 text-sm dark:text-neutral-200">Allergens</span><input x-model="allergens" type="text" placeholder="Comma-separated, for example: Gluten, Soy" class="mt-1 px-3 py-2 w-full text-gray-900 text-sm dark:text-white bg-white dark:bg-neutral-900 border border-gray-300 rounded-md dark:border-neutral-700" /></label>
|
|
131
132
|
<label class="block sm:col-span-2"><span class="font-medium text-gray-700 text-sm dark:text-neutral-200">Nutritional information (JSON object)</span><textarea x-model="nutritionalInfo" rows="4" spellcheck="false" :aria-invalid="!nutritionValid()" class="mt-1 px-3 py-2 w-full font-mono text-gray-900 text-sm dark:text-white bg-white dark:bg-neutral-900 border border-gray-300 rounded-md dark:border-neutral-700"></textarea><span :if="!nutritionValid()" class="block mt-1 text-red-600 text-xs dark:text-red-400">Enter a valid JSON object.</span></label>
|
|
132
133
|
</div>
|
|
133
|
-
</div>
|
|
134
|
-
<footer class="flex gap-2 justify-end px-6 py-4 bg-gray-50 dark:bg-neutral-900/50 border-gray-200 border-t dark:border-neutral-700"><Button variant="secondary" :disabled="busy()" @click="emit('close')">Cancel</Button><Button type="submit" :loading="busy()" :disabled="!valid()">{{ mode() === 'edit' ? 'Save product' : 'Add product' }}</Button></footer>
|
|
135
134
|
</form>
|
|
136
|
-
|
|
137
|
-
</div>
|
|
135
|
+
<template #footer>
|
|
136
|
+
<div class="flex gap-2 justify-end w-full"><Button variant="secondary" :disabled="busy()" @click="emit('close')">Cancel</Button><Button type="submit" form="product-form" :loading="busy()" :disabled="!valid()">{{ mode() === 'edit' ? 'Save product' : 'Add product' }}</Button></div>
|
|
137
|
+
</template>
|
|
138
|
+
</Modal>
|
|
@@ -5,23 +5,15 @@ const open = useReactiveProp('open', false)
|
|
|
5
5
|
const review = useReactiveProp('review', null as ReviewRecord | null)
|
|
6
6
|
const busy = useReactiveProp('busy', false)
|
|
7
7
|
const emit = defineEmits()
|
|
8
|
+
const description = derived(() => `Delete "${review()?.title || 'Untitled review'}" permanently? This cannot be undone.`)
|
|
8
9
|
</script>
|
|
9
10
|
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
<p class="mt-2 text-gray-500 text-sm dark:text-neutral-400">Delete "{{ review()?.title || 'Untitled review' }}" permanently? This cannot be undone.</p>
|
|
20
|
-
</div>
|
|
21
|
-
</div>
|
|
22
|
-
<footer class="flex gap-2 justify-end mt-6">
|
|
23
|
-
<Button variant="secondary" :disabled="busy()" @click="emit('close')">Cancel</Button>
|
|
24
|
-
<Button variant="danger" :loading="busy()" @click="emit('confirm')">Delete review</Button>
|
|
25
|
-
</footer>
|
|
26
|
-
</section>
|
|
27
|
-
</div>
|
|
11
|
+
<ConfirmDialog
|
|
12
|
+
:isOpen="open()"
|
|
13
|
+
title="Delete review"
|
|
14
|
+
:description="description()"
|
|
15
|
+
confirmLabel="Delete review"
|
|
16
|
+
:busy="busy()"
|
|
17
|
+
@close="emit('close')"
|
|
18
|
+
@confirm="emit('confirm')"
|
|
19
|
+
/>
|
|
@@ -49,18 +49,19 @@ function errorMessages(): string[] {
|
|
|
49
49
|
}
|
|
50
50
|
</script>
|
|
51
51
|
|
|
52
|
-
<
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
52
|
+
<Modal
|
|
53
|
+
:isOpen="open()"
|
|
54
|
+
title="Edit review"
|
|
55
|
+
:description="`${review()?.customerName || 'Unknown customer'} on ${review()?.productName || 'Unknown product'}`"
|
|
56
|
+
size="lg"
|
|
57
|
+
@close="emit('close')"
|
|
58
|
+
>
|
|
59
|
+
<form id="review-form" @submit.prevent="submit">
|
|
60
|
+
<ul :if="errorMessages().length > 0" class="mb-5 p-3 space-y-1 text-red-700 text-sm dark:text-red-300 bg-red-50 dark:bg-red-950/30 border border-red-200 rounded-lg dark:border-red-900">
|
|
60
61
|
<template :for="message in errorMessages()" :key="message"><li>{{ message }}</li></template>
|
|
61
62
|
</ul>
|
|
62
63
|
|
|
63
|
-
<div class="
|
|
64
|
+
<div class="space-y-4">
|
|
64
65
|
<label class="block">
|
|
65
66
|
<span class="font-medium text-gray-700 text-sm dark:text-neutral-200">Title</span>
|
|
66
67
|
<input x-model="title" type="text" maxlength="100" required class="mt-1 px-3 py-2 w-full text-gray-900 text-sm dark:text-white bg-white dark:bg-neutral-900 border border-gray-300 rounded-md dark:border-neutral-700" />
|
|
@@ -90,11 +91,11 @@ function errorMessages(): string[] {
|
|
|
90
91
|
</label>
|
|
91
92
|
</div>
|
|
92
93
|
</div>
|
|
93
|
-
</div>
|
|
94
|
-
<footer class="flex gap-2 justify-end px-6 py-4 bg-gray-50 dark:bg-neutral-900/50 border-gray-200 border-t dark:border-neutral-700">
|
|
95
|
-
<Button variant="secondary" :disabled="busy()" @click="emit('close')">Cancel</Button>
|
|
96
|
-
<Button type="submit" :loading="busy()" :disabled="!title().trim() || !content().trim()">Save review</Button>
|
|
97
|
-
</footer>
|
|
98
94
|
</form>
|
|
99
|
-
|
|
100
|
-
|
|
95
|
+
<template #footer>
|
|
96
|
+
<div class="flex gap-2 justify-end w-full">
|
|
97
|
+
<Button variant="secondary" :disabled="busy()" @click="emit('close')">Cancel</Button>
|
|
98
|
+
<Button type="submit" form="review-form" :loading="busy()" :disabled="!title().trim() || !content().trim()">Save review</Button>
|
|
99
|
+
</div>
|
|
100
|
+
</template>
|
|
101
|
+
</Modal>
|
|
@@ -5,19 +5,19 @@ const open = useReactiveProp('open', false)
|
|
|
5
5
|
const record = useReactiveProp('record', null as TaxRateRecord | null)
|
|
6
6
|
const busy = useReactiveProp('busy', false)
|
|
7
7
|
const emit = defineEmits()
|
|
8
|
+
const description = derived(() => `${record()?.name || 'This tax rate'} will be permanently removed.`)
|
|
9
|
+
const warning = derived(() => record()?.isDefault
|
|
10
|
+
? 'This rate is marked as default. No replacement is selected automatically.'
|
|
11
|
+
: '')
|
|
8
12
|
</script>
|
|
9
13
|
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
</Button>
|
|
21
|
-
</footer>
|
|
22
|
-
</section>
|
|
23
|
-
</div>
|
|
14
|
+
<ConfirmDialog
|
|
15
|
+
:isOpen="open()"
|
|
16
|
+
title="Delete tax rate?"
|
|
17
|
+
:description="description()"
|
|
18
|
+
:warning="warning()"
|
|
19
|
+
confirmLabel="Delete tax rate"
|
|
20
|
+
:busy="busy()"
|
|
21
|
+
@close="emit('close')"
|
|
22
|
+
@confirm="emit('confirm')"
|
|
23
|
+
/>
|
|
@@ -66,17 +66,18 @@ function errorMessages(): string[] {
|
|
|
66
66
|
}
|
|
67
67
|
</script>
|
|
68
68
|
|
|
69
|
-
<
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
69
|
+
<Modal
|
|
70
|
+
:isOpen="open()"
|
|
71
|
+
:title="mode() === 'edit' ? 'Edit tax rate' : 'Add tax rate'"
|
|
72
|
+
description="All fields follow the TaxRate model validation rules."
|
|
73
|
+
size="md"
|
|
74
|
+
@close="emit('close')"
|
|
75
|
+
>
|
|
76
|
+
<form id="tax-rate-form" @submit.prevent="submit">
|
|
77
|
+
<ul :if="errorMessages().length > 0" class="mb-5 p-3 space-y-1 text-red-700 text-sm dark:text-red-300 bg-red-50 dark:bg-red-950/30 border border-red-200 rounded-lg dark:border-red-900">
|
|
77
78
|
<template :for="message in errorMessages()" :key="message"><li>{{ message }}</li></template>
|
|
78
79
|
</ul>
|
|
79
|
-
<div class="
|
|
80
|
+
<div class="space-y-4">
|
|
80
81
|
<label class="block">
|
|
81
82
|
<span class="font-medium text-gray-700 text-sm dark:text-neutral-200">Name</span>
|
|
82
83
|
<input x-model="name" type="text" maxlength="255" required class="mt-1 px-3 py-2 w-full text-gray-900 text-sm dark:text-white bg-white dark:bg-neutral-900 border border-gray-300 rounded-md dark:border-neutral-700" />
|
|
@@ -136,13 +137,13 @@ function errorMessages(): string[] {
|
|
|
136
137
|
</span>
|
|
137
138
|
</label>
|
|
138
139
|
</div>
|
|
139
|
-
|
|
140
|
-
|
|
140
|
+
</form>
|
|
141
|
+
<template #footer>
|
|
142
|
+
<div class="flex gap-2 justify-end w-full">
|
|
141
143
|
<Button variant="secondary" :disabled="busy()" @click="emit('close')">Cancel</Button>
|
|
142
|
-
<Button type="submit" :loading="busy()" :disabled="!name().trim() || !type().trim() || !country().trim() || rate() < 0 || rate() > 100">
|
|
144
|
+
<Button type="submit" form="tax-rate-form" :loading="busy()" :disabled="!name().trim() || !type().trim() || !country().trim() || rate() < 0 || rate() > 100">
|
|
143
145
|
{{ mode() === 'edit' ? 'Save tax rate' : 'Add tax rate' }}
|
|
144
146
|
</Button>
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
</div>
|
|
147
|
+
</div>
|
|
148
|
+
</template>
|
|
149
|
+
</Modal>
|
|
@@ -49,7 +49,7 @@ function formatDate(value: string): string {
|
|
|
49
49
|
renaming the rate must not change the bill.
|
|
50
50
|
--}}
|
|
51
51
|
<span :if="record.code" class="px-2 py-0.5 font-mono text-gray-600 text-xs dark:text-neutral-300 bg-gray-100 dark:bg-neutral-700 rounded-full">{{ record.code }}</span>
|
|
52
|
-
<span :if="record.exemptible" class="px-2 py-0.5 font-medium text-amber-700 text-xs dark:text-amber-300 bg-amber-50 dark:bg-amber-950/40 rounded-full" title="Not charged to a customer who qualifies for an exemption">Exemptible</span>
|
|
52
|
+
<span :if="record.exemptible" class="px-2 py-0.5 font-medium text-amber-700 text-xs dark:text-amber-300 bg-amber-50 dark:bg-amber-950/40 rounded-full" x-tooltip="Not charged to a customer who qualifies for an exemption" title="Not charged to a customer who qualifies for an exemption">Exemptible</span>
|
|
53
53
|
</div>
|
|
54
54
|
<p class="mt-1 text-gray-500 text-xs dark:text-neutral-400">{{ record.type }}</p>
|
|
55
55
|
</td>
|
|
@@ -5,22 +5,19 @@ const open = useReactiveProp('open', false)
|
|
|
5
5
|
const record = useReactiveProp('record', null as ProductUnitRecord | null)
|
|
6
6
|
const busy = useReactiveProp('busy', false)
|
|
7
7
|
const emit = defineEmits()
|
|
8
|
+
const description = derived(() => `${record()?.name || 'This product unit'} will be permanently removed.${record()?.productName ? ` The linked product ${record()?.productName} will remain.` : ''}`)
|
|
9
|
+
const warning = derived(() => record()?.isDefault
|
|
10
|
+
? `This is the current default for ${record()?.type || 'this unit type'}. No replacement is selected automatically.`
|
|
11
|
+
: '')
|
|
8
12
|
</script>
|
|
9
13
|
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
<Button variant="secondary" :disabled="busy()" @click="emit('close')">Cancel</Button>
|
|
21
|
-
<Button variant="danger" :loading="busy()" @click="emit('confirm')">
|
|
22
|
-
Delete product unit
|
|
23
|
-
</Button>
|
|
24
|
-
</footer>
|
|
25
|
-
</section>
|
|
26
|
-
</div>
|
|
14
|
+
<ConfirmDialog
|
|
15
|
+
:isOpen="open()"
|
|
16
|
+
title="Delete product unit?"
|
|
17
|
+
:description="description()"
|
|
18
|
+
:warning="warning()"
|
|
19
|
+
confirmLabel="Delete product unit"
|
|
20
|
+
:busy="busy()"
|
|
21
|
+
@close="emit('close')"
|
|
22
|
+
@confirm="emit('confirm')"
|
|
23
|
+
/>
|
|
@@ -59,17 +59,18 @@ function errorMessages(): string[] {
|
|
|
59
59
|
}
|
|
60
60
|
</script>
|
|
61
61
|
|
|
62
|
-
<
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
62
|
+
<Modal
|
|
63
|
+
:isOpen="open()"
|
|
64
|
+
:title="mode() === 'edit' ? 'Edit product unit' : 'Add product unit'"
|
|
65
|
+
description="Fields and relationships come from the ProductUnit model."
|
|
66
|
+
size="md"
|
|
67
|
+
@close="emit('close')"
|
|
68
|
+
>
|
|
69
|
+
<form id="product-unit-form" @submit.prevent="submit">
|
|
70
|
+
<ul :if="errorMessages().length > 0" class="mb-5 p-3 space-y-1 text-red-700 text-sm dark:text-red-300 bg-red-50 dark:bg-red-950/30 border border-red-200 rounded-lg dark:border-red-900">
|
|
70
71
|
<template :for="message in errorMessages()" :key="message"><li>{{ message }}</li></template>
|
|
71
72
|
</ul>
|
|
72
|
-
<div class="
|
|
73
|
+
<div class="space-y-4">
|
|
73
74
|
<div class="grid gap-4 sm:grid-cols-2">
|
|
74
75
|
<label class="block">
|
|
75
76
|
<span class="font-medium text-gray-700 text-sm dark:text-neutral-200">Name</span>
|
|
@@ -110,13 +111,13 @@ function errorMessages(): string[] {
|
|
|
110
111
|
</span>
|
|
111
112
|
</label>
|
|
112
113
|
</div>
|
|
113
|
-
|
|
114
|
-
|
|
114
|
+
</form>
|
|
115
|
+
<template #footer>
|
|
116
|
+
<div class="flex gap-2 justify-end w-full">
|
|
115
117
|
<Button variant="secondary" :disabled="busy()" @click="emit('close')">Cancel</Button>
|
|
116
|
-
<Button type="submit" :loading="busy()" :disabled="!name().trim() || !abbreviation().trim() || !type().trim()">
|
|
118
|
+
<Button type="submit" form="product-unit-form" :loading="busy()" :disabled="!name().trim() || !abbreviation().trim() || !type().trim()">
|
|
117
119
|
{{ mode() === 'edit' ? 'Save product unit' : 'Add product unit' }}
|
|
118
120
|
</Button>
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
</div>
|
|
121
|
+
</div>
|
|
122
|
+
</template>
|
|
123
|
+
</Modal>
|