@7365admin1/layer-common 3.2.2-staging.159 → 3.2.2-staging.161
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/assets/css/screens.css +25 -0
- package/components/OnlineFormConfigurationForm.vue +96 -73
- package/components/OnlineFormFill.vue +165 -96
- package/components/OnlineFormRenderPreview.vue +25 -30
- package/components/OnlineFormsConfiguration.vue +66 -65
- package/package.json +1 -1
- package/utils/status.ts +5 -0
package/assets/css/screens.css
CHANGED
|
@@ -398,6 +398,31 @@
|
|
|
398
398
|
opacity: 0;
|
|
399
399
|
}
|
|
400
400
|
|
|
401
|
+
/*
|
|
402
|
+
* DISABLED. The two rules above set `background` and `color` unconditionally,
|
|
403
|
+
* and they out-specify the treatment Vuetify would otherwise give a disabled
|
|
404
|
+
* button - so a Submit that a `v-form` has genuinely gated OFF was painting
|
|
405
|
+
* the full accent fill at full opacity, identical to a live one. Measured on
|
|
406
|
+
* `OnlineFormFill` with its required field emptied: enabled and disabled came
|
|
407
|
+
* back byte-identical (`rgb(75, 116, 196)` / `rgb(255, 255, 255)` /
|
|
408
|
+
* `opacity: 1`) on BOTH themes. The gate held; nothing showed it.
|
|
409
|
+
*
|
|
410
|
+
* 0.5 is the design's own disabled step - `.app-btn:disabled` in
|
|
411
|
+
* `primitives.css` uses it - so the two button families dim by the same amount
|
|
412
|
+
* rather than inventing a second number here.
|
|
413
|
+
*
|
|
414
|
+
* Both the attribute and Vuetify's class are named: `:disabled` is what a
|
|
415
|
+
* plain `<button>` carries, `.v-btn--disabled` is what Vuetify adds, and a
|
|
416
|
+
* rule that matched only one of them would go quiet the moment the other path
|
|
417
|
+
* was used.
|
|
418
|
+
*/
|
|
419
|
+
.v-btn.screen-btn-primary:disabled,
|
|
420
|
+
.v-btn.screen-btn-primary.v-btn--disabled,
|
|
421
|
+
.v-btn.screen-btn-ghost:disabled,
|
|
422
|
+
.v-btn.screen-btn-ghost.v-btn--disabled {
|
|
423
|
+
opacity: 0.5;
|
|
424
|
+
}
|
|
425
|
+
|
|
401
426
|
/**
|
|
402
427
|
* The icon-only actions next to a primary button (download template, import,
|
|
403
428
|
* export). The design draws an icon button as a bordered square the height of
|
|
@@ -1,20 +1,26 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
<!-- The card wears `.screen-modal` for the 16px corner, the `--card` surface
|
|
3
|
+
and the modal shadow. Its title row and its Cancel/Create row were both
|
|
4
|
+
`v-toolbar`s - Vuetify `surface` slabs that stay a visible grey bar on
|
|
5
|
+
the dark card - and are now a `v-card-title` and the shared
|
|
6
|
+
`.screen-modal__footer` on the card's own surface. -->
|
|
7
|
+
<v-card class="screen-modal d-flex flex-column" width="100%">
|
|
8
|
+
<v-card-title class="flex-grow-0">
|
|
9
|
+
{{ prop.mode === "edit" ? "Edit" : "New" }} Online Form
|
|
10
|
+
</v-card-title>
|
|
11
|
+
|
|
12
|
+
<v-card-text class="screen-modal__body flex-grow-1 pa-0">
|
|
13
|
+
<!-- `.filter-field` is a DESCENDANT selector (`.filter-field .v-field`),
|
|
14
|
+
so one class on the form gives every input below it the design's
|
|
15
|
+
40px/10px/13.5px geometry. Not one `AppField` anywhere in here: the
|
|
16
|
+
Create gate runs off these `:rules`, and AppField carries none. -->
|
|
17
|
+
<v-form v-model="validForm" class="filter-field">
|
|
13
18
|
<div class="pa-4 pb-0">
|
|
14
19
|
|
|
15
20
|
<!-- Form Name -->
|
|
16
21
|
<div class="mb-3">
|
|
17
|
-
|
|
22
|
+
<!-- Create is gated on this being filled, so the label says so. -->
|
|
23
|
+
<InputLabel title="Form Name" :required="prop.mode !== 'edit'" />
|
|
18
24
|
<v-text-field
|
|
19
25
|
v-if="prop.mode !== 'edit'"
|
|
20
26
|
v-model="formName"
|
|
@@ -90,13 +96,14 @@
|
|
|
90
96
|
<span class="text-subtitle-2 font-weight-bold">Form Blocks</span>
|
|
91
97
|
<v-menu :close-on-content-click="true">
|
|
92
98
|
<template #activator="{ props: menuProps }">
|
|
99
|
+
<!-- The design's primary button. `tonal` painted Vuetify's own
|
|
100
|
+
wash over the accent; `.screen-btn-primary` is the 40px
|
|
101
|
+
accent fill the rest of the layer uses. -->
|
|
93
102
|
<v-btn
|
|
94
103
|
v-bind="menuProps"
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
variant="tonal"
|
|
104
|
+
variant="flat"
|
|
105
|
+
class="screen-btn-primary"
|
|
98
106
|
prepend-icon="mdi-plus"
|
|
99
|
-
class="text-none"
|
|
100
107
|
>
|
|
101
108
|
Add Block
|
|
102
109
|
</v-btn>
|
|
@@ -118,11 +125,14 @@
|
|
|
118
125
|
</v-menu>
|
|
119
126
|
</div>
|
|
120
127
|
|
|
121
|
-
<!-- Empty state
|
|
128
|
+
<!-- Empty state. The dashed edge was a hardcoded `#e0e0e0` - the same
|
|
129
|
+
near-white line on the dark card, where it read as a bright box
|
|
130
|
+
around nothing. `--border` is the design's own and follows the
|
|
131
|
+
theme; the dashed treatment stays, because this is a drop target
|
|
132
|
+
and not a card. -->
|
|
122
133
|
<div
|
|
123
134
|
v-if="blocks.length === 0"
|
|
124
|
-
class="
|
|
125
|
-
style="border: 2px dashed #e0e0e0; border-radius: 8px"
|
|
135
|
+
class="online-form-config__empty"
|
|
126
136
|
>
|
|
127
137
|
No blocks yet. Click "Add Block" to start building your form.
|
|
128
138
|
</div>
|
|
@@ -133,18 +143,25 @@
|
|
|
133
143
|
:key="block._uid"
|
|
134
144
|
class="mb-2"
|
|
135
145
|
>
|
|
136
|
-
<v-card
|
|
146
|
+
<v-card class="screen-card" flat>
|
|
137
147
|
<!-- Header row -->
|
|
138
148
|
<div class="d-flex align-center px-3 py-2 ga-2">
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
149
|
+
<!-- MEASURED, and the colour coding is deliberately GONE.
|
|
150
|
+
`blockTypeColor` painted eight fixed Vuetify palette fills
|
|
151
|
+
- teal, purple, orange, indigo - the SAME on both themes,
|
|
152
|
+
with white 10px text on them: "Heading" read 4.37:1 and
|
|
153
|
+
"Field" 3.67:1, identically light and dark, which is the
|
|
154
|
+
tell that nothing about them followed the theme. The
|
|
155
|
+
design has one tag, and it is neutral; the tag already
|
|
156
|
+
PRINTS the block type, so the eight colours told the user
|
|
157
|
+
nothing the word did not. Deleting the map is the fix, not
|
|
158
|
+
re-tinting it. -->
|
|
159
|
+
<StatusChip
|
|
160
|
+
:label="blockTypeLabel(block.type)"
|
|
161
|
+
tone="neutral"
|
|
162
|
+
:dot="false"
|
|
163
|
+
class="online-form-config__tag"
|
|
164
|
+
/>
|
|
148
165
|
<span
|
|
149
166
|
class="text-caption text-medium-emphasis flex-grow-1"
|
|
150
167
|
style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap"
|
|
@@ -363,54 +380,51 @@
|
|
|
363
380
|
</v-form>
|
|
364
381
|
</v-card-text>
|
|
365
382
|
|
|
366
|
-
<!--
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
</v-toolbar>
|
|
383
|
+
<!-- The design's footer: two equal-width buttons, ghost then primary. The
|
|
384
|
+
confirming button was a hardcoded `color="black"` fill, the same black
|
|
385
|
+
on both themes. `loading` keeps it a `v-btn` - AppButton has no
|
|
386
|
+
in-flight state. `:disabled` is unchanged, so the submit gate is
|
|
387
|
+
exactly the gate it was. -->
|
|
388
|
+
<div class="screen-modal__footer flex-grow-0">
|
|
389
|
+
<v-btn variant="outlined" class="screen-btn-ghost" @click="emit('cancel')">Cancel</v-btn>
|
|
390
|
+
<v-btn
|
|
391
|
+
variant="flat"
|
|
392
|
+
class="screen-btn-primary"
|
|
393
|
+
:disabled="!canSubmit || loading"
|
|
394
|
+
:loading="loading"
|
|
395
|
+
@click="submit"
|
|
396
|
+
>
|
|
397
|
+
{{ prop.mode === "edit" ? "Update" : "Create Form" }}
|
|
398
|
+
</v-btn>
|
|
399
|
+
</div>
|
|
384
400
|
|
|
385
401
|
<!-- Template picker dialog -->
|
|
386
402
|
<v-dialog v-model="showTemplatePicker" width="520" scrollable>
|
|
387
|
-
<v-card>
|
|
388
|
-
<v-
|
|
389
|
-
|
|
390
|
-
</v-toolbar>
|
|
391
|
-
<div class="pt-3 px-4 pb-2 text-caption text-medium-emphasis" style="white-space: normal">
|
|
403
|
+
<v-card class="screen-modal">
|
|
404
|
+
<v-card-title>Load Template</v-card-title>
|
|
405
|
+
<div class="screen-hint px-6 pb-2" style="white-space: normal">
|
|
392
406
|
Select a template to pre-populate form blocks. You can customise them after loading.
|
|
393
407
|
</div>
|
|
394
|
-
<v-card-text style="max-height: 55vh
|
|
395
|
-
|
|
408
|
+
<v-card-text class="screen-modal__body pa-0" style="max-height: 55vh">
|
|
409
|
+
<!-- `bg-color="transparent"` so the list sits on the card's own
|
|
410
|
+
surface rather than Vuetify's `surface` slab. -->
|
|
411
|
+
<v-list density="compact" bg-color="transparent">
|
|
396
412
|
<v-list-item
|
|
397
413
|
v-if="sortedTemplateNames.length === 0"
|
|
398
414
|
disabled
|
|
399
415
|
title="All templates have already been added for this site"
|
|
400
|
-
class="text-caption text-medium-emphasis"
|
|
401
416
|
/>
|
|
402
417
|
<v-list-item
|
|
403
418
|
v-for="name in sortedTemplateNames"
|
|
404
419
|
:key="name"
|
|
405
420
|
:title="name"
|
|
406
|
-
class="text-caption"
|
|
407
421
|
@click="loadTemplate(name)"
|
|
408
422
|
/>
|
|
409
423
|
</v-list>
|
|
410
424
|
</v-card-text>
|
|
411
|
-
<
|
|
412
|
-
<v-btn
|
|
413
|
-
</
|
|
425
|
+
<div class="screen-modal__footer">
|
|
426
|
+
<v-btn variant="outlined" class="screen-btn-ghost" @click="showTemplatePicker = false">Close</v-btn>
|
|
427
|
+
</div>
|
|
414
428
|
</v-card>
|
|
415
429
|
</v-dialog>
|
|
416
430
|
</v-card>
|
|
@@ -528,20 +542,6 @@ function blockTypeLabel(type: string): string {
|
|
|
528
542
|
return map[type] ?? type;
|
|
529
543
|
}
|
|
530
544
|
|
|
531
|
-
function blockTypeColor(type: string): string {
|
|
532
|
-
const map: Record<string, string> = {
|
|
533
|
-
"section-header": "blue-grey",
|
|
534
|
-
paragraph: "grey",
|
|
535
|
-
"ordered-list": "indigo",
|
|
536
|
-
"unordered-list": "indigo",
|
|
537
|
-
divider: "grey",
|
|
538
|
-
field: "teal",
|
|
539
|
-
"checkbox-group": "purple",
|
|
540
|
-
"signature-row": "orange",
|
|
541
|
-
};
|
|
542
|
-
return map[type] ?? "grey";
|
|
543
|
-
}
|
|
544
|
-
|
|
545
545
|
function blockSummary(block: AnyBlock): string {
|
|
546
546
|
switch (block.type) {
|
|
547
547
|
case "section-header":
|
|
@@ -720,3 +720,26 @@ async function submit() {
|
|
|
720
720
|
}
|
|
721
721
|
}
|
|
722
722
|
</script>
|
|
723
|
+
|
|
724
|
+
<style scoped>
|
|
725
|
+
/* The block builder's drop target. Same copy, same dashed treatment, on the
|
|
726
|
+
design's own border colour and secondary ink so it follows the theme. */
|
|
727
|
+
.online-form-config__empty {
|
|
728
|
+
padding: 32px 16px;
|
|
729
|
+
text-align: center;
|
|
730
|
+
font-family: var(--font-sans);
|
|
731
|
+
font-size: var(--fs-cell);
|
|
732
|
+
color: var(--muted);
|
|
733
|
+
border: 2px dashed var(--border);
|
|
734
|
+
border-radius: var(--r-inner);
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
/* The tags sit in a column, so they keep the fixed width the `v-chip` had -
|
|
738
|
+
otherwise "Divider" and "Numbered List" start their summaries at different
|
|
739
|
+
x positions down the list. */
|
|
740
|
+
.online-form-config__tag {
|
|
741
|
+
min-width: 110px;
|
|
742
|
+
justify-content: center;
|
|
743
|
+
flex-shrink: 0;
|
|
744
|
+
}
|
|
745
|
+
</style>
|
|
@@ -1,32 +1,29 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<v-card width="100%">
|
|
3
|
-
<!--
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
</span>
|
|
12
|
-
<v-spacer v-if="$slots['title-actions']" />
|
|
13
|
-
<slot name="title-actions" />
|
|
14
|
-
</v-row>
|
|
15
|
-
</v-toolbar>
|
|
2
|
+
<v-card class="screen-modal" width="100%">
|
|
3
|
+
<!-- The title row was a `grey-darken-3` v-toolbar with white uppercase
|
|
4
|
+
text: the same hardcoded dark slab on both themes. A `v-card-title` on
|
|
5
|
+
`.screen-modal` is the same row on the card's own surface, so it
|
|
6
|
+
follows the theme - and the actions slot keeps its place on the right. -->
|
|
7
|
+
<v-card-title class="d-flex align-center ga-2">
|
|
8
|
+
<span class="flex-grow-1">{{ definition.title }}</span>
|
|
9
|
+
<slot name="title-actions" />
|
|
10
|
+
</v-card-title>
|
|
16
11
|
|
|
17
12
|
<!-- Submission metadata bar (readonly only) -->
|
|
18
13
|
<div
|
|
19
14
|
v-if="readonly && (submissionStatus)"
|
|
20
|
-
class="px-6 py-2 d-flex align-center ga-4"
|
|
21
|
-
style="background: #f5f5f5; border-bottom: 1px solid #e0e0e0; flex-wrap: wrap"
|
|
15
|
+
class="online-form-fill__meta px-6 py-2 d-flex align-center ga-4"
|
|
22
16
|
>
|
|
23
|
-
|
|
17
|
+
<!-- `StatusChip` IS the design's status pill: it maps the WORD to a tone
|
|
18
|
+
through the shared `utils/status.ts`, so "Pending" is the same amber
|
|
19
|
+
here as on a work order, and it carries `--tone-bg` with the ink so
|
|
20
|
+
both halves of the measured pair arrive together. The `v-chip` it
|
|
21
|
+
replaces painted a flat fixed-palette fill under a white label. -->
|
|
22
|
+
<StatusChip
|
|
24
23
|
v-if="submissionStatus"
|
|
25
|
-
:
|
|
26
|
-
variant="flat"
|
|
27
|
-
size="x-small"
|
|
24
|
+
:status="submissionStatus"
|
|
28
25
|
class="text-capitalize"
|
|
29
|
-
|
|
26
|
+
/>
|
|
30
27
|
<span v-if="(initialValues as any).block" class="text-caption text-medium-emphasis">
|
|
31
28
|
Block: <strong>{{ (initialValues as any).block }}</strong>
|
|
32
29
|
</span>
|
|
@@ -37,18 +34,14 @@
|
|
|
37
34
|
Unit: <strong>{{ submissionUnit }}</strong>
|
|
38
35
|
</span>
|
|
39
36
|
<template v-if="requiresPayment">
|
|
40
|
-
|
|
37
|
+
<!-- The payment pair is not a status WORD the shared map knows, so the
|
|
38
|
+
tone is given directly - the same pill, the same measured pair. -->
|
|
39
|
+
<StatusChip
|
|
41
40
|
v-if="initialManagementValues?.paymentStatus"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
<v-chip
|
|
47
|
-
v-else
|
|
48
|
-
color="orange"
|
|
49
|
-
variant="flat"
|
|
50
|
-
size="x-small"
|
|
51
|
-
>Payment Not Paid</v-chip>
|
|
41
|
+
tone="ok"
|
|
42
|
+
:label="`Payment ${initialManagementValues.paymentStatus}`"
|
|
43
|
+
/>
|
|
44
|
+
<StatusChip v-else tone="warn" label="Payment Not Paid" />
|
|
52
45
|
<span
|
|
53
46
|
v-if="initialManagementValues?.paymentOrderId"
|
|
54
47
|
class="text-caption text-medium-emphasis"
|
|
@@ -58,17 +51,21 @@
|
|
|
58
51
|
|
|
59
52
|
<!-- Scrollable body -->
|
|
60
53
|
<v-card-text
|
|
61
|
-
style="max-height: 76vh
|
|
62
|
-
class="pa-6"
|
|
54
|
+
style="max-height: 76vh"
|
|
55
|
+
class="screen-modal__body pa-6"
|
|
63
56
|
>
|
|
64
|
-
|
|
57
|
+
<!-- `.filter-field` is a DESCENDANT selector (`.filter-field .v-field`),
|
|
58
|
+
so one class on the form gives every input below it the design's
|
|
59
|
+
40px/10px/13.5px geometry. Every `:rules` below is untouched, and no
|
|
60
|
+
field becomes an `AppField` - AppField carries no rules, and Submit
|
|
61
|
+
is gated on `validForm`, which only exists because these rules run. -->
|
|
62
|
+
<v-form v-model="validForm" class="filter-field">
|
|
65
63
|
<template v-for="(block, i) in displayBlocks" :key="i">
|
|
66
64
|
|
|
67
65
|
<!-- ADDRESS BLOCK -->
|
|
68
66
|
<div
|
|
69
67
|
v-if="block.type === 'address'"
|
|
70
|
-
class="mb-4 pa-3"
|
|
71
|
-
style="background: #f5f5f5; border-radius: 6px"
|
|
68
|
+
class="online-form-fill__panel mb-4 pa-3"
|
|
72
69
|
>
|
|
73
70
|
<v-row no-gutters>
|
|
74
71
|
<v-col cols="5">
|
|
@@ -91,7 +88,11 @@
|
|
|
91
88
|
:key="field.key"
|
|
92
89
|
:cols="field.cols || 6"
|
|
93
90
|
>
|
|
94
|
-
|
|
91
|
+
<!-- `required` was never passed, so the design system's own
|
|
92
|
+
asterisk never drew: a field the form REFUSES to submit
|
|
93
|
+
without looked identical to an optional one. The rule below
|
|
94
|
+
is keyed on the same `field.required`. -->
|
|
95
|
+
<InputLabel :title="field.label" :required="!readonly && !!field.required" />
|
|
95
96
|
<v-text-field
|
|
96
97
|
v-if="field.fieldType === 'text'"
|
|
97
98
|
v-model="values[field.key]"
|
|
@@ -137,7 +138,7 @@
|
|
|
137
138
|
|
|
138
139
|
<!-- SINGLE FULL-WIDTH FIELD -->
|
|
139
140
|
<div v-else-if="block.type === 'field'" class="mb-0">
|
|
140
|
-
<InputLabel :title="block.field.label" />
|
|
141
|
+
<InputLabel :title="block.field.label" :required="!readonly && !!block.field.required" />
|
|
141
142
|
<v-text-field
|
|
142
143
|
v-if="block.field.fieldType === 'text'"
|
|
143
144
|
v-model="values[block.field.key]"
|
|
@@ -233,16 +234,12 @@
|
|
|
233
234
|
</div>
|
|
234
235
|
|
|
235
236
|
<!-- PARAGRAPH (terms / info text) -->
|
|
237
|
+
<!-- `color: #333` was a near-black on a dark card: the terms text was
|
|
238
|
+
invisible on the dark theme (measured 1.32:1). `--text` is the
|
|
239
|
+
design's own ink and `--border` the design's own rule. -->
|
|
236
240
|
<p
|
|
237
241
|
v-else-if="block.type === 'paragraph'"
|
|
238
|
-
class="text-body-2 mb-3"
|
|
239
|
-
style="
|
|
240
|
-
line-height: 1.65;
|
|
241
|
-
color: #333;
|
|
242
|
-
text-align: justify;
|
|
243
|
-
border-left: 3px solid #ddd;
|
|
244
|
-
padding-left: 10px;
|
|
245
|
-
"
|
|
242
|
+
class="online-form-fill__para text-body-2 mb-3"
|
|
246
243
|
>
|
|
247
244
|
{{ resolveText(block.text) }}
|
|
248
245
|
</p>
|
|
@@ -259,7 +256,7 @@
|
|
|
259
256
|
v-for="(item, itemIdx) in block.items"
|
|
260
257
|
:key="itemIdx"
|
|
261
258
|
class="text-body-2 mb-1"
|
|
262
|
-
style="line-height: 1.55; color:
|
|
259
|
+
style="line-height: 1.55; color: var(--text)"
|
|
263
260
|
>{{ item }}</li>
|
|
264
261
|
</ol>
|
|
265
262
|
</div>
|
|
@@ -276,7 +273,7 @@
|
|
|
276
273
|
v-for="(item, itemIdx) in block.items"
|
|
277
274
|
:key="itemIdx"
|
|
278
275
|
class="text-body-2 mb-1"
|
|
279
|
-
style="line-height: 1.55; color:
|
|
276
|
+
style="line-height: 1.55; color: var(--text)"
|
|
280
277
|
>{{ item }}</li>
|
|
281
278
|
</ul>
|
|
282
279
|
</div>
|
|
@@ -299,6 +296,12 @@
|
|
|
299
296
|
class="mt-3 mb-5"
|
|
300
297
|
>
|
|
301
298
|
<span class="text-caption text-medium-emphasis d-block mb-1">{{ block.label }}</span>
|
|
299
|
+
<!-- DELIBERATELY NOT TOKENISED. `detectSigBackground` reads the
|
|
300
|
+
saved PNG and decides whether its ink is black or white; this
|
|
301
|
+
plate has to match THAT ink, not the current theme. A white
|
|
302
|
+
signature on a `--card` plate is invisible on the light theme,
|
|
303
|
+
and a black one on the dark theme - which is the whole reason
|
|
304
|
+
the detection exists. -->
|
|
302
305
|
<div
|
|
303
306
|
v-if="initialValues[block.key]"
|
|
304
307
|
:style="{
|
|
@@ -317,15 +320,14 @@
|
|
|
317
320
|
</div>
|
|
318
321
|
<div
|
|
319
322
|
v-else
|
|
320
|
-
|
|
323
|
+
class="online-form-fill__sig-blank"
|
|
321
324
|
/>
|
|
322
325
|
</div>
|
|
323
326
|
|
|
324
327
|
<!-- ACKNOWLEDGEMENT -->
|
|
325
328
|
<div
|
|
326
329
|
v-else-if="block.type === 'acknowledgement'"
|
|
327
|
-
class="mb-4 pa-3"
|
|
328
|
-
style="background: #f9f9f9; border-radius: 6px; border: 1px solid #eee"
|
|
330
|
+
class="online-form-fill__panel online-form-fill__panel--bordered mb-4 pa-3"
|
|
329
331
|
>
|
|
330
332
|
<span class="text-body-2 font-weight-medium">{{ resolveText(block.text) }}</span>
|
|
331
333
|
</div>
|
|
@@ -333,10 +335,10 @@
|
|
|
333
335
|
<!-- MANAGEMENT USE -->
|
|
334
336
|
<div
|
|
335
337
|
v-else-if="block.type === 'management-use'"
|
|
336
|
-
class="pa-4 mt-2"
|
|
337
|
-
:
|
|
338
|
-
? '
|
|
339
|
-
: '
|
|
338
|
+
class="online-form-fill__panel pa-4 mt-2"
|
|
339
|
+
:class="approvalMode && selectedAction === 'approved'
|
|
340
|
+
? 'online-form-fill__panel--ok'
|
|
341
|
+
: 'online-form-fill__panel--dim'"
|
|
340
342
|
>
|
|
341
343
|
<v-row no-gutters class="mb-2">
|
|
342
344
|
<span class="text-caption font-weight-bold text-medium-emphasis">
|
|
@@ -360,7 +362,7 @@
|
|
|
360
362
|
/>
|
|
361
363
|
<div
|
|
362
364
|
v-else
|
|
363
|
-
|
|
365
|
+
class="online-form-fill__mgmt-line"
|
|
364
366
|
>{{ managementValues[item] || '' }}</div>
|
|
365
367
|
</div>
|
|
366
368
|
</v-row>
|
|
@@ -378,7 +380,7 @@
|
|
|
378
380
|
<!-- Approval action panel -->
|
|
379
381
|
<div
|
|
380
382
|
v-if="readonly && approvalMode"
|
|
381
|
-
|
|
383
|
+
class="online-form-fill__approve"
|
|
382
384
|
>
|
|
383
385
|
<v-text-field
|
|
384
386
|
v-model="adminRemarks"
|
|
@@ -389,35 +391,35 @@
|
|
|
389
391
|
:error="remarksRequired && adminRemarks.trim().length === 0"
|
|
390
392
|
:error-messages="remarksRequired && adminRemarks.trim().length === 0 ? 'Remarks are required' : ''"
|
|
391
393
|
/>
|
|
392
|
-
|
|
393
|
-
|
|
394
|
+
<!-- The three verdicts keep their colour coding - it is what tells them
|
|
395
|
+
apart - but on the theme's own status colours rather than fixed
|
|
396
|
+
palette entries, so both the tonal and the flat state follow the
|
|
397
|
+
theme. Confirm was a hardcoded `grey-darken-3` fill and is now the
|
|
398
|
+
design's primary button, which is what it is. -->
|
|
399
|
+
<div class="d-flex align-center ga-2 justify-end flex-wrap">
|
|
400
|
+
<v-btn variant="outlined" class="screen-btn-ghost" @click="emit('cancel')">Close</v-btn>
|
|
394
401
|
<v-btn
|
|
395
402
|
:variant="selectedAction === 'resubmission' ? 'flat' : 'tonal'"
|
|
396
|
-
color="
|
|
403
|
+
color="warning"
|
|
397
404
|
class="text-none"
|
|
398
|
-
size="small"
|
|
399
405
|
@click="selectAction('resubmission')"
|
|
400
406
|
>Resubmit</v-btn>
|
|
401
407
|
<v-btn
|
|
402
408
|
:variant="selectedAction === 'rejected' ? 'flat' : 'tonal'"
|
|
403
|
-
color="
|
|
409
|
+
color="error"
|
|
404
410
|
class="text-none"
|
|
405
|
-
size="small"
|
|
406
411
|
@click="selectAction('rejected')"
|
|
407
412
|
>Reject</v-btn>
|
|
408
413
|
<v-btn
|
|
409
414
|
:variant="selectedAction === 'approved' ? 'flat' : 'tonal'"
|
|
410
|
-
color="
|
|
415
|
+
color="success"
|
|
411
416
|
class="text-none"
|
|
412
|
-
size="small"
|
|
413
417
|
@click="selectAction('approved')"
|
|
414
418
|
>Approve</v-btn>
|
|
415
419
|
<v-btn
|
|
416
420
|
v-if="selectedAction"
|
|
417
421
|
variant="flat"
|
|
418
|
-
|
|
419
|
-
class="text-none"
|
|
420
|
-
size="small"
|
|
422
|
+
class="screen-btn-primary"
|
|
421
423
|
:disabled="!canConfirm"
|
|
422
424
|
:loading="updatingStatus"
|
|
423
425
|
@click="confirmStatusUpdate"
|
|
@@ -425,24 +427,25 @@
|
|
|
425
427
|
</div>
|
|
426
428
|
</div>
|
|
427
429
|
|
|
428
|
-
<!--
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
430
|
+
<!-- The design's footer: equal-width buttons, ghost then primary, on a
|
|
431
|
+
bordered strip. Submit was a hardcoded `color="black"` block fill. Its
|
|
432
|
+
`:disabled="!validForm || submitting"` is untouched - the gate is still
|
|
433
|
+
the form's own validity. -->
|
|
434
|
+
<div v-else class="screen-modal__footer">
|
|
435
|
+
<template v-if="readonly">
|
|
436
|
+
<v-btn variant="outlined" class="screen-btn-ghost" @click="emit('cancel')">Close</v-btn>
|
|
437
|
+
</template>
|
|
438
|
+
<template v-else>
|
|
439
|
+
<v-btn variant="outlined" class="screen-btn-ghost" :disabled="submitting" @click="emit('cancel')">Cancel</v-btn>
|
|
440
|
+
<v-btn
|
|
441
|
+
variant="flat"
|
|
442
|
+
class="screen-btn-primary"
|
|
443
|
+
:disabled="!validForm || submitting"
|
|
444
|
+
:loading="submitting"
|
|
445
|
+
@click="submit"
|
|
446
|
+
>Submit</v-btn>
|
|
447
|
+
</template>
|
|
448
|
+
</div>
|
|
446
449
|
</v-card>
|
|
447
450
|
</template>
|
|
448
451
|
<script setup lang="ts">
|
|
@@ -621,15 +624,10 @@ function confirmStatusUpdate() {
|
|
|
621
624
|
|
|
622
625
|
const requiredRule = (v: any) => (v !== null && v !== undefined && v !== "") || "This field is required";
|
|
623
626
|
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
case "resubmission": return "orange";
|
|
629
|
-
case "rejected": return "red";
|
|
630
|
-
default: return "grey";
|
|
631
|
-
}
|
|
632
|
-
});
|
|
627
|
+
// The local status -> colour switch this file carried is gone: `StatusChip`
|
|
628
|
+
// maps the word through the shared `utils/status.ts`, which already had
|
|
629
|
+
// approved/pending/rejected and now has resubmission too. One mapping, not a
|
|
630
|
+
// second private copy that could drift from it.
|
|
633
631
|
|
|
634
632
|
const requiresPayment = computed(() => {
|
|
635
633
|
if (props.paymentAmount <= 0) return false;
|
|
@@ -771,3 +769,74 @@ async function submit() {
|
|
|
771
769
|
}
|
|
772
770
|
}
|
|
773
771
|
</script>
|
|
772
|
+
|
|
773
|
+
<style scoped>
|
|
774
|
+
/*
|
|
775
|
+
* Every surface below was a hardcoded near-white hex - `#f5f5f5`, `#f9f9f9`,
|
|
776
|
+
* `#f0f0f0`, `#fafafa` - with THEMED text on top of it. On the dark theme that
|
|
777
|
+
* put the design's near-white ink on a near-white plate: the address strip read
|
|
778
|
+
* 1.05:1, the acknowledgement 1.08:1 and the management panel 1:1, i.e. text
|
|
779
|
+
* that was there and could not be seen. `--bg` is the design's own recessed
|
|
780
|
+
* surface and follows the theme, so the same rows read correctly on both.
|
|
781
|
+
*/
|
|
782
|
+
.online-form-fill__meta {
|
|
783
|
+
flex-wrap: wrap;
|
|
784
|
+
background: var(--bg);
|
|
785
|
+
border-bottom: 1px solid var(--border);
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
.online-form-fill__panel {
|
|
789
|
+
background: var(--bg);
|
|
790
|
+
border-radius: var(--r-inner);
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
.online-form-fill__panel--bordered {
|
|
794
|
+
border: 1px solid var(--border);
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
/* The approved state of the management panel. `--ok-bg` / `--ok` are the
|
|
798
|
+
design's own success pair; it was `#e8f5e9` on `#a5d6a7`, the same greens on
|
|
799
|
+
both themes. */
|
|
800
|
+
.online-form-fill__panel--ok {
|
|
801
|
+
background: var(--ok-bg);
|
|
802
|
+
border: 1px solid var(--ok);
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
.online-form-fill__panel--dim {
|
|
806
|
+
opacity: 0.75;
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
.online-form-fill__para {
|
|
810
|
+
line-height: 1.65;
|
|
811
|
+
color: var(--text);
|
|
812
|
+
text-align: justify;
|
|
813
|
+
border-left: 3px solid var(--border);
|
|
814
|
+
padding-left: 10px;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
/* The ruled line a management entry is written on, and the empty signature
|
|
818
|
+
plate - both were fixed greys. */
|
|
819
|
+
.online-form-fill__mgmt-line {
|
|
820
|
+
border-bottom: 1px solid var(--border);
|
|
821
|
+
min-width: 120px;
|
|
822
|
+
height: 22px;
|
|
823
|
+
font-size: var(--fs-cell);
|
|
824
|
+
padding-top: 2px;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
.online-form-fill__sig-blank {
|
|
828
|
+
border-bottom: 1px dashed var(--border);
|
|
829
|
+
height: 56px;
|
|
830
|
+
background: var(--bg);
|
|
831
|
+
border-radius: var(--r-inner-sm);
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
.online-form-fill__approve {
|
|
835
|
+
display: flex;
|
|
836
|
+
flex-direction: column;
|
|
837
|
+
gap: 10px;
|
|
838
|
+
padding: 12px 16px;
|
|
839
|
+
background: var(--bg);
|
|
840
|
+
border-top: 1px solid var(--border);
|
|
841
|
+
}
|
|
842
|
+
</style>
|
|
@@ -5,25 +5,25 @@
|
|
|
5
5
|
width="560"
|
|
6
6
|
persistent
|
|
7
7
|
>
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
</v-
|
|
8
|
+
<!-- The title row was a `grey-darken-3` v-toolbar: the same hardcoded grey
|
|
9
|
+
slab on both themes, with white text sitting on it. A `v-card-title` on
|
|
10
|
+
`.screen-modal` is the same row on the card's own surface, so it
|
|
11
|
+
follows the theme. -->
|
|
12
|
+
<v-card class="screen-modal d-flex flex-column">
|
|
13
|
+
<v-card-title class="flex-grow-0">{{ form?.formType }}</v-card-title>
|
|
14
14
|
|
|
15
|
-
<v-card-subtitle class="px-6
|
|
15
|
+
<v-card-subtitle class="screen-hint px-6 pb-0 flex-grow-0">
|
|
16
16
|
Form preview — fields are read-only
|
|
17
17
|
</v-card-subtitle>
|
|
18
18
|
|
|
19
|
-
<v-card-text class="px-6 py-4 flex-grow-1"
|
|
19
|
+
<v-card-text class="screen-modal__body px-6 py-4 flex-grow-1">
|
|
20
20
|
<template v-for="(input, index) in form?.inputs" :key="index">
|
|
21
21
|
<v-text-field
|
|
22
22
|
v-if="input.dataType === 'Text Input'"
|
|
23
23
|
:label="input.label"
|
|
24
24
|
density="comfortable"
|
|
25
25
|
variant="outlined"
|
|
26
|
-
class="mb-1"
|
|
26
|
+
class="filter-field mb-1"
|
|
27
27
|
:hint="input.required ? 'Required' : ''"
|
|
28
28
|
persistent-hint
|
|
29
29
|
readonly
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
density="comfortable"
|
|
35
35
|
variant="outlined"
|
|
36
36
|
rows="3"
|
|
37
|
-
class="mb-1"
|
|
37
|
+
class="filter-field mb-1"
|
|
38
38
|
:hint="input.required ? 'Required' : ''"
|
|
39
39
|
persistent-hint
|
|
40
40
|
readonly
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
type="date"
|
|
46
46
|
density="comfortable"
|
|
47
47
|
variant="outlined"
|
|
48
|
-
class="mb-1"
|
|
48
|
+
class="filter-field mb-1"
|
|
49
49
|
:hint="input.required ? 'Required' : ''"
|
|
50
50
|
persistent-hint
|
|
51
51
|
readonly
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
:items="input.options || []"
|
|
57
57
|
density="comfortable"
|
|
58
58
|
variant="outlined"
|
|
59
|
-
class="mb-1"
|
|
59
|
+
class="filter-field mb-1"
|
|
60
60
|
:hint="input.required ? 'Required' : ''"
|
|
61
61
|
persistent-hint
|
|
62
62
|
readonly
|
|
@@ -65,29 +65,24 @@
|
|
|
65
65
|
v-else-if="input.dataType === 'Checkbox'"
|
|
66
66
|
:label="input.label"
|
|
67
67
|
density="comfortable"
|
|
68
|
-
class="mb-1"
|
|
68
|
+
class="filter-field mb-1"
|
|
69
69
|
readonly
|
|
70
70
|
/>
|
|
71
71
|
</template>
|
|
72
72
|
</v-card-text>
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
Close Preview
|
|
87
|
-
</v-btn>
|
|
88
|
-
</v-col>
|
|
89
|
-
</v-row>
|
|
90
|
-
</v-toolbar>
|
|
74
|
+
<!-- The design's modal footer. The Close button was a `color="black"`
|
|
75
|
+
square-cornered block fill - the same black on both themes, and the
|
|
76
|
+
shape of a primary action for what is only a dismiss. -->
|
|
77
|
+
<div class="screen-modal__footer flex-grow-0">
|
|
78
|
+
<v-btn
|
|
79
|
+
variant="outlined"
|
|
80
|
+
class="screen-btn-ghost"
|
|
81
|
+
@click="$emit('update:modelValue', false)"
|
|
82
|
+
>
|
|
83
|
+
Close Preview
|
|
84
|
+
</v-btn>
|
|
85
|
+
</div>
|
|
91
86
|
</v-card>
|
|
92
87
|
</v-dialog>
|
|
93
88
|
</template>
|
|
@@ -22,24 +22,23 @@
|
|
|
22
22
|
<AppCard class="table-card">
|
|
23
23
|
<CardToolbar :count="pageRange">
|
|
24
24
|
<template #left>
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
<!-- The design's 32px icon button, the same one every other
|
|
26
|
+
converted table toolbar uses, instead of Vuetify's tinted
|
|
27
|
+
fab. -->
|
|
28
|
+
<AppButton
|
|
29
|
+
variant="icon"
|
|
30
|
+
icon="mdi-refresh"
|
|
31
|
+
aria-label="Refresh"
|
|
29
32
|
@click="getOnlineFormConfigurations"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
density="comfortable"
|
|
37
|
-
:color="sortAlpha ? 'primary' : undefined"
|
|
33
|
+
/>
|
|
34
|
+
<AppButton
|
|
35
|
+
variant="icon"
|
|
36
|
+
icon="mdi-sort-alphabetical-ascending"
|
|
37
|
+
class="online-forms-config__sort"
|
|
38
|
+
:class="{ 'online-forms-config__sort--on': sortAlpha }"
|
|
38
39
|
:title="sortAlpha ? 'Sorted A–Z' : 'Sort A–Z'"
|
|
39
40
|
@click="sortAlpha = !sortAlpha"
|
|
40
|
-
|
|
41
|
-
<v-icon>mdi-sort-alphabetical-ascending</v-icon>
|
|
42
|
-
</v-btn>
|
|
41
|
+
/>
|
|
43
42
|
<AppField
|
|
44
43
|
v-model="search"
|
|
45
44
|
search
|
|
@@ -109,12 +108,15 @@
|
|
|
109
108
|
@cancel="previewDialog = false"
|
|
110
109
|
>
|
|
111
110
|
<template #title-actions>
|
|
111
|
+
<!-- `color="white"` was correct only while the fill's title bar was a
|
|
112
|
+
hardcoded dark slab. The bar now paints from `--card`, so the
|
|
113
|
+
pencil takes the card's own ink; `error` is a theme colour and
|
|
114
|
+
follows both themes. -->
|
|
112
115
|
<v-btn
|
|
113
116
|
v-if="canUpdate && canUpdateOnlineFormConfiguration"
|
|
114
117
|
icon
|
|
115
118
|
size="small"
|
|
116
119
|
variant="text"
|
|
117
|
-
color="white"
|
|
118
120
|
@click="openEditDialog()"
|
|
119
121
|
>
|
|
120
122
|
<v-icon>mdi-pencil</v-icon>
|
|
@@ -133,34 +135,38 @@
|
|
|
133
135
|
</OnlineFormFill>
|
|
134
136
|
|
|
135
137
|
<!-- Fallback: no block definition found for this form type -->
|
|
136
|
-
<v-card v-else width="100%">
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
</
|
|
143
|
-
<
|
|
144
|
-
<v-btn
|
|
138
|
+
<v-card v-else class="screen-modal" width="100%">
|
|
139
|
+
<!-- The design's empty block, the same one every other "nothing to
|
|
140
|
+
show here" surface in the layer draws. -->
|
|
141
|
+
<div class="screen-empty">
|
|
142
|
+
<v-icon size="48">mdi-file-question-outline</v-icon>
|
|
143
|
+
<div>No preview available for "{{ selectedFormType }}".</div>
|
|
144
|
+
</div>
|
|
145
|
+
<div class="screen-modal__footer">
|
|
146
|
+
<v-btn variant="outlined" class="screen-btn-ghost" @click="previewDialog = false">
|
|
145
147
|
Close
|
|
146
148
|
</v-btn>
|
|
147
|
-
</
|
|
149
|
+
</div>
|
|
148
150
|
</v-card>
|
|
149
151
|
</v-dialog>
|
|
150
152
|
|
|
151
153
|
<!-- Delete Dialog -->
|
|
154
|
+
<!-- 520px is the handoff's `--modal-w`. The two `v-toolbar`s this drew for
|
|
155
|
+
its title row and its footer were Vuetify `surface` slabs - a visible
|
|
156
|
+
grey bar on the dark card; a `v-card-title` and the shared
|
|
157
|
+
`.screen-modal__footer` are the same rows on the card's own surface.
|
|
158
|
+
The confirming button was a hardcoded `color="black"` fill, the same
|
|
159
|
+
black on both themes. -->
|
|
152
160
|
<v-dialog
|
|
153
161
|
v-model="confirmDialog"
|
|
154
162
|
:loading="deleteLoading"
|
|
155
|
-
width="
|
|
163
|
+
width="520"
|
|
156
164
|
persistent
|
|
157
165
|
>
|
|
158
|
-
<v-card width="100%">
|
|
159
|
-
<v-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
<v-card-text>
|
|
163
|
-
<p class="text-subtitle-2 text-center">
|
|
166
|
+
<v-card class="screen-modal" width="100%">
|
|
167
|
+
<v-card-title>Delete Online Form</v-card-title>
|
|
168
|
+
<v-card-text class="screen-modal__body">
|
|
169
|
+
<p class="text-center">
|
|
164
170
|
Are you sure you want to delete this online form? This action cannot
|
|
165
171
|
be undone.
|
|
166
172
|
</p>
|
|
@@ -171,38 +177,25 @@
|
|
|
171
177
|
</span>
|
|
172
178
|
</v-row>
|
|
173
179
|
</v-card-text>
|
|
174
|
-
<
|
|
175
|
-
<v-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
size="48"
|
|
194
|
-
color="black"
|
|
195
|
-
variant="flat"
|
|
196
|
-
class="text-none"
|
|
197
|
-
:loading="deleteLoading"
|
|
198
|
-
:disabled="deleteLoading"
|
|
199
|
-
@click="handleDeleteOnlineFormConfiguration()"
|
|
200
|
-
>
|
|
201
|
-
Delete Online Form
|
|
202
|
-
</v-btn>
|
|
203
|
-
</v-col>
|
|
204
|
-
</v-row>
|
|
205
|
-
</v-toolbar>
|
|
180
|
+
<div class="screen-modal__footer">
|
|
181
|
+
<v-btn
|
|
182
|
+
variant="outlined"
|
|
183
|
+
class="screen-btn-ghost"
|
|
184
|
+
:disabled="deleteLoading"
|
|
185
|
+
@click="confirmDialog = false"
|
|
186
|
+
>
|
|
187
|
+
Close
|
|
188
|
+
</v-btn>
|
|
189
|
+
<v-btn
|
|
190
|
+
variant="flat"
|
|
191
|
+
class="screen-btn-primary"
|
|
192
|
+
:loading="deleteLoading"
|
|
193
|
+
:disabled="deleteLoading"
|
|
194
|
+
@click="handleDeleteOnlineFormConfiguration()"
|
|
195
|
+
>
|
|
196
|
+
Delete Online Form
|
|
197
|
+
</v-btn>
|
|
198
|
+
</div>
|
|
206
199
|
</v-card>
|
|
207
200
|
</v-dialog>
|
|
208
201
|
|
|
@@ -433,4 +426,12 @@ function successUpdate() {
|
|
|
433
426
|
.online-forms-config__search {
|
|
434
427
|
max-width: 240px;
|
|
435
428
|
}
|
|
429
|
+
|
|
430
|
+
/* The sort toggle is the only control on this toolbar with an on/off state.
|
|
431
|
+
`--accent-strong` is the design's own accent; the icon button has no
|
|
432
|
+
"selected" variant, so the state is one declaration rather than a variant
|
|
433
|
+
nothing else would use. */
|
|
434
|
+
.online-forms-config__sort--on {
|
|
435
|
+
color: var(--accent-strong);
|
|
436
|
+
}
|
|
436
437
|
</style>
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@7365admin1/layer-common",
|
|
3
3
|
"license": "MIT",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "3.2.2-staging.
|
|
5
|
+
"version": "3.2.2-staging.161",
|
|
6
6
|
"author": "7365admin1",
|
|
7
7
|
"main": "./nuxt.config.ts",
|
|
8
8
|
"//files": "What a consumer extending this layer actually loads. Without this npm ships the whole working tree - the changesets, the CI workflows, the render harness in tools/ and any scratch directory that happened to exist at publish time. Nuxt resolves a layer by directory, so every runtime directory below has to stay listed; adding a new top-level runtime directory means adding it here too.",
|
package/utils/status.ts
CHANGED
|
@@ -58,6 +58,11 @@ const TONES: Record<string, TStatusTone> = {
|
|
|
58
58
|
resolved: "ok", // was #4CAF50, green
|
|
59
59
|
active: "ok", // was `success`
|
|
60
60
|
|
|
61
|
+
// An online-form submission sent back to the resident to correct and send
|
|
62
|
+
// again. Unlisted it would come out neutral, which would make "needs your
|
|
63
|
+
// attention" look the same as "nothing is happening".
|
|
64
|
+
resubmission: "warn",
|
|
65
|
+
|
|
61
66
|
assigned: "info", // was `primary`, on the access-card details dialog
|
|
62
67
|
replaced: "warn", // was `orange`, same screen
|
|
63
68
|
returned: "warn", // was `orange`, same screen - the card came back
|