@stacksjs/defaults 0.75.231 → 0.75.233
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-native/CATALOG.md +4 -4
- package/ai/skills/stacks-storage/SKILL.md +43 -0
- package/ai/skills/stacks-testing/SKILL.md +38 -10
- package/functions/dashboard-form.test.ts +41 -0
- package/functions/dashboard-form.ts +30 -0
- package/functions/dashboard-list.test.ts +228 -0
- package/functions/dashboard-list.ts +257 -0
- package/ide/vscode/package.json +1 -1
- package/package.json +2 -2
- package/project/storage/framework/types/browser-composables.d.ts +56 -0
- package/resources/components/Dashboard/Commerce/CommerceCategoriesDashboard.stx +2 -7
- package/resources/components/Dashboard/Commerce/CommerceCategoryDialog.stx +2 -4
- package/resources/components/Dashboard/Commerce/CommerceCouponDialog.stx +2 -4
- package/resources/components/Dashboard/Commerce/CommerceCouponsDashboard.stx +2 -7
- package/resources/components/Dashboard/Commerce/CommerceCustomerDialog.stx +2 -4
- package/resources/components/Dashboard/Commerce/CommerceCustomersDashboard.stx +2 -7
- package/resources/components/Dashboard/Commerce/CommerceGiftCardDialog.stx +2 -4
- package/resources/components/Dashboard/Commerce/CommerceGiftCardsDashboard.stx +2 -7
- package/resources/components/Dashboard/Commerce/CommerceManufacturerDialog.stx +2 -4
- package/resources/components/Dashboard/Commerce/CommerceOrderDialog.stx +2 -4
- package/resources/components/Dashboard/Commerce/CommerceOrdersDashboard.stx +2 -7
- package/resources/components/Dashboard/Commerce/CommerceProductDialog.stx +2 -4
- package/resources/components/Dashboard/Commerce/CommerceProductsDashboard.stx +2 -7
- package/resources/components/Dashboard/Commerce/CommerceReviewEditDialog.stx +2 -4
- package/resources/components/Dashboard/Commerce/CommerceTaxDialog.stx +2 -4
- package/resources/components/Dashboard/Commerce/CommerceUnitDialog.stx +2 -4
- package/resources/components/Dashboard/Commerce/CommerceVariantDialog.stx +2 -4
- package/resources/components/Dashboard/Commerce/Delivery/CouriersDashboard.stx +45 -92
- package/resources/components/Dashboard/Commerce/Delivery/DeliveryRoutesDashboard.stx +46 -92
- package/resources/components/Dashboard/Commerce/Delivery/LicenseKeysDashboard.stx +46 -92
- package/resources/components/Dashboard/Commerce/Delivery/ShippingRatesDashboard.stx +44 -90
- package/resources/components/Dashboard/Commerce/Delivery/ShippingZonesDashboard.stx +45 -91
- package/resources/components/Dashboard/Commerce/PrintDeviceDialog.stx +2 -4
- package/resources/components/Dashboard/Commerce/PrintDevicesDashboard.stx +2 -7
- package/resources/components/Dashboard/Commerce/ProductWaitlistEntryDialog.stx +2 -4
- package/resources/components/Dashboard/Commerce/RestaurantWaitlistEntryDialog.stx +2 -4
- package/resources/components/Dashboard/Marketing/AbandonedCartsDashboard.stx +2 -9
- package/resources/components/Dashboard/Marketing/CampaignsDashboard.stx +2 -9
- package/resources/components/Dashboard/Marketing/MarketingListsDashboard.stx +2 -9
- package/resources/components/Dashboard/Marketing/SocialPostsDashboard.stx +2 -9
- package/resources/plugins/preloader.ts +9 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script client>
|
|
2
2
|
import { dashboardApi } from '../../../../../functions/dashboard-api'
|
|
3
|
+
import { useRecordsDashboard } from '../../../../../functions/dashboard-list'
|
|
3
4
|
import { pushToast } from '../../../../../functions/toasts'
|
|
4
5
|
import { formatCurrency, minorToInput } from '@stacksjs/commerce/money'
|
|
5
6
|
|
|
@@ -28,22 +29,47 @@ interface ShippingRatePayload {
|
|
|
28
29
|
rate: number
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
function matchesQuery(records: ShippingRateRecord[], query: string): ShippingRateRecord[] {
|
|
33
|
+
return records.filter(record => [
|
|
34
|
+
record.shipping_method?.name,
|
|
35
|
+
record.shipping_zone?.name,
|
|
36
|
+
record.weight_from,
|
|
37
|
+
record.weight_to,
|
|
38
|
+
minorToInput(record.rate, 'USD'),
|
|
39
|
+
].some(value => String(value ?? '').toLowerCase().includes(query)))
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const {
|
|
43
|
+
records,
|
|
44
|
+
loading,
|
|
45
|
+
loadError,
|
|
46
|
+
search,
|
|
47
|
+
page,
|
|
48
|
+
perPage,
|
|
49
|
+
editorOpen,
|
|
50
|
+
editorMode,
|
|
51
|
+
editing,
|
|
52
|
+
saving,
|
|
53
|
+
editorError,
|
|
54
|
+
deleting,
|
|
55
|
+
deleteBusy,
|
|
56
|
+
deleteError,
|
|
57
|
+
filteredRecords,
|
|
58
|
+
paginatedRecords,
|
|
59
|
+
goToPage,
|
|
60
|
+
handleSearch,
|
|
61
|
+
openCreate,
|
|
62
|
+
openEdit,
|
|
63
|
+
closeEditor,
|
|
64
|
+
requestDelete,
|
|
65
|
+
closeDelete,
|
|
66
|
+
upsert,
|
|
67
|
+
remove,
|
|
68
|
+
clampPage,
|
|
69
|
+
} = useRecordsDashboard<ShippingRateRecord>({ filter: matchesQuery })
|
|
70
|
+
|
|
32
71
|
const methods = state<ShippingResourceOption[]>([])
|
|
33
72
|
const zones = state<ShippingResourceOption[]>([])
|
|
34
|
-
const loading = state(true)
|
|
35
|
-
const loadError = state('')
|
|
36
|
-
const search = state('')
|
|
37
|
-
const page = state(1)
|
|
38
|
-
const perPage = state(10)
|
|
39
|
-
const editorOpen = state(false)
|
|
40
|
-
const editorMode = state<'create' | 'edit'>('create')
|
|
41
|
-
const editing = state<ShippingRateRecord | null>(null)
|
|
42
|
-
const saving = state(false)
|
|
43
|
-
const editorError = state('')
|
|
44
|
-
const deleting = state<ShippingRateRecord | null>(null)
|
|
45
|
-
const deleteBusy = state(false)
|
|
46
|
-
const deleteError = state('')
|
|
47
73
|
|
|
48
74
|
function methodFor(id: number): ShippingResourceOption | undefined {
|
|
49
75
|
return methods().find(method => method.id === id)
|
|
@@ -61,24 +87,6 @@ function withRelations(record: ShippingRateRecord): ShippingRateRecord {
|
|
|
61
87
|
}
|
|
62
88
|
}
|
|
63
89
|
|
|
64
|
-
function filteredRecords(): ShippingRateRecord[] {
|
|
65
|
-
const query = search().trim().toLowerCase()
|
|
66
|
-
if (!query)
|
|
67
|
-
return records()
|
|
68
|
-
return records().filter(record => [
|
|
69
|
-
record.shipping_method?.name,
|
|
70
|
-
record.shipping_zone?.name,
|
|
71
|
-
record.weight_from,
|
|
72
|
-
record.weight_to,
|
|
73
|
-
minorToInput(record.rate, 'USD'),
|
|
74
|
-
].some(value => String(value ?? '').toLowerCase().includes(query)))
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function paginatedRecords(): ShippingRateRecord[] {
|
|
78
|
-
const start = (page() - 1) * perPage()
|
|
79
|
-
return filteredRecords().slice(start, start + perPage())
|
|
80
|
-
}
|
|
81
|
-
|
|
82
90
|
function uniqueZoneCount(): number {
|
|
83
91
|
return new Set(records().map(record => record.shipping_zone_id)).size
|
|
84
92
|
}
|
|
@@ -114,9 +122,7 @@ async function loadRates(): Promise<void> {
|
|
|
114
122
|
methods.set(methodData)
|
|
115
123
|
zones.set(zoneData)
|
|
116
124
|
records.set(rateData.map(withRelations))
|
|
117
|
-
|
|
118
|
-
if (page() > lastPage)
|
|
119
|
-
page.set(lastPage)
|
|
125
|
+
clampPage()
|
|
120
126
|
}
|
|
121
127
|
catch (error) {
|
|
122
128
|
loadError.set(error instanceof Error ? error.message : String(error))
|
|
@@ -127,33 +133,6 @@ async function loadRates(): Promise<void> {
|
|
|
127
133
|
}
|
|
128
134
|
}
|
|
129
135
|
|
|
130
|
-
function handleSearch(value: string): void {
|
|
131
|
-
search.set(value)
|
|
132
|
-
page.set(1)
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function openCreate(): void {
|
|
136
|
-
editing.set(null)
|
|
137
|
-
editorMode.set('create')
|
|
138
|
-
editorError.set('')
|
|
139
|
-
editorOpen.set(true)
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
function openEdit(record: ShippingRateRecord): void {
|
|
143
|
-
editing.set(record)
|
|
144
|
-
editorMode.set('edit')
|
|
145
|
-
editorError.set('')
|
|
146
|
-
editorOpen.set(true)
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
function closeEditor(): void {
|
|
150
|
-
if (saving())
|
|
151
|
-
return
|
|
152
|
-
editorOpen.set(false)
|
|
153
|
-
editing.set(null)
|
|
154
|
-
editorError.set('')
|
|
155
|
-
}
|
|
156
|
-
|
|
157
136
|
function setEditorError(message: string): void {
|
|
158
137
|
editorError.set(message)
|
|
159
138
|
}
|
|
@@ -173,14 +152,7 @@ async function saveRate(payload: ShippingRatePayload): Promise<void> {
|
|
|
173
152
|
},
|
|
174
153
|
)
|
|
175
154
|
const hydrated = withRelations(updated)
|
|
176
|
-
|
|
177
|
-
records.set(records().map(record => record.id === current.id ? hydrated : record))
|
|
178
|
-
}
|
|
179
|
-
else {
|
|
180
|
-
const nextRecords = [...records(), hydrated]
|
|
181
|
-
records.set(nextRecords)
|
|
182
|
-
page.set(Math.max(1, Math.ceil(nextRecords.length / perPage())))
|
|
183
|
-
}
|
|
155
|
+
upsert(hydrated, current)
|
|
184
156
|
editorOpen.set(false)
|
|
185
157
|
editing.set(null)
|
|
186
158
|
pushToast('success', current ? 'Shipping rate updated' : 'Shipping rate added', {
|
|
@@ -195,18 +167,6 @@ async function saveRate(payload: ShippingRatePayload): Promise<void> {
|
|
|
195
167
|
}
|
|
196
168
|
}
|
|
197
169
|
|
|
198
|
-
function requestDelete(record: ShippingRateRecord): void {
|
|
199
|
-
deleting.set(record)
|
|
200
|
-
deleteError.set('')
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
function closeDelete(): void {
|
|
204
|
-
if (deleteBusy())
|
|
205
|
-
return
|
|
206
|
-
deleting.set(null)
|
|
207
|
-
deleteError.set('')
|
|
208
|
-
}
|
|
209
|
-
|
|
210
170
|
async function confirmDelete(): Promise<void> {
|
|
211
171
|
const current = deleting()
|
|
212
172
|
if (!current)
|
|
@@ -217,11 +177,9 @@ async function confirmDelete(): Promise<void> {
|
|
|
217
177
|
await dashboardApi(`/api/dashboard/commerce/shipping-rates/${current.id}`, {
|
|
218
178
|
method: 'DELETE',
|
|
219
179
|
})
|
|
220
|
-
|
|
180
|
+
remove(current)
|
|
221
181
|
deleting.set(null)
|
|
222
|
-
|
|
223
|
-
if (page() > lastPage)
|
|
224
|
-
page.set(lastPage)
|
|
182
|
+
clampPage()
|
|
225
183
|
pushToast('success', 'Shipping rate deleted', {
|
|
226
184
|
detail: `${current.shipping_method?.name || 'Method'} for ${current.shipping_zone?.name || 'zone'}`,
|
|
227
185
|
})
|
|
@@ -234,10 +192,6 @@ async function confirmDelete(): Promise<void> {
|
|
|
234
192
|
}
|
|
235
193
|
}
|
|
236
194
|
|
|
237
|
-
function goToPage(value: number): void {
|
|
238
|
-
page.set(value)
|
|
239
|
-
}
|
|
240
|
-
|
|
241
195
|
onMount(() => {
|
|
242
196
|
void loadRates()
|
|
243
197
|
})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script client>
|
|
2
2
|
import { dashboardApi } from '../../../../../functions/dashboard-api'
|
|
3
|
+
import { useRecordsDashboard } from '../../../../../functions/dashboard-list'
|
|
3
4
|
import { pushToast } from '../../../../../functions/toasts'
|
|
4
5
|
|
|
5
6
|
type SerializedList = string | string[] | null | undefined
|
|
@@ -30,21 +31,47 @@ interface ShippingZonePayload {
|
|
|
30
31
|
status: 'active' | 'inactive' | 'draft'
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
|
|
34
|
+
function matchesQuery(records: ShippingZoneRecord[], query: string): ShippingZoneRecord[] {
|
|
35
|
+
return records.filter(record => [
|
|
36
|
+
record.name,
|
|
37
|
+
record.status,
|
|
38
|
+
record.shipping_method?.name,
|
|
39
|
+
...listTokens(record.countries),
|
|
40
|
+
...listTokens(record.regions),
|
|
41
|
+
...listTokens(record.postal_codes),
|
|
42
|
+
].some(value => String(value || '').toLowerCase().includes(query)))
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const {
|
|
46
|
+
records,
|
|
47
|
+
loading,
|
|
48
|
+
loadError,
|
|
49
|
+
search,
|
|
50
|
+
page,
|
|
51
|
+
perPage,
|
|
52
|
+
editorOpen,
|
|
53
|
+
editorMode,
|
|
54
|
+
editing,
|
|
55
|
+
saving,
|
|
56
|
+
editorError,
|
|
57
|
+
deleting,
|
|
58
|
+
deleteBusy,
|
|
59
|
+
deleteError,
|
|
60
|
+
filteredRecords,
|
|
61
|
+
paginatedRecords,
|
|
62
|
+
goToPage,
|
|
63
|
+
handleSearch,
|
|
64
|
+
openCreate,
|
|
65
|
+
openEdit,
|
|
66
|
+
closeEditor,
|
|
67
|
+
requestDelete,
|
|
68
|
+
closeDelete,
|
|
69
|
+
upsert,
|
|
70
|
+
remove,
|
|
71
|
+
clampPage,
|
|
72
|
+
} = useRecordsDashboard<ShippingZoneRecord>({ filter: matchesQuery })
|
|
73
|
+
|
|
34
74
|
const methods = state<ShippingMethodOption[]>([])
|
|
35
|
-
const loading = state(true)
|
|
36
|
-
const loadError = state('')
|
|
37
|
-
const search = state('')
|
|
38
|
-
const page = state(1)
|
|
39
|
-
const perPage = state(10)
|
|
40
|
-
const editorOpen = state(false)
|
|
41
|
-
const editorMode = state<'create' | 'edit'>('create')
|
|
42
|
-
const editing = state<ShippingZoneRecord | null>(null)
|
|
43
|
-
const saving = state(false)
|
|
44
|
-
const editorError = state('')
|
|
45
|
-
const deleting = state<ShippingZoneRecord | null>(null)
|
|
46
|
-
const deleteBusy = state(false)
|
|
47
|
-
const deleteError = state('')
|
|
48
75
|
|
|
49
76
|
function listTokens(value: SerializedList): string[] {
|
|
50
77
|
if (Array.isArray(value))
|
|
@@ -73,25 +100,6 @@ function withMethod(record: ShippingZoneRecord): ShippingZoneRecord {
|
|
|
73
100
|
}
|
|
74
101
|
}
|
|
75
102
|
|
|
76
|
-
function filteredRecords(): ShippingZoneRecord[] {
|
|
77
|
-
const query = search().trim().toLowerCase()
|
|
78
|
-
if (!query)
|
|
79
|
-
return records()
|
|
80
|
-
return records().filter(record => [
|
|
81
|
-
record.name,
|
|
82
|
-
record.status,
|
|
83
|
-
record.shipping_method?.name,
|
|
84
|
-
...listTokens(record.countries),
|
|
85
|
-
...listTokens(record.regions),
|
|
86
|
-
...listTokens(record.postal_codes),
|
|
87
|
-
].some(value => String(value || '').toLowerCase().includes(query)))
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function paginatedRecords(): ShippingZoneRecord[] {
|
|
91
|
-
const start = (page() - 1) * perPage()
|
|
92
|
-
return filteredRecords().slice(start, start + perPage())
|
|
93
|
-
}
|
|
94
|
-
|
|
95
103
|
function uniqueCount(field: 'countries' | 'regions'): number {
|
|
96
104
|
return new Set(records().flatMap(record => listTokens(record[field]))).size
|
|
97
105
|
}
|
|
@@ -122,9 +130,7 @@ async function loadZones(): Promise<void> {
|
|
|
122
130
|
throw new TypeError('Shipping zone resources were not returned as arrays.')
|
|
123
131
|
methods.set(methodData)
|
|
124
132
|
records.set(zoneData.map(withMethod))
|
|
125
|
-
|
|
126
|
-
if (page() > lastPage)
|
|
127
|
-
page.set(lastPage)
|
|
133
|
+
clampPage()
|
|
128
134
|
}
|
|
129
135
|
catch (error) {
|
|
130
136
|
loadError.set(error instanceof Error ? error.message : String(error))
|
|
@@ -135,33 +141,6 @@ async function loadZones(): Promise<void> {
|
|
|
135
141
|
}
|
|
136
142
|
}
|
|
137
143
|
|
|
138
|
-
function handleSearch(value: string): void {
|
|
139
|
-
search.set(value)
|
|
140
|
-
page.set(1)
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
function openCreate(): void {
|
|
144
|
-
editing.set(null)
|
|
145
|
-
editorMode.set('create')
|
|
146
|
-
editorError.set('')
|
|
147
|
-
editorOpen.set(true)
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
function openEdit(record: ShippingZoneRecord): void {
|
|
151
|
-
editing.set(record)
|
|
152
|
-
editorMode.set('edit')
|
|
153
|
-
editorError.set('')
|
|
154
|
-
editorOpen.set(true)
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
function closeEditor(): void {
|
|
158
|
-
if (saving())
|
|
159
|
-
return
|
|
160
|
-
editorOpen.set(false)
|
|
161
|
-
editing.set(null)
|
|
162
|
-
editorError.set('')
|
|
163
|
-
}
|
|
164
|
-
|
|
165
144
|
function setEditorError(message: string): void {
|
|
166
145
|
editorError.set(message)
|
|
167
146
|
}
|
|
@@ -181,14 +160,7 @@ async function saveZone(payload: ShippingZonePayload): Promise<void> {
|
|
|
181
160
|
},
|
|
182
161
|
)
|
|
183
162
|
const hydrated = withMethod(updated)
|
|
184
|
-
|
|
185
|
-
records.set(records().map(record => record.id === current.id ? hydrated : record))
|
|
186
|
-
}
|
|
187
|
-
else {
|
|
188
|
-
const nextRecords = [...records(), hydrated]
|
|
189
|
-
records.set(nextRecords)
|
|
190
|
-
page.set(Math.max(1, Math.ceil(nextRecords.length / perPage())))
|
|
191
|
-
}
|
|
163
|
+
upsert(hydrated, current)
|
|
192
164
|
editorOpen.set(false)
|
|
193
165
|
editing.set(null)
|
|
194
166
|
pushToast('success', current ? 'Shipping zone updated' : 'Shipping zone added', {
|
|
@@ -203,18 +175,6 @@ async function saveZone(payload: ShippingZonePayload): Promise<void> {
|
|
|
203
175
|
}
|
|
204
176
|
}
|
|
205
177
|
|
|
206
|
-
function requestDelete(record: ShippingZoneRecord): void {
|
|
207
|
-
deleting.set(record)
|
|
208
|
-
deleteError.set('')
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
function closeDelete(): void {
|
|
212
|
-
if (deleteBusy())
|
|
213
|
-
return
|
|
214
|
-
deleting.set(null)
|
|
215
|
-
deleteError.set('')
|
|
216
|
-
}
|
|
217
|
-
|
|
218
178
|
async function confirmDelete(): Promise<void> {
|
|
219
179
|
const current = deleting()
|
|
220
180
|
if (!current)
|
|
@@ -225,11 +185,9 @@ async function confirmDelete(): Promise<void> {
|
|
|
225
185
|
await dashboardApi(`/api/dashboard/commerce/shipping-zones/${current.id}`, {
|
|
226
186
|
method: 'DELETE',
|
|
227
187
|
})
|
|
228
|
-
|
|
188
|
+
remove(current)
|
|
229
189
|
deleting.set(null)
|
|
230
|
-
|
|
231
|
-
if (page() > lastPage)
|
|
232
|
-
page.set(lastPage)
|
|
190
|
+
clampPage()
|
|
233
191
|
pushToast('success', 'Shipping zone deleted', { detail: current.name })
|
|
234
192
|
}
|
|
235
193
|
catch (error) {
|
|
@@ -240,10 +198,6 @@ async function confirmDelete(): Promise<void> {
|
|
|
240
198
|
}
|
|
241
199
|
}
|
|
242
200
|
|
|
243
|
-
function goToPage(value: number): void {
|
|
244
|
-
page.set(value)
|
|
245
|
-
}
|
|
246
|
-
|
|
247
201
|
onMount(() => {
|
|
248
202
|
void loadZones()
|
|
249
203
|
})
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script client>
|
|
2
|
+
import { formErrorMessages } from '../../../../functions/dashboard-form'
|
|
2
3
|
import type {
|
|
3
4
|
PrintDeviceRecord,
|
|
4
5
|
PrintDeviceStatus,
|
|
@@ -51,10 +52,7 @@ function submit(): void {
|
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
function errorMessages(): string[] {
|
|
54
|
-
return
|
|
55
|
-
const label = field.replace(/([a-z])([A-Z])/g, '$1 $2').replaceAll('_', ' ')
|
|
56
|
-
return `${label.charAt(0).toUpperCase()}${label.slice(1)}: ${message}`
|
|
57
|
-
})
|
|
55
|
+
return formErrorMessages(errors())
|
|
58
56
|
}
|
|
59
57
|
</script>
|
|
60
58
|
|
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
} from '../../../../app/Actions/Dashboard/Commerce/print-device-records'
|
|
7
7
|
import { DashboardApiError, dashboardApi } from '../../../../functions/dashboard-api'
|
|
8
8
|
import { pushToast } from '../../../../functions/toasts'
|
|
9
|
+
import { pageControls } from '../../../../functions/dashboard-list'
|
|
9
10
|
|
|
10
11
|
interface PrintDevicesResponse {
|
|
11
12
|
records: PrintDeviceRecord[]
|
|
@@ -234,13 +235,7 @@ async function deletePrintDevice(): Promise<void> {
|
|
|
234
235
|
}
|
|
235
236
|
}
|
|
236
237
|
|
|
237
|
-
|
|
238
|
-
page.set(Math.max(1, page() - 1))
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
function nextPage(): void {
|
|
242
|
-
page.set(Math.min(pageCount(), page() + 1))
|
|
243
|
-
}
|
|
238
|
+
const { previousPage, nextPage } = pageControls(page, pageCount)
|
|
244
239
|
|
|
245
240
|
onMount(() => {
|
|
246
241
|
void loadPrintDevices()
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script client>
|
|
2
2
|
import type { ProductWaitlistOptions, ProductWaitlistRecord, ProductWaitlistWritePayload } from '../../../../app/Actions/Dashboard/Commerce/product-waitlist-records'
|
|
3
|
+
import { formErrorMessages } from '../../../../functions/dashboard-form'
|
|
3
4
|
|
|
4
5
|
type DialogMode = 'add' | 'edit'
|
|
5
6
|
|
|
@@ -94,10 +95,7 @@ function submitForm(): void {
|
|
|
94
95
|
}
|
|
95
96
|
|
|
96
97
|
function errorMessages(): string[] {
|
|
97
|
-
return
|
|
98
|
-
const label = field.replace(/([a-z])([A-Z])/g, '$1 $2').replaceAll('_', ' ')
|
|
99
|
-
return `${label.charAt(0).toUpperCase()}${label.slice(1)}: ${message}`
|
|
100
|
-
})
|
|
98
|
+
return formErrorMessages(errors())
|
|
101
99
|
}
|
|
102
100
|
</script>
|
|
103
101
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script client>
|
|
2
2
|
import type { RestaurantWaitlistOptions, RestaurantWaitlistRecord, RestaurantWaitlistWritePayload } from '../../../../app/Actions/Dashboard/Commerce/restaurant-waitlist-records'
|
|
3
3
|
import { restaurantWaitlistDateTimeLocal, restaurantWaitlistTimestamp } from '../../../../app/Actions/Dashboard/Commerce/restaurant-waitlist-records'
|
|
4
|
+
import { formErrorMessages } from '../../../../functions/dashboard-form'
|
|
4
5
|
|
|
5
6
|
type DialogMode = 'add' | 'edit'
|
|
6
7
|
|
|
@@ -104,10 +105,7 @@ function submitForm(): void {
|
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
function errorMessages(): string[] {
|
|
107
|
-
return
|
|
108
|
-
const label = field.replace(/([a-z])([A-Z])/g, '$1 $2').replaceAll('_', ' ')
|
|
109
|
-
return `${label.charAt(0).toUpperCase()}${label.slice(1)}: ${message}`
|
|
110
|
-
})
|
|
108
|
+
return formErrorMessages(errors())
|
|
111
109
|
}
|
|
112
110
|
</script>
|
|
113
111
|
|
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
import { formatCurrency } from '@stacksjs/commerce/money'
|
|
9
9
|
import { dashboardApi } from '../../../../functions/dashboard-api'
|
|
10
10
|
import { pushToast } from '../../../../functions/toasts'
|
|
11
|
+
import { pageControls } from '../../../../functions/dashboard-list'
|
|
11
12
|
|
|
12
13
|
const emptySummary: AbandonedCartSummary = {
|
|
13
14
|
open: 0,
|
|
@@ -162,15 +163,7 @@ async function createCampaign(payload: Record<string, unknown>): Promise<void> {
|
|
|
162
163
|
}
|
|
163
164
|
}
|
|
164
165
|
|
|
165
|
-
|
|
166
|
-
if (page() > 1)
|
|
167
|
-
page.set(page() - 1)
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
function nextPage(): void {
|
|
171
|
-
if (page() < totalPages())
|
|
172
|
-
page.set(page() + 1)
|
|
173
|
-
}
|
|
166
|
+
const { previousPage, nextPage } = pageControls(page, totalPages)
|
|
174
167
|
|
|
175
168
|
onMount(() => {
|
|
176
169
|
void loadCarts()
|
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
import type { CampaignDeliveryOperation } from '../../../../app/Actions/Dashboard/Marketing/campaign-delivery'
|
|
8
8
|
import { dashboardApi } from '../../../../functions/dashboard-api'
|
|
9
9
|
import { pushToast } from '../../../../functions/toasts'
|
|
10
|
+
import { pageControls } from '../../../../functions/dashboard-list'
|
|
10
11
|
|
|
11
12
|
interface CampaignIndexResponse {
|
|
12
13
|
records: CampaignRecord[]
|
|
@@ -271,15 +272,7 @@ async function confirmDelivery(payload: { scheduledAt?: string }): Promise<void>
|
|
|
271
272
|
}
|
|
272
273
|
}
|
|
273
274
|
|
|
274
|
-
|
|
275
|
-
if (page() > 1)
|
|
276
|
-
page.set(page() - 1)
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
function nextPage(): void {
|
|
280
|
-
if (page() < totalPages())
|
|
281
|
-
page.set(page() + 1)
|
|
282
|
-
}
|
|
275
|
+
const { previousPage, nextPage } = pageControls(page, totalPages)
|
|
283
276
|
|
|
284
277
|
onMount(() => {
|
|
285
278
|
void loadCampaigns()
|
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
} from '../../../../app/Actions/Dashboard/Marketing/marketing-list-records'
|
|
6
6
|
import { dashboardApi } from '../../../../functions/dashboard-api'
|
|
7
7
|
import { pushToast } from '../../../../functions/toasts'
|
|
8
|
+
import { pageControls } from '../../../../functions/dashboard-list'
|
|
8
9
|
|
|
9
10
|
interface MarketingListIndexResponse {
|
|
10
11
|
records: MarketingListRecord[]
|
|
@@ -193,15 +194,7 @@ async function deleteList(): Promise<void> {
|
|
|
193
194
|
}
|
|
194
195
|
}
|
|
195
196
|
|
|
196
|
-
|
|
197
|
-
if (page() > 1)
|
|
198
|
-
page.set(page() - 1)
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
function nextPage(): void {
|
|
202
|
-
if (page() < totalPages())
|
|
203
|
-
page.set(page() + 1)
|
|
204
|
-
}
|
|
197
|
+
const { previousPage, nextPage } = pageControls(page, totalPages)
|
|
205
198
|
|
|
206
199
|
onMount(() => {
|
|
207
200
|
void loadLists()
|
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
} from '../../../../app/Actions/Dashboard/Marketing/social-post-records'
|
|
7
7
|
import { dashboardApi } from '../../../../functions/dashboard-api'
|
|
8
8
|
import { pushToast } from '../../../../functions/toasts'
|
|
9
|
+
import { pageControls } from '../../../../functions/dashboard-list'
|
|
9
10
|
|
|
10
11
|
interface SocialPostIndexResponse {
|
|
11
12
|
records: SocialPostRecord[]
|
|
@@ -186,15 +187,7 @@ async function deletePost(): Promise<void> {
|
|
|
186
187
|
}
|
|
187
188
|
}
|
|
188
189
|
|
|
189
|
-
|
|
190
|
-
if (page() > 1)
|
|
191
|
-
page.set(page() - 1)
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
function nextPage(): void {
|
|
195
|
-
if (page() < totalPages())
|
|
196
|
-
page.set(page() + 1)
|
|
197
|
-
}
|
|
190
|
+
const { previousPage, nextPage } = pageControls(page, totalPages)
|
|
198
191
|
|
|
199
192
|
onMount(() => {
|
|
200
193
|
void loadPosts()
|
|
@@ -88,7 +88,15 @@ const isRepl = !process.argv[1]
|
|
|
88
88
|
// otherwise valid. Postinstall scripts are bootstrap work and must stay independent
|
|
89
89
|
// of the application runtime preloader.
|
|
90
90
|
const isPostinstall = process.env.npm_lifecycle_event === 'postinstall'
|
|
91
|
-
|
|
91
|
+
// runAction starts these framework files directly, with flags rather than a
|
|
92
|
+
// Buddy command in argv[2]. They only inspect/release repository metadata.
|
|
93
|
+
// Match the framework's source and published layouts, never an app action
|
|
94
|
+
// which happens to have the same basename and needs its application globals.
|
|
95
|
+
const entrypoint = (process.argv[1] ?? '').replaceAll('\\', '/')
|
|
96
|
+
const repositoryAction = '(?:release|bump|generate/lib-entries)\\.[jt]s'
|
|
97
|
+
const isRepositoryAction = new RegExp(`(?:^|/)storage/framework/core/actions/src/${repositoryAction}$`).test(entrypoint)
|
|
98
|
+
|| new RegExp(`(?:^|/)(?:node_modules|pantry)/@stacksjs/actions/(?:src|dist(?:/src)?)/${repositoryAction}$`).test(entrypoint)
|
|
99
|
+
const skipPreloader = isRepl || isPostinstall || isRepositoryAction || (args.length > 0 && fastCommands.some(cmd => args[0] === cmd || args[0].startsWith(`${cmd}:`)))
|
|
92
100
|
|
|
93
101
|
if (!skipPreloader) {
|
|
94
102
|
// Detect production/deployment commands and set environment accordingly BEFORE loading env files
|