@7365admin1/layer-common 3.1.0 → 3.1.2-staging.29
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/.github/workflows/publish-staging.yml +11 -0
- package/CHANGELOG.md +6 -0
- package/components/AddEqupmentForm.vue +52 -1
- package/components/AddPassKeyToVisitor.vue +115 -53
- package/components/DashboardMain.vue +231 -87
- package/components/EquipmentManagementMain.vue +56 -0
- package/components/InvitationMain.vue +4 -3
- package/components/ManageChecklistMain.vue +44 -38
- package/components/Nfc/NFCPatrolReportMain.vue +128 -38
- package/components/Nfc/PatrolReport/DailyReportTab.vue +10 -6
- package/components/Nfc/PatrolReport/MonthlyReportTab.vue +19 -9
- package/components/Nfc/PatrolReport/MonthlyReportTable.vue +69 -0
- package/components/Nfc/PatrolReport/PatrolReportTab.vue +5 -3
- package/components/Nfc/PatrolReport/ReportFilters.vue +50 -18
- package/components/PhotoUpload.vue +19 -4
- package/components/ServiceProviderMain.vue +46 -29
- package/components/VisitorForm.vue +3 -108
- package/components/VisitorManagement.vue +109 -30
- package/composables/useCleaningSchedulePermission.ts +16 -51
- package/composables/useEquipment.ts +2 -0
- package/composables/useLocalAuth.ts +1 -1
- package/composables/useNFCPatrolDailyReport.ts +1 -4
- package/composables/useNFCPatrolMonthlyReport.ts +62 -30
- package/package.json +1 -1
- package/types/customer.d.ts +2 -1
- package/types/equipment.d.ts +5 -1
- package/types/nfc-patrol-report.ts +15 -1
|
@@ -984,60 +984,44 @@
|
|
|
984
984
|
<div
|
|
985
985
|
v-for="item in formattedActivePatrolItems"
|
|
986
986
|
:key="item.id || item._id"
|
|
987
|
-
class="
|
|
988
|
-
style="
|
|
989
|
-
padding: 16px 20px;
|
|
990
|
-
border: 1px solid #e2e8f0;
|
|
991
|
-
border-radius: 12px;
|
|
992
|
-
margin-bottom: 12px;
|
|
993
|
-
background-color: #ffffff;
|
|
994
|
-
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.02);
|
|
995
|
-
"
|
|
987
|
+
class="active-patrol-row"
|
|
996
988
|
>
|
|
997
|
-
<div
|
|
998
|
-
<strong
|
|
999
|
-
|
|
1000
|
-
display: block;
|
|
1001
|
-
font-size: 15px;
|
|
1002
|
-
font-weight: 700;
|
|
1003
|
-
color: #0b2f47;
|
|
1004
|
-
margin-bottom: 4px;
|
|
1005
|
-
"
|
|
1006
|
-
>{{ item.title || item.name }}</strong
|
|
1007
|
-
>
|
|
1008
|
-
<span style="font-size: 13px; color: #94a3b8">{{
|
|
1009
|
-
item.subtitle || item.location || ""
|
|
1010
|
-
}}</span>
|
|
989
|
+
<div class="active-patrol-main">
|
|
990
|
+
<strong>{{ item.title || item.name }}</strong>
|
|
991
|
+
<span>{{ item.subtitle || item.location || "" }}</span>
|
|
1011
992
|
</div>
|
|
1012
993
|
|
|
1013
|
-
<div
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
item.
|
|
1022
|
-
|
|
994
|
+
<div class="active-patrol-assignees">
|
|
995
|
+
<div class="active-patrol-assignee">
|
|
996
|
+
<AvatarMain :name="item.primaryAssignee" :size="24" />
|
|
997
|
+
<span>{{ item.primaryAssignee }}</span>
|
|
998
|
+
</div>
|
|
999
|
+
<span
|
|
1000
|
+
v-if="item.extraAssigneeCount > 0"
|
|
1001
|
+
class="active-patrol-more-pill active-patrol-tooltip"
|
|
1002
|
+
:data-tooltip="item.extraAssignees.join(', ')"
|
|
1003
|
+
>
|
|
1004
|
+
+{{ item.extraAssigneeCount }}
|
|
1005
|
+
</span>
|
|
1023
1006
|
</div>
|
|
1024
1007
|
|
|
1025
|
-
<div
|
|
1008
|
+
<div class="active-patrol-statuses">
|
|
1026
1009
|
<div
|
|
1027
|
-
|
|
1028
|
-
style="
|
|
1029
|
-
padding: 6px 16px;
|
|
1030
|
-
border-radius: 20px;
|
|
1031
|
-
font-size: 13px;
|
|
1032
|
-
font-weight: 500;
|
|
1033
|
-
text-transform: capitalize;
|
|
1034
|
-
"
|
|
1010
|
+
class="active-patrol-status-pill"
|
|
1011
|
+
:style="getPatrolStatusStyle(item.primaryStatus)"
|
|
1035
1012
|
>
|
|
1036
|
-
{{ item.
|
|
1013
|
+
{{ item.primaryStatus }}
|
|
1037
1014
|
</div>
|
|
1015
|
+
<span
|
|
1016
|
+
v-if="item.extraStatusCount > 0"
|
|
1017
|
+
class="active-patrol-more-pill active-patrol-tooltip"
|
|
1018
|
+
:data-tooltip="item.extraStatuses.join(', ')"
|
|
1019
|
+
>
|
|
1020
|
+
+{{ item.extraStatusCount }}
|
|
1021
|
+
</span>
|
|
1038
1022
|
</div>
|
|
1039
1023
|
|
|
1040
|
-
<div
|
|
1024
|
+
<div class="active-patrol-action">
|
|
1041
1025
|
<v-btn
|
|
1042
1026
|
variant="outlined"
|
|
1043
1027
|
class="text-none font-weight-medium"
|
|
@@ -1545,30 +1529,16 @@ const { userAppRole } = useLocalSetup();
|
|
|
1545
1529
|
const { downloadPDF } = usePDFDownload();
|
|
1546
1530
|
const route = useRoute();
|
|
1547
1531
|
|
|
1548
|
-
const dashboardWidgetPermissions: Record<string, string> = {
|
|
1549
|
-
activity: "dashboard:view-activity",
|
|
1550
|
-
recentActivity: "dashboard:view-activity",
|
|
1551
|
-
taskSchedule: "dashboard:view-task-schedule",
|
|
1552
|
-
staffStatus: "dashboard:view-attendance-widget",
|
|
1553
|
-
attendance: "dashboard:view-attendance-widget",
|
|
1554
|
-
feedbacks: "dashboard:view-feedbacks-widget",
|
|
1555
|
-
workOrderStatus: "dashboard:view-work-order-status",
|
|
1556
|
-
activePatrol: "dashboard:view-active-patrol",
|
|
1557
|
-
upcomingEvents: "dashboard:view-upcoming-events",
|
|
1558
|
-
todayReminders: "dashboard:view-today-reminders",
|
|
1559
|
-
todayAttentions: "dashboard:view-today-attentions",
|
|
1560
|
-
};
|
|
1561
|
-
|
|
1562
1532
|
const propertyWidgetPermissions: Record<string, string[]> = {
|
|
1563
1533
|
workOrders: [
|
|
1564
|
-
"
|
|
1534
|
+
"work_orders:see-all-work-orders",
|
|
1565
1535
|
"work-order:see-all-work-orders",
|
|
1566
1536
|
],
|
|
1567
1537
|
incidents: ["incident-reports:see-incident-reports"],
|
|
1568
1538
|
visitors: ["visitorManagement:see-all-visitor"],
|
|
1569
1539
|
facilityBookings: ["facility-booking-mgmt:see-all-facility-booking"],
|
|
1570
1540
|
activity: [
|
|
1571
|
-
"
|
|
1541
|
+
"work_orders:see-all-work-orders",
|
|
1572
1542
|
"work-order:see-all-work-orders",
|
|
1573
1543
|
],
|
|
1574
1544
|
upcomingEvents: ["event-mgmt:see-all-event"],
|
|
@@ -1578,7 +1548,7 @@ const propertyWidgetPermissions: Record<string, string[]> = {
|
|
|
1578
1548
|
"facility-booking-mgmt:see-all-facility-booking",
|
|
1579
1549
|
],
|
|
1580
1550
|
workOrderStatus: [
|
|
1581
|
-
"
|
|
1551
|
+
"work_orders:see-all-work-orders",
|
|
1582
1552
|
"work-order:see-all-work-orders",
|
|
1583
1553
|
],
|
|
1584
1554
|
feedbacks: ["feedbacks:see-all-feedback"],
|
|
@@ -1587,27 +1557,30 @@ const propertyWidgetPermissions: Record<string, string[]> = {
|
|
|
1587
1557
|
|
|
1588
1558
|
const moduleWidgetPermissions: Record<string, string[]> = {
|
|
1589
1559
|
openWorkOrder: [
|
|
1560
|
+
"work_orders:see-all-work-orders",
|
|
1590
1561
|
"work_order:see-all-work-orders",
|
|
1591
1562
|
"work-order:see-all-work-orders",
|
|
1592
1563
|
"work-orders:see-all-work-orders",
|
|
1593
1564
|
],
|
|
1594
1565
|
workOrders: [
|
|
1566
|
+
"work_orders:see-all-work-orders",
|
|
1595
1567
|
"work_order:see-all-work-orders",
|
|
1596
1568
|
"work-order:see-all-work-orders",
|
|
1597
1569
|
"work-orders:see-all-work-orders",
|
|
1598
1570
|
],
|
|
1599
1571
|
activity: [
|
|
1572
|
+
"work_orders:see-all-work-orders",
|
|
1600
1573
|
"work_order:see-all-work-orders",
|
|
1601
1574
|
"work-order:see-all-work-orders",
|
|
1602
1575
|
"work-orders:see-all-work-orders",
|
|
1576
|
+
"work_orders:see-all-work-orders",
|
|
1603
1577
|
],
|
|
1604
|
-
|
|
1605
|
-
"
|
|
1606
|
-
"
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
"
|
|
1610
|
-
"schedule-task-mgmt:see-all-schedule-tasks",
|
|
1578
|
+
recentActivity: [
|
|
1579
|
+
"work_orders:see-all-work-orders",
|
|
1580
|
+
"work_order:see-all-work-orders",
|
|
1581
|
+
"work-order:see-all-work-orders",
|
|
1582
|
+
"work-orders:see-all-work-orders",
|
|
1583
|
+
"work_orders:see-all-work-orders",
|
|
1611
1584
|
],
|
|
1612
1585
|
staffStatus: ["attendance-mgmt:see-all-attendance"],
|
|
1613
1586
|
attendance: ["attendance-mgmt:see-all-attendance"],
|
|
@@ -1630,9 +1603,14 @@ const moduleWidgetPermissions: Record<string, string[]> = {
|
|
|
1630
1603
|
activePatrol: ["virtual-patrol:see-all-virtual-patrol-logs"],
|
|
1631
1604
|
};
|
|
1632
1605
|
|
|
1606
|
+
function hasSchedulePermission(permissions: string[], action: string) {
|
|
1607
|
+
return permissions.some((permission) =>
|
|
1608
|
+
permission.endsWith(`-schedule-mgmt:${action}`)
|
|
1609
|
+
);
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1633
1612
|
function canViewWidget(key: string) {
|
|
1634
1613
|
const permissions = userAppRole.value?.permissions;
|
|
1635
|
-
const dashboardPermission = dashboardWidgetPermissions[key];
|
|
1636
1614
|
const modulePermissions = isPropertyMode.value
|
|
1637
1615
|
? propertyWidgetPermissions[key]
|
|
1638
1616
|
: moduleWidgetPermissions[key];
|
|
@@ -1640,20 +1618,22 @@ function canViewWidget(key: string) {
|
|
|
1640
1618
|
if (!permissions) return true;
|
|
1641
1619
|
if (permissions.includes("*")) return true;
|
|
1642
1620
|
|
|
1621
|
+
if (
|
|
1622
|
+
!isPropertyMode.value &&
|
|
1623
|
+
["taskSchedule", "taskCompleted"].includes(key)
|
|
1624
|
+
) {
|
|
1625
|
+
return hasSchedulePermission(permissions, "see-all-schedules");
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1643
1628
|
if (isPropertyMode.value && modulePermissions) {
|
|
1644
1629
|
return modulePermissions.some((permission) =>
|
|
1645
1630
|
permissions.includes(permission)
|
|
1646
1631
|
);
|
|
1647
1632
|
}
|
|
1648
1633
|
|
|
1649
|
-
if (
|
|
1650
|
-
return (
|
|
1651
|
-
|
|
1652
|
-
Boolean(
|
|
1653
|
-
modulePermissions?.some((permission) =>
|
|
1654
|
-
permissions.includes(permission)
|
|
1655
|
-
)
|
|
1656
|
-
)
|
|
1634
|
+
if (modulePermissions) {
|
|
1635
|
+
return modulePermissions.some((permission) =>
|
|
1636
|
+
permissions.includes(permission)
|
|
1657
1637
|
);
|
|
1658
1638
|
}
|
|
1659
1639
|
|
|
@@ -2771,18 +2751,23 @@ const activePatrolItems = computed<any[]>(
|
|
|
2771
2751
|
|
|
2772
2752
|
const formattedActivePatrolItems = computed<any[]>(() => {
|
|
2773
2753
|
return activePatrolItems.value.map((item) => {
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
if (Array.isArray(person)) {
|
|
2780
|
-
person = person.join(", ");
|
|
2781
|
-
}
|
|
2754
|
+
const statuses = normalizeListValue(item.status || "Pending");
|
|
2755
|
+
const assignees = normalizeListValue(
|
|
2756
|
+
item.person || item.assignedTo || "Unassigned"
|
|
2757
|
+
);
|
|
2758
|
+
|
|
2782
2759
|
return {
|
|
2783
2760
|
...item,
|
|
2784
|
-
status,
|
|
2785
|
-
|
|
2761
|
+
status: statuses.join(", "),
|
|
2762
|
+
statuses,
|
|
2763
|
+
primaryStatus: statuses[0] || "Pending",
|
|
2764
|
+
extraStatuses: statuses.slice(1),
|
|
2765
|
+
extraStatusCount: Math.max(0, statuses.length - 1),
|
|
2766
|
+
person: assignees.join(", "),
|
|
2767
|
+
assignees,
|
|
2768
|
+
primaryAssignee: assignees[0] || "Unassigned",
|
|
2769
|
+
extraAssignees: assignees.slice(1),
|
|
2770
|
+
extraAssigneeCount: Math.max(0, assignees.length - 1),
|
|
2786
2771
|
};
|
|
2787
2772
|
});
|
|
2788
2773
|
});
|
|
@@ -3952,6 +3937,20 @@ function normalizeStatus(value: any) {
|
|
|
3952
3937
|
return text.replace(/[_-]+/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
3953
3938
|
}
|
|
3954
3939
|
|
|
3940
|
+
function normalizeListValue(value: any) {
|
|
3941
|
+
if (Array.isArray(value)) {
|
|
3942
|
+
return value
|
|
3943
|
+
.flatMap((entry) => normalizeListValue(entry))
|
|
3944
|
+
.map((entry) => String(entry).trim())
|
|
3945
|
+
.filter(Boolean);
|
|
3946
|
+
}
|
|
3947
|
+
|
|
3948
|
+
return String(value || "")
|
|
3949
|
+
.split(",")
|
|
3950
|
+
.map((entry) => entry.trim())
|
|
3951
|
+
.filter(Boolean);
|
|
3952
|
+
}
|
|
3953
|
+
|
|
3955
3954
|
function getStatusTone(status: any) {
|
|
3956
3955
|
const s = String(status || "").toLowerCase();
|
|
3957
3956
|
if (
|
|
@@ -4419,6 +4418,151 @@ function formatDashboardTime(value?: string) {
|
|
|
4419
4418
|
border: 2px solid #f9c97c;
|
|
4420
4419
|
}
|
|
4421
4420
|
|
|
4421
|
+
.active-patrol-row {
|
|
4422
|
+
align-items: center;
|
|
4423
|
+
background-color: #ffffff;
|
|
4424
|
+
border: 1px solid #e2e8f0;
|
|
4425
|
+
border-radius: 8px;
|
|
4426
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.02);
|
|
4427
|
+
display: grid;
|
|
4428
|
+
gap: 10px;
|
|
4429
|
+
grid-template-columns: 150px minmax(0, 1fr) max-content max-content;
|
|
4430
|
+
margin-bottom: 12px;
|
|
4431
|
+
min-height: 64px;
|
|
4432
|
+
overflow: visible;
|
|
4433
|
+
padding: 12px 14px;
|
|
4434
|
+
}
|
|
4435
|
+
|
|
4436
|
+
.active-patrol-main {
|
|
4437
|
+
min-width: 0;
|
|
4438
|
+
}
|
|
4439
|
+
|
|
4440
|
+
.active-patrol-main strong {
|
|
4441
|
+
color: #0b2f47;
|
|
4442
|
+
display: block;
|
|
4443
|
+
font-size: 13px;
|
|
4444
|
+
font-weight: 700;
|
|
4445
|
+
line-height: 1.25;
|
|
4446
|
+
margin-bottom: 3px;
|
|
4447
|
+
overflow-wrap: anywhere;
|
|
4448
|
+
}
|
|
4449
|
+
|
|
4450
|
+
.active-patrol-main span {
|
|
4451
|
+
color: #94a3b8;
|
|
4452
|
+
display: block;
|
|
4453
|
+
font-size: 11px;
|
|
4454
|
+
line-height: 1.25;
|
|
4455
|
+
overflow-wrap: anywhere;
|
|
4456
|
+
}
|
|
4457
|
+
|
|
4458
|
+
.active-patrol-assignees {
|
|
4459
|
+
align-items: center;
|
|
4460
|
+
display: flex;
|
|
4461
|
+
gap: 6px;
|
|
4462
|
+
min-width: 0;
|
|
4463
|
+
}
|
|
4464
|
+
|
|
4465
|
+
.active-patrol-assignee {
|
|
4466
|
+
align-items: center;
|
|
4467
|
+
background: #f8fafc;
|
|
4468
|
+
border: 1px solid #e7edf3;
|
|
4469
|
+
border-radius: 999px;
|
|
4470
|
+
display: inline-flex;
|
|
4471
|
+
flex: 1 1 auto;
|
|
4472
|
+
gap: 6px;
|
|
4473
|
+
max-width: 100%;
|
|
4474
|
+
min-width: 0;
|
|
4475
|
+
padding: 2px 8px 2px 3px;
|
|
4476
|
+
}
|
|
4477
|
+
|
|
4478
|
+
.active-patrol-assignee span {
|
|
4479
|
+
color: #475569;
|
|
4480
|
+
font-size: 11px;
|
|
4481
|
+
font-weight: 600;
|
|
4482
|
+
line-height: 1.2;
|
|
4483
|
+
min-width: 0;
|
|
4484
|
+
overflow: hidden;
|
|
4485
|
+
text-overflow: ellipsis;
|
|
4486
|
+
white-space: nowrap;
|
|
4487
|
+
}
|
|
4488
|
+
|
|
4489
|
+
.active-patrol-statuses {
|
|
4490
|
+
align-items: center;
|
|
4491
|
+
display: flex;
|
|
4492
|
+
gap: 6px;
|
|
4493
|
+
justify-content: flex-start;
|
|
4494
|
+
min-width: 0;
|
|
4495
|
+
}
|
|
4496
|
+
|
|
4497
|
+
.active-patrol-status-pill {
|
|
4498
|
+
border-radius: 20px;
|
|
4499
|
+
font-size: 11px;
|
|
4500
|
+
font-weight: 600;
|
|
4501
|
+
line-height: 1.2;
|
|
4502
|
+
padding: 5px 10px;
|
|
4503
|
+
text-transform: capitalize;
|
|
4504
|
+
white-space: nowrap;
|
|
4505
|
+
}
|
|
4506
|
+
|
|
4507
|
+
.active-patrol-more-pill {
|
|
4508
|
+
align-items: center;
|
|
4509
|
+
background: #eef3f8;
|
|
4510
|
+
border: 1px solid #dbe4ed;
|
|
4511
|
+
border-radius: 999px;
|
|
4512
|
+
color: #607386;
|
|
4513
|
+
display: inline-flex;
|
|
4514
|
+
flex: 0 0 auto;
|
|
4515
|
+
font-size: 11px;
|
|
4516
|
+
font-weight: 800;
|
|
4517
|
+
height: 24px;
|
|
4518
|
+
justify-content: center;
|
|
4519
|
+
line-height: 1;
|
|
4520
|
+
min-width: 30px;
|
|
4521
|
+
padding: 0 8px;
|
|
4522
|
+
position: relative;
|
|
4523
|
+
white-space: nowrap;
|
|
4524
|
+
}
|
|
4525
|
+
|
|
4526
|
+
.active-patrol-action {
|
|
4527
|
+
justify-self: end;
|
|
4528
|
+
text-align: right;
|
|
4529
|
+
}
|
|
4530
|
+
|
|
4531
|
+
.active-patrol-tooltip::after {
|
|
4532
|
+
background: #0f2638;
|
|
4533
|
+
border-radius: 6px;
|
|
4534
|
+
bottom: calc(100% + 8px);
|
|
4535
|
+
box-shadow: 0 8px 24px rgba(15, 38, 56, 0.18);
|
|
4536
|
+
color: #ffffff;
|
|
4537
|
+
content: attr(data-tooltip);
|
|
4538
|
+
font-size: 11px;
|
|
4539
|
+
font-weight: 600;
|
|
4540
|
+
left: 50%;
|
|
4541
|
+
line-height: 1.35;
|
|
4542
|
+
max-width: 260px;
|
|
4543
|
+
opacity: 0;
|
|
4544
|
+
padding: 7px 9px;
|
|
4545
|
+
pointer-events: none;
|
|
4546
|
+
position: absolute;
|
|
4547
|
+
text-align: left;
|
|
4548
|
+
transform: translate(-50%, 4px);
|
|
4549
|
+
transition: opacity 0.14s ease, transform 0.14s ease;
|
|
4550
|
+
white-space: normal;
|
|
4551
|
+
width: max-content;
|
|
4552
|
+
z-index: 5;
|
|
4553
|
+
}
|
|
4554
|
+
|
|
4555
|
+
.active-patrol-tooltip:hover::after {
|
|
4556
|
+
opacity: 1;
|
|
4557
|
+
transform: translate(-50%, 0);
|
|
4558
|
+
}
|
|
4559
|
+
|
|
4560
|
+
@media (max-width: 960px) {
|
|
4561
|
+
.active-patrol-row {
|
|
4562
|
+
grid-template-columns: 120px minmax(0, 1fr) max-content max-content;
|
|
4563
|
+
}
|
|
4564
|
+
}
|
|
4565
|
+
|
|
4422
4566
|
.figma-icon-badge {
|
|
4423
4567
|
align-items: center;
|
|
4424
4568
|
border-radius: 50%;
|
|
@@ -46,6 +46,19 @@
|
|
|
46
46
|
</v-row>
|
|
47
47
|
</template>
|
|
48
48
|
|
|
49
|
+
<template #item.attachment="{ value }">
|
|
50
|
+
<v-btn
|
|
51
|
+
v-if="value"
|
|
52
|
+
size="small"
|
|
53
|
+
variant="tonal"
|
|
54
|
+
class="text-none"
|
|
55
|
+
@click.stop="viewAttachment(value)"
|
|
56
|
+
>
|
|
57
|
+
View Image
|
|
58
|
+
</v-btn>
|
|
59
|
+
<span v-else>—</span>
|
|
60
|
+
</template>
|
|
61
|
+
|
|
49
62
|
<template #item.status="{ value }">
|
|
50
63
|
<v-chip class="text-capitalize">{{ value || "N/A" }}</v-chip>
|
|
51
64
|
</template>
|
|
@@ -61,6 +74,7 @@
|
|
|
61
74
|
v-model="dialogShowForm"
|
|
62
75
|
v-model:name="equipmentName"
|
|
63
76
|
v-model:unitOfMeasurement="equipmentUnit"
|
|
77
|
+
v-model:attachment="equipmentAttachment"
|
|
64
78
|
:mode="dialogMode"
|
|
65
79
|
:equipmentData="editingEquipment"
|
|
66
80
|
:site="props.site"
|
|
@@ -242,6 +256,29 @@
|
|
|
242
256
|
</v-card>
|
|
243
257
|
</v-dialog>
|
|
244
258
|
|
|
259
|
+
<v-dialog v-model="showAttachmentDialog" max-width="720" persistent>
|
|
260
|
+
<v-card rounded="lg">
|
|
261
|
+
<v-card-title class="d-flex align-center pa-4">
|
|
262
|
+
<span class="text-h6 font-weight-bold">Attachment</span>
|
|
263
|
+
|
|
264
|
+
<v-spacer />
|
|
265
|
+
|
|
266
|
+
<v-btn
|
|
267
|
+
icon="mdi-close"
|
|
268
|
+
variant="text"
|
|
269
|
+
size="small"
|
|
270
|
+
@click="(showAttachmentDialog = false), (attachmentUrl = '')"
|
|
271
|
+
/>
|
|
272
|
+
</v-card-title>
|
|
273
|
+
|
|
274
|
+
<v-divider />
|
|
275
|
+
|
|
276
|
+
<v-card-text class="pa-6">
|
|
277
|
+
<v-img :src="attachmentUrl" contain />
|
|
278
|
+
</v-card-text>
|
|
279
|
+
</v-card>
|
|
280
|
+
</v-dialog>
|
|
281
|
+
|
|
245
282
|
<Snackbar
|
|
246
283
|
v-model="messageSnackbar"
|
|
247
284
|
:text="snackbarMessage"
|
|
@@ -253,6 +290,7 @@ import useEquipment from "../composables/useEquipment";
|
|
|
253
290
|
import useStock from "../composables/useStock";
|
|
254
291
|
import useUtils from "../composables/useUtils";
|
|
255
292
|
import useEquipmentManagement from "../composables/useEquipmentManagement";
|
|
293
|
+
import useFile from "../composables/useFile";
|
|
256
294
|
|
|
257
295
|
const props = defineProps({
|
|
258
296
|
orgId: { type: String, default: "" },
|
|
@@ -280,6 +318,7 @@ const siteName = ref<string>("");
|
|
|
280
318
|
const submitting = ref(false);
|
|
281
319
|
|
|
282
320
|
const headers = [
|
|
321
|
+
{ title: "Image", value: "attachment" },
|
|
283
322
|
{ title: "Name", value: "name" },
|
|
284
323
|
{ title: "Available Stock Qty", value: "qty" },
|
|
285
324
|
{ title: "Status", value: "status" },
|
|
@@ -293,6 +332,7 @@ const {
|
|
|
293
332
|
deleteEquipment,
|
|
294
333
|
} = useEquipment();
|
|
295
334
|
const { debounce, requiredRule } = useUtils();
|
|
335
|
+
const { getFileUrl } = useFile();
|
|
296
336
|
|
|
297
337
|
const searchInput = ref("");
|
|
298
338
|
const startDate = ref("");
|
|
@@ -352,11 +392,21 @@ const dialogMode = ref<"add" | "edit">("add");
|
|
|
352
392
|
const editingEquipment = ref<Record<string, any>>({});
|
|
353
393
|
const equipmentName = ref("");
|
|
354
394
|
const equipmentUnit = ref("");
|
|
395
|
+
const equipmentAttachment = ref("");
|
|
355
396
|
|
|
356
397
|
const stockActionFormRef = ref<any>(null);
|
|
357
398
|
const stockActionValid = ref(false);
|
|
358
399
|
|
|
359
400
|
const snackbarMessage = ref("");
|
|
401
|
+
const showAttachmentDialog = ref(false);
|
|
402
|
+
const attachmentUrl = ref("");
|
|
403
|
+
|
|
404
|
+
function viewAttachment(attachmentId: string) {
|
|
405
|
+
if (!attachmentId) return;
|
|
406
|
+
|
|
407
|
+
attachmentUrl.value = getFileUrl(attachmentId);
|
|
408
|
+
showAttachmentDialog.value = true;
|
|
409
|
+
}
|
|
360
410
|
|
|
361
411
|
function showMessage(msg: string, color: string = "error") {
|
|
362
412
|
message.value = msg;
|
|
@@ -370,6 +420,7 @@ function onCreateUnit() {
|
|
|
370
420
|
editingEquipment.value = {};
|
|
371
421
|
equipmentName.value = "";
|
|
372
422
|
equipmentUnit.value = "";
|
|
423
|
+
equipmentAttachment.value = "";
|
|
373
424
|
dialogShowForm.value = true;
|
|
374
425
|
}
|
|
375
426
|
|
|
@@ -379,6 +430,9 @@ async function _createEquipment() {
|
|
|
379
430
|
const payload: TEquipmentCreate = {
|
|
380
431
|
name: equipmentName.value,
|
|
381
432
|
unitOfMeasurement: equipmentUnit.value,
|
|
433
|
+
...(equipmentAttachment.value
|
|
434
|
+
? { attachment: equipmentAttachment.value }
|
|
435
|
+
: {}),
|
|
382
436
|
};
|
|
383
437
|
|
|
384
438
|
let response;
|
|
@@ -398,6 +452,7 @@ async function _createEquipment() {
|
|
|
398
452
|
editingEquipment.value = {};
|
|
399
453
|
equipmentName.value = "";
|
|
400
454
|
equipmentUnit.value = "";
|
|
455
|
+
equipmentAttachment.value = "";
|
|
401
456
|
|
|
402
457
|
await getEquipmentsRefresh();
|
|
403
458
|
} catch (error: any) {
|
|
@@ -455,6 +510,7 @@ const onEditFromMoreAction = async () => {
|
|
|
455
510
|
editingEquipment.value = response;
|
|
456
511
|
equipmentName.value = response.name || "";
|
|
457
512
|
equipmentUnit.value = response.unitOfMeasurement || "";
|
|
513
|
+
equipmentAttachment.value = response.attachment || "";
|
|
458
514
|
dialogShowForm.value = true;
|
|
459
515
|
};
|
|
460
516
|
|
|
@@ -221,7 +221,7 @@ const headers = computed(() => {
|
|
|
221
221
|
title: "Status",
|
|
222
222
|
value: "status",
|
|
223
223
|
},
|
|
224
|
-
|
|
224
|
+
|
|
225
225
|
];
|
|
226
226
|
|
|
227
227
|
if (props.status === "pending" && props.cancelInvitation) {
|
|
@@ -270,10 +270,11 @@ const {
|
|
|
270
270
|
page: page.value,
|
|
271
271
|
status: props.status,
|
|
272
272
|
search: headerSearch.value,
|
|
273
|
-
type: "user-invite,member-invite",
|
|
273
|
+
// type: "user-invite,member-invite",
|
|
274
|
+
type: "member-invite",
|
|
274
275
|
app: props.app,
|
|
275
276
|
orgId: props.org,
|
|
276
|
-
siteId: props.siteId,
|
|
277
|
+
// siteId: props.siteId,
|
|
277
278
|
}),
|
|
278
279
|
{
|
|
279
280
|
watch: [() => props.status]
|
|
@@ -97,7 +97,10 @@
|
|
|
97
97
|
Rejected
|
|
98
98
|
</v-chip>
|
|
99
99
|
</div>
|
|
100
|
-
<div
|
|
100
|
+
<div
|
|
101
|
+
v-if="item.remarks"
|
|
102
|
+
class="text-body-2 text-medium-emphasis"
|
|
103
|
+
>
|
|
101
104
|
{{ item.remarks }}
|
|
102
105
|
</div>
|
|
103
106
|
<div
|
|
@@ -225,11 +228,7 @@
|
|
|
225
228
|
<v-card-text class="pa-4">
|
|
226
229
|
<v-row>
|
|
227
230
|
<v-col cols="12">
|
|
228
|
-
<InputLabel
|
|
229
|
-
title="Remarks (Optional)"
|
|
230
|
-
:required="false"
|
|
231
|
-
class="mb-2"
|
|
232
|
-
/>
|
|
231
|
+
<InputLabel title="Remarks" :required="false" class="mb-2" />
|
|
233
232
|
<v-textarea
|
|
234
233
|
v-model="modalData.remark"
|
|
235
234
|
placeholder="Enter your remarks here"
|
|
@@ -243,7 +242,7 @@
|
|
|
243
242
|
<v-col cols="12">
|
|
244
243
|
<v-divider class="mb-4" />
|
|
245
244
|
<PhotoUpload
|
|
246
|
-
title="Take/Upload
|
|
245
|
+
title="Take/Upload Photos"
|
|
247
246
|
:required="false"
|
|
248
247
|
v-model="modalData.photos"
|
|
249
248
|
v-model:photo-ids="modalData.photoIds"
|
|
@@ -305,31 +304,38 @@
|
|
|
305
304
|
|
|
306
305
|
<v-divider />
|
|
307
306
|
|
|
308
|
-
<v-
|
|
309
|
-
<v-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
class="
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
307
|
+
<v-toolbar class="pa-0" density="compact">
|
|
308
|
+
<v-row no-gutters>
|
|
309
|
+
<v-col cols="6" class="pa-0">
|
|
310
|
+
<v-btn
|
|
311
|
+
block
|
|
312
|
+
variant="text"
|
|
313
|
+
class="text-none"
|
|
314
|
+
size="large"
|
|
315
|
+
height="48"
|
|
316
|
+
:disabled="rejectModal.submitting"
|
|
317
|
+
@click="closeRejectDialog"
|
|
318
|
+
>
|
|
319
|
+
Cancel
|
|
320
|
+
</v-btn>
|
|
321
|
+
</v-col>
|
|
322
|
+
|
|
323
|
+
<v-col cols="6" class="pa-0">
|
|
324
|
+
<v-btn
|
|
325
|
+
block
|
|
326
|
+
variant="flat"
|
|
327
|
+
color="black"
|
|
328
|
+
class="text-none font-weight-bold rounded-0"
|
|
329
|
+
height="48"
|
|
330
|
+
:loading="rejectModal.submitting"
|
|
331
|
+
:disabled="!isRejectModalValid || rejectModal.submitting"
|
|
332
|
+
@click="submitRejectDialog"
|
|
333
|
+
>
|
|
334
|
+
Confirm
|
|
335
|
+
</v-btn>
|
|
336
|
+
</v-col>
|
|
337
|
+
</v-row>
|
|
338
|
+
</v-toolbar>
|
|
333
339
|
</v-card>
|
|
334
340
|
</v-dialog>
|
|
335
341
|
|
|
@@ -435,12 +441,12 @@ const { back } = useUtils();
|
|
|
435
441
|
const route = useRoute();
|
|
436
442
|
const scheduleTitle = computed(() => {
|
|
437
443
|
const path = route.path;
|
|
438
|
-
if (path.includes(
|
|
439
|
-
if (path.includes(
|
|
440
|
-
if (path.includes(
|
|
441
|
-
if (path.includes(
|
|
442
|
-
if (path.includes(
|
|
443
|
-
return
|
|
444
|
+
if (path.includes("cleaning-schedule")) return "Cleaning Checklist";
|
|
445
|
+
if (path.includes("technician-schedule")) return "Technician Checklist";
|
|
446
|
+
if (path.includes("landscape-schedule")) return "Landscape Checklist";
|
|
447
|
+
if (path.includes("pool-schedule")) return "Pool Checklist";
|
|
448
|
+
if (path.includes("pest-schedule")) return "Pest Checklist";
|
|
449
|
+
return "Cleaner Checklist";
|
|
444
450
|
});
|
|
445
451
|
|
|
446
452
|
const canAddRemarks = computed(() => props.canAddRemarks);
|