@7365admin1/layer-common 4.97.1-staging.591 → 4.97.1-staging.593
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.
|
@@ -68,6 +68,8 @@
|
|
|
68
68
|
-->
|
|
69
69
|
<!-- "Admin · St. Regis Residences": names are unique per site (2026-10-01) -->
|
|
70
70
|
<template #item.name="{ item }">{{ roleLabel(item) }}</template>
|
|
71
|
+
<!-- "App" column: plain app name, not the stored code (security_agency) -->
|
|
72
|
+
<template #item.type="{ item }">{{ roleAppLabel(item.type) }}</template>
|
|
71
73
|
<template #item.scope="{ item }">
|
|
72
74
|
<StatusChip
|
|
73
75
|
:dot="false"
|
|
@@ -214,7 +216,7 @@
|
|
|
214
216
|
|
|
215
217
|
<script setup lang="ts">
|
|
216
218
|
// Relative import: this layer's `utils/` is not auto-imported into consumers.
|
|
217
|
-
import { roleLabel, safeReturnTo, showSiteField, sitePickerRoleLabel } from "../utils/role";
|
|
219
|
+
import { roleAppLabel, roleLabel, safeReturnTo, showSiteField, sitePickerRoleLabel } from "../utils/role";
|
|
218
220
|
import { holdsPermission } from "../utils/permission-spellings";
|
|
219
221
|
import { countRealPermissions } from "../utils/security-catalogue";
|
|
220
222
|
import {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
ADD / EDIT AN EXTRA CHECK - four short steps: What, Where, When, Who is told.
|
|
3
3
|
|
|
4
4
|
The last step shows one sentence saying exactly what will be created
|
|
5
|
-
("Adds 1 extra check to 3 areas (24 units) at 08:00 every weekday ... next:
|
|
5
|
+
("Adds 1 extra check to each of 3 areas (24 units) at 08:00 every weekday ... next:
|
|
6
6
|
Wed 21 Oct"). The form checks what the server checks (utils/schedule-task.ts)
|
|
7
7
|
so a schedule that would never run is caught before saving; whatever the
|
|
8
8
|
server still refuses is shown in its own words.
|
|
@@ -85,8 +85,10 @@
|
|
|
85
85
|
<v-stepper-window-item :value="2">
|
|
86
86
|
<div class="st-step">
|
|
87
87
|
<p class="st-step__help">
|
|
88
|
-
Pick the areas to check.
|
|
89
|
-
one
|
|
88
|
+
Pick the areas to check. Each time this check is due, every
|
|
89
|
+
picked area gets exactly one extra round on the Daily
|
|
90
|
+
Checklist (one more tick box per unit) - one round, however
|
|
91
|
+
many normal visits the area has each day.
|
|
90
92
|
</p>
|
|
91
93
|
<InputLabel for="selected-areas" title="Areas" required />
|
|
92
94
|
<v-select
|
|
@@ -16,9 +16,11 @@
|
|
|
16
16
|
that.
|
|
17
17
|
</li>
|
|
18
18
|
<li>
|
|
19
|
-
An <strong>extra check</strong> adds one more round of
|
|
20
|
-
that checklist
|
|
21
|
-
or repeating (every day, weekdays,
|
|
19
|
+
An <strong>extra check</strong> adds exactly one more round of
|
|
20
|
+
ticks to that checklist each time it is due, in the areas you pick,
|
|
21
|
+
at the time you set - once, or repeating (every day, weekdays,
|
|
22
|
+
chosen days, or monthly). One extra check is one round per area,
|
|
23
|
+
however many normal visits that area has each day.
|
|
22
24
|
</li>
|
|
23
25
|
<li>
|
|
24
26
|
At that time, staff get a phone notification and see the extra
|
|
@@ -163,7 +163,11 @@
|
|
|
163
163
|
"
|
|
164
164
|
value="toggle-status"
|
|
165
165
|
class="text-body-2"
|
|
166
|
-
@click="
|
|
166
|
+
@click="
|
|
167
|
+
item.status === 'active'
|
|
168
|
+
? (planToDeactivate = item)
|
|
169
|
+
: togglePlanStatus(item)
|
|
170
|
+
"
|
|
167
171
|
/>
|
|
168
172
|
</v-list>
|
|
169
173
|
</v-card>
|
|
@@ -197,6 +201,32 @@
|
|
|
197
201
|
/>
|
|
198
202
|
</v-dialog>
|
|
199
203
|
|
|
204
|
+
<ConfirmDialog
|
|
205
|
+
:model-value="!!planToDeactivate"
|
|
206
|
+
@update:model-value="(v: boolean) => { if (!v) planToDeactivate = null; }"
|
|
207
|
+
>
|
|
208
|
+
<template #title>Deactivate plan</template>
|
|
209
|
+
<template #description>
|
|
210
|
+
Deactivate {{ planToDeactivate?.name || "this plan" }}? You can activate
|
|
211
|
+
it again from the Deactivated tab.
|
|
212
|
+
</template>
|
|
213
|
+
<template #footer>
|
|
214
|
+
<v-spacer />
|
|
215
|
+
<v-btn
|
|
216
|
+
variant="outlined"
|
|
217
|
+
:disabled="isDeactivating"
|
|
218
|
+
@click="planToDeactivate = null"
|
|
219
|
+
>Cancel</v-btn
|
|
220
|
+
>
|
|
221
|
+
<v-btn
|
|
222
|
+
color="error"
|
|
223
|
+
variant="flat"
|
|
224
|
+
:loading="isDeactivating"
|
|
225
|
+
@click="confirmDeactivate"
|
|
226
|
+
>Deactivate</v-btn
|
|
227
|
+
>
|
|
228
|
+
</template>
|
|
229
|
+
</ConfirmDialog>
|
|
200
230
|
<Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" />
|
|
201
231
|
</v-container>
|
|
202
232
|
</template>
|
|
@@ -417,6 +447,20 @@ async function handleSubmit(payload: PlanFormState) {
|
|
|
417
447
|
}
|
|
418
448
|
}
|
|
419
449
|
|
|
450
|
+
// Deactivate asks first; Activate stays one tap.
|
|
451
|
+
const planToDeactivate = ref<SubscriptionPlan | null>(null);
|
|
452
|
+
const isDeactivating = ref(false);
|
|
453
|
+
async function confirmDeactivate() {
|
|
454
|
+
if (!planToDeactivate.value) return;
|
|
455
|
+
isDeactivating.value = true;
|
|
456
|
+
try {
|
|
457
|
+
await togglePlanStatus(planToDeactivate.value);
|
|
458
|
+
} finally {
|
|
459
|
+
isDeactivating.value = false;
|
|
460
|
+
planToDeactivate.value = null;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
420
464
|
async function togglePlanStatus(plan: SubscriptionPlan) {
|
|
421
465
|
const nextStatus = plan.status === "active" ? "deactive" : "active";
|
|
422
466
|
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@7365admin1/layer-common",
|
|
3
3
|
"license": "MIT",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "4.97.1-staging.
|
|
5
|
+
"version": "4.97.1-staging.593",
|
|
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/role.ts
CHANGED
|
@@ -158,3 +158,27 @@ export function siteAccessLabel(item: { limitedTo?: unknown } | null | undefined
|
|
|
158
158
|
const names = limitedSites(item).map((l) => l.siteName || "a site");
|
|
159
159
|
return names.length ? `Limited to: ${names.join(", ")}` : "All sites";
|
|
160
160
|
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* A role's `type` is the app it belongs to, stored as a code
|
|
164
|
+
* (`security_agency`). The roles table shows the app's plain name instead.
|
|
165
|
+
* An unknown code is shown with its underscores as spaces, never dropped.
|
|
166
|
+
*/
|
|
167
|
+
const ROLE_APP_LABELS: Readonly<Record<string, string>> = Object.freeze({
|
|
168
|
+
admin: "Super Admin",
|
|
169
|
+
organization: "Organization",
|
|
170
|
+
property_management_agency: "Property Management",
|
|
171
|
+
security_agency: "Security",
|
|
172
|
+
cleaning_services: "Cleaning",
|
|
173
|
+
mechanical_electrical_services: "Mechanical & Electrical",
|
|
174
|
+
pest_control_services: "Pest Control",
|
|
175
|
+
pool_maintenance_services: "Pool Maintenance",
|
|
176
|
+
landscaping_services: "Landscape",
|
|
177
|
+
resident: "Resident",
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
export function roleAppLabel(type: unknown): string {
|
|
181
|
+
const code = String(type ?? "").trim();
|
|
182
|
+
if (!code) return "";
|
|
183
|
+
return ROLE_APP_LABELS[code] ?? code.replace(/_/g, " ").replace(/^./, (c) => c.toUpperCase());
|
|
184
|
+
}
|
package/utils/schedule-task.ts
CHANGED
|
@@ -268,7 +268,8 @@ export function buildSummary(
|
|
|
268
268
|
now: Date = new Date(),
|
|
269
269
|
): string {
|
|
270
270
|
const year = sgtParts(now).date.slice(0, 4);
|
|
271
|
-
|
|
271
|
+
// One extra check = exactly one more round per picked area each time it runs (not one per normal visit).
|
|
272
|
+
const areas = f.areaCount === 1 ? "1 area" : `each of ${f.areaCount} areas`;
|
|
272
273
|
const units = `${unitCount} unit${unitCount === 1 ? "" : "s"}`;
|
|
273
274
|
const next = nextRunDate(f, now);
|
|
274
275
|
const nextText = next ? `${DAYS[weekdayOf(next)]} ${fmtDate(next, year)}` : "never";
|