@7365admin1/layer-common 3.2.2-staging.125 → 3.2.2-staging.126
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/components/DashboardMain.vue +151 -283
- package/components/DashboardPanel.vue +84 -21
- package/package.json +1 -1
|
@@ -479,54 +479,34 @@
|
|
|
479
479
|
action-label="View All"
|
|
480
480
|
@action="goToDashboardRoute(primaryListConfig.route)"
|
|
481
481
|
>
|
|
482
|
-
<div v-if="taskScheduleItems.length" class="
|
|
483
|
-
<
|
|
482
|
+
<div v-if="taskScheduleItems.length" class="figma-list">
|
|
483
|
+
<div
|
|
484
484
|
v-for="item in taskScheduleItems"
|
|
485
485
|
:key="item.id"
|
|
486
|
-
|
|
487
|
-
class="dashboard-row-card pa-3"
|
|
486
|
+
class="figma-list-row figma-list-row--wide"
|
|
488
487
|
>
|
|
489
|
-
<div class="
|
|
490
|
-
<
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
>
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
{{ item.subtitle
|
|
498
|
-
}}<template v-if="item.subtitle && item.time">
|
|
499
|
-
• </template
|
|
500
|
-
>{{ item.time }}
|
|
501
|
-
</div>
|
|
502
|
-
</div>
|
|
503
|
-
<div
|
|
504
|
-
class="d-flex align-center ga-2 text-caption text-medium-emphasis"
|
|
505
|
-
>
|
|
506
|
-
<AvatarMain :name="item.person" :size="30" />
|
|
507
|
-
<span class="text-truncate" style="max-width: 100px">{{
|
|
508
|
-
item.person
|
|
509
|
-
}}</span>
|
|
510
|
-
</div>
|
|
511
|
-
<v-chip
|
|
512
|
-
size="small"
|
|
513
|
-
:color="getStatusTone(item.status)"
|
|
514
|
-
variant="tonal"
|
|
515
|
-
label
|
|
516
|
-
>
|
|
517
|
-
{{ item.status }}
|
|
518
|
-
</v-chip>
|
|
519
|
-
<v-btn
|
|
520
|
-
variant="outlined"
|
|
521
|
-
color="primary"
|
|
522
|
-
size="small"
|
|
523
|
-
class="text-none font-weight-bold"
|
|
524
|
-
@click="goToListItem(item, primaryListConfig.route)"
|
|
525
|
-
>
|
|
526
|
-
View
|
|
527
|
-
</v-btn>
|
|
488
|
+
<div class="figma-list-main">
|
|
489
|
+
<strong>{{ item.title }}</strong>
|
|
490
|
+
<p v-if="item.subtitle || item.time">
|
|
491
|
+
{{ item.subtitle
|
|
492
|
+
}}<template v-if="item.subtitle && item.time">
|
|
493
|
+
• </template
|
|
494
|
+
>{{ item.time }}
|
|
495
|
+
</p>
|
|
528
496
|
</div>
|
|
529
|
-
|
|
497
|
+
<div class="figma-list-person">
|
|
498
|
+
<AvatarMain :name="item.person" :size="30" />
|
|
499
|
+
<span>{{ item.person }}</span>
|
|
500
|
+
</div>
|
|
501
|
+
<StatusChip :status="item.status" pill />
|
|
502
|
+
<button
|
|
503
|
+
class="figma-row-action"
|
|
504
|
+
type="button"
|
|
505
|
+
@click="goToListItem(item, primaryListConfig.route)"
|
|
506
|
+
>
|
|
507
|
+
View
|
|
508
|
+
</button>
|
|
509
|
+
</div>
|
|
530
510
|
</div>
|
|
531
511
|
<DashboardEmptyState v-else />
|
|
532
512
|
</DashboardPanel>
|
|
@@ -543,35 +523,22 @@
|
|
|
543
523
|
action-label="View All"
|
|
544
524
|
@action="goToDashboardRoute('attendance')"
|
|
545
525
|
>
|
|
546
|
-
<div v-if="staffStatusItems.length" class="
|
|
547
|
-
<
|
|
526
|
+
<div v-if="staffStatusItems.length" class="figma-list">
|
|
527
|
+
<div
|
|
548
528
|
v-for="item in staffStatusItems"
|
|
549
529
|
:key="item.id"
|
|
550
|
-
|
|
551
|
-
class="dashboard-row-card pa-3"
|
|
530
|
+
class="figma-list-row"
|
|
552
531
|
>
|
|
553
|
-
<
|
|
554
|
-
|
|
555
|
-
<
|
|
556
|
-
|
|
557
|
-
class="text-body-2 font-weight-bold text-high-emphasis text-truncate"
|
|
558
|
-
>
|
|
559
|
-
{{ item.name }}
|
|
560
|
-
</div>
|
|
561
|
-
<div class="text-caption text-medium-emphasis mt-1 text-truncate">
|
|
562
|
-
{{ item.role }}
|
|
563
|
-
</div>
|
|
564
|
-
</div>
|
|
565
|
-
<v-chip
|
|
566
|
-
size="small"
|
|
567
|
-
variant="tonal"
|
|
568
|
-
label
|
|
569
|
-
class="ml-auto flex-shrink-0 font-weight-bold"
|
|
570
|
-
>
|
|
571
|
-
{{ item.totalHours || 0 }} hrs
|
|
572
|
-
</v-chip>
|
|
532
|
+
<AvatarMain :name="item.name" :size="32" />
|
|
533
|
+
<div class="figma-list-main">
|
|
534
|
+
<strong>{{ item.name }}</strong>
|
|
535
|
+
<p v-if="item.role">{{ item.role }}</p>
|
|
573
536
|
</div>
|
|
574
|
-
|
|
537
|
+
<!-- Hours are a FIGURE, not a status: no tone to read, so the
|
|
538
|
+
design's neutral pill rather than a StatusChip, which would
|
|
539
|
+
have coloured "8 hrs" as if it were a word it knows. -->
|
|
540
|
+
<span class="figma-row-figure">{{ item.totalHours || 0 }} hrs</span>
|
|
541
|
+
</div>
|
|
575
542
|
</div>
|
|
576
543
|
<DashboardEmptyState v-else />
|
|
577
544
|
</DashboardPanel>
|
|
@@ -583,76 +550,28 @@
|
|
|
583
550
|
action-label="View All"
|
|
584
551
|
@action="goToDashboardRoute('feedbacks')"
|
|
585
552
|
>
|
|
586
|
-
<div v-if="feedbackItems.length" class="figma-list
|
|
553
|
+
<div v-if="feedbackItems.length" class="figma-list">
|
|
587
554
|
<div
|
|
588
555
|
v-for="item in feedbackItems"
|
|
589
556
|
:key="item.id"
|
|
590
|
-
class="
|
|
591
|
-
style="
|
|
592
|
-
padding: 16px 20px;
|
|
593
|
-
border: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
|
|
594
|
-
border-radius: 12px;
|
|
595
|
-
margin-bottom: 12px;
|
|
596
|
-
background-color: rgb(var(--v-theme-surface-bright));
|
|
597
|
-
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.02);
|
|
598
|
-
"
|
|
557
|
+
class="figma-list-row figma-list-row--wide"
|
|
599
558
|
>
|
|
600
|
-
<div
|
|
601
|
-
<strong
|
|
602
|
-
|
|
603
|
-
display: block;
|
|
604
|
-
font-size: 15px;
|
|
605
|
-
font-weight: 700;
|
|
606
|
-
color: rgb(var(--v-theme-on-surface));
|
|
607
|
-
margin-bottom: 4px;
|
|
608
|
-
"
|
|
609
|
-
>{{ item.title }}</strong
|
|
610
|
-
>
|
|
611
|
-
<span style="font-size: 13px; color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity))">{{
|
|
612
|
-
item.subtitle
|
|
613
|
-
}}</span>
|
|
614
|
-
</div>
|
|
615
|
-
|
|
616
|
-
<div
|
|
617
|
-
style="flex: 1; display: flex; align-items: center; gap: 12px"
|
|
618
|
-
>
|
|
619
|
-
<AvatarMain :name="item.person" :size="36" />
|
|
620
|
-
<span style="font-size: 14px; color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity))">{{
|
|
621
|
-
item.person
|
|
622
|
-
}}</span>
|
|
623
|
-
</div>
|
|
624
|
-
|
|
625
|
-
<div style="flex: 1; display: flex; justify-content: center">
|
|
626
|
-
<div
|
|
627
|
-
:style="getStatusPillStyle(item.status)"
|
|
628
|
-
style="
|
|
629
|
-
padding: 6px 16px;
|
|
630
|
-
border-radius: 20px;
|
|
631
|
-
font-size: 13px;
|
|
632
|
-
font-weight: 500;
|
|
633
|
-
text-transform: capitalize;
|
|
634
|
-
"
|
|
635
|
-
>
|
|
636
|
-
{{ item.status || "To-Do" }}
|
|
637
|
-
</div>
|
|
559
|
+
<div class="figma-list-main">
|
|
560
|
+
<strong>{{ item.title }}</strong>
|
|
561
|
+
<p v-if="item.subtitle">{{ item.subtitle }}</p>
|
|
638
562
|
</div>
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
<
|
|
642
|
-
variant="outlined"
|
|
643
|
-
class="text-none font-weight-medium"
|
|
644
|
-
size="small"
|
|
645
|
-
color="primary"
|
|
646
|
-
style="
|
|
647
|
-
border-color: rgba(var(--v-border-color), var(--v-border-opacity));
|
|
648
|
-
border-radius: 8px;
|
|
649
|
-
padding: 0 16px;
|
|
650
|
-
height: 32px;
|
|
651
|
-
"
|
|
652
|
-
@click="goToListItem(item, 'feedbacks')"
|
|
653
|
-
>View</v-btn
|
|
654
|
-
>
|
|
563
|
+
<div class="figma-list-person">
|
|
564
|
+
<AvatarMain :name="item.person" :size="30" />
|
|
565
|
+
<span>{{ item.person }}</span>
|
|
655
566
|
</div>
|
|
567
|
+
<StatusChip :status="item.status || 'To-Do'" pill />
|
|
568
|
+
<button
|
|
569
|
+
class="figma-row-action"
|
|
570
|
+
type="button"
|
|
571
|
+
@click="goToListItem(item, 'feedbacks')"
|
|
572
|
+
>
|
|
573
|
+
View
|
|
574
|
+
</button>
|
|
656
575
|
</div>
|
|
657
576
|
</div>
|
|
658
577
|
<DashboardEmptyState v-else />
|
|
@@ -943,20 +862,15 @@
|
|
|
943
862
|
</div>
|
|
944
863
|
|
|
945
864
|
<div class="active-patrol-action">
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
style="
|
|
952
|
-
border-color: rgba(var(--v-border-color), var(--v-border-opacity));
|
|
953
|
-
border-radius: 8px;
|
|
954
|
-
padding: 0 16px;
|
|
955
|
-
height: 32px;
|
|
956
|
-
"
|
|
865
|
+
<!-- Chrome only: the route and the Virtual Patrol flow
|
|
866
|
+
behind it are unchanged. -->
|
|
867
|
+
<button
|
|
868
|
+
class="figma-row-action"
|
|
869
|
+
type="button"
|
|
957
870
|
@click="goToDashboardRoute('virtual-patrol')"
|
|
958
|
-
>View</v-btn
|
|
959
871
|
>
|
|
872
|
+
View
|
|
873
|
+
</button>
|
|
960
874
|
</div>
|
|
961
875
|
</div>
|
|
962
876
|
</div>
|
|
@@ -978,62 +892,28 @@
|
|
|
978
892
|
</button>
|
|
979
893
|
</div>
|
|
980
894
|
<div class="figma-panel-body">
|
|
981
|
-
<div v-if="securityStaffItems.length" class="figma-list
|
|
895
|
+
<div v-if="securityStaffItems.length" class="figma-list">
|
|
982
896
|
<div
|
|
983
897
|
v-for="item in securityStaffItems"
|
|
984
898
|
:key="item._id || item.id"
|
|
985
|
-
class="
|
|
986
|
-
style="
|
|
987
|
-
padding: 16px 20px;
|
|
988
|
-
border: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
|
|
989
|
-
border-radius: 12px;
|
|
990
|
-
margin-bottom: 12px;
|
|
991
|
-
background-color: rgb(var(--v-theme-surface-bright));
|
|
992
|
-
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.02);
|
|
993
|
-
"
|
|
899
|
+
class="figma-list-row"
|
|
994
900
|
>
|
|
995
|
-
<
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
<
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
font-size: 15px;
|
|
1010
|
-
font-weight: 700;
|
|
1011
|
-
color: rgb(var(--v-theme-on-surface));
|
|
1012
|
-
margin-bottom: 4px;
|
|
1013
|
-
"
|
|
1014
|
-
>{{
|
|
1015
|
-
item.userName || item.personName || "Unassigned"
|
|
1016
|
-
}}</strong
|
|
1017
|
-
>
|
|
1018
|
-
<span style="font-size: 13px; color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity))">{{
|
|
1019
|
-
item.role || item.designation || "Officer"
|
|
1020
|
-
}}</span>
|
|
1021
|
-
</div>
|
|
1022
|
-
</div>
|
|
1023
|
-
|
|
1024
|
-
<div style="flex: 0 0 auto">
|
|
1025
|
-
<div
|
|
1026
|
-
:style="getStaffStatusPillStyle(item.status)"
|
|
1027
|
-
style="
|
|
1028
|
-
padding: 6px 16px;
|
|
1029
|
-
border-radius: 20px;
|
|
1030
|
-
font-size: 13px;
|
|
1031
|
-
font-weight: 500;
|
|
1032
|
-
"
|
|
1033
|
-
>
|
|
1034
|
-
{{ item.status || "On duty" }}
|
|
1035
|
-
</div>
|
|
901
|
+
<AvatarMain
|
|
902
|
+
:name="
|
|
903
|
+
item.personName ||
|
|
904
|
+
item.employeeName ||
|
|
905
|
+
item.userName ||
|
|
906
|
+
'Unassigned'
|
|
907
|
+
"
|
|
908
|
+
:size="32"
|
|
909
|
+
/>
|
|
910
|
+
<div class="figma-list-main">
|
|
911
|
+
<strong>{{
|
|
912
|
+
item.userName || item.personName || "Unassigned"
|
|
913
|
+
}}</strong>
|
|
914
|
+
<p>{{ item.role || item.designation || "Officer" }}</p>
|
|
1036
915
|
</div>
|
|
916
|
+
<StatusChip :status="item.status || 'On duty'" pill />
|
|
1037
917
|
</div>
|
|
1038
918
|
</div>
|
|
1039
919
|
<DashboardEmptyState v-else />
|
|
@@ -1048,76 +928,28 @@
|
|
|
1048
928
|
action-label="View All"
|
|
1049
929
|
@action="goToDashboardRoute('feedbacks')"
|
|
1050
930
|
>
|
|
1051
|
-
<div v-if="feedbackItems.length" class="figma-list
|
|
931
|
+
<div v-if="feedbackItems.length" class="figma-list">
|
|
1052
932
|
<div
|
|
1053
933
|
v-for="item in feedbackItems"
|
|
1054
934
|
:key="item.id"
|
|
1055
|
-
class="
|
|
1056
|
-
style="
|
|
1057
|
-
padding: 16px 20px;
|
|
1058
|
-
border: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
|
|
1059
|
-
border-radius: 12px;
|
|
1060
|
-
margin-bottom: 12px;
|
|
1061
|
-
background-color: rgb(var(--v-theme-surface-bright));
|
|
1062
|
-
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.02);
|
|
1063
|
-
"
|
|
935
|
+
class="figma-list-row figma-list-row--wide"
|
|
1064
936
|
>
|
|
1065
|
-
<div
|
|
1066
|
-
<strong
|
|
1067
|
-
|
|
1068
|
-
display: block;
|
|
1069
|
-
font-size: 15px;
|
|
1070
|
-
font-weight: 700;
|
|
1071
|
-
color: rgb(var(--v-theme-on-surface));
|
|
1072
|
-
margin-bottom: 4px;
|
|
1073
|
-
"
|
|
1074
|
-
>{{ item.title }}</strong
|
|
1075
|
-
>
|
|
1076
|
-
<span style="font-size: 13px; color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity))">{{
|
|
1077
|
-
item.subtitle
|
|
1078
|
-
}}</span>
|
|
1079
|
-
</div>
|
|
1080
|
-
|
|
1081
|
-
<div
|
|
1082
|
-
style="flex: 1; display: flex; align-items: center; gap: 12px"
|
|
1083
|
-
>
|
|
1084
|
-
<AvatarMain :name="item.person" :size="36" />
|
|
1085
|
-
<span style="font-size: 14px; color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity))">{{
|
|
1086
|
-
item.person
|
|
1087
|
-
}}</span>
|
|
1088
|
-
</div>
|
|
1089
|
-
|
|
1090
|
-
<div style="flex: 1; display: flex; justify-content: center">
|
|
1091
|
-
<div
|
|
1092
|
-
:style="getStatusPillStyle(item.status)"
|
|
1093
|
-
style="
|
|
1094
|
-
padding: 6px 16px;
|
|
1095
|
-
border-radius: 20px;
|
|
1096
|
-
font-size: 13px;
|
|
1097
|
-
font-weight: 500;
|
|
1098
|
-
text-transform: capitalize;
|
|
1099
|
-
"
|
|
1100
|
-
>
|
|
1101
|
-
{{ item.status || "To-Do" }}
|
|
1102
|
-
</div>
|
|
937
|
+
<div class="figma-list-main">
|
|
938
|
+
<strong>{{ item.title }}</strong>
|
|
939
|
+
<p v-if="item.subtitle">{{ item.subtitle }}</p>
|
|
1103
940
|
</div>
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
<
|
|
1107
|
-
variant="outlined"
|
|
1108
|
-
class="text-none font-weight-medium"
|
|
1109
|
-
size="small"
|
|
1110
|
-
color="primary"
|
|
1111
|
-
style="
|
|
1112
|
-
border-color: rgba(var(--v-border-color), var(--v-border-opacity));
|
|
1113
|
-
border-radius: 8px;
|
|
1114
|
-
padding: 0 16px;
|
|
1115
|
-
height: 32px;
|
|
1116
|
-
"
|
|
1117
|
-
@click="goToListItem(item, 'feedbacks')"
|
|
1118
|
-
>View</v-btn
|
|
1119
|
-
>
|
|
941
|
+
<div class="figma-list-person">
|
|
942
|
+
<AvatarMain :name="item.person" :size="30" />
|
|
943
|
+
<span>{{ item.person }}</span>
|
|
1120
944
|
</div>
|
|
945
|
+
<StatusChip :status="item.status || 'To-Do'" pill />
|
|
946
|
+
<button
|
|
947
|
+
class="figma-row-action"
|
|
948
|
+
type="button"
|
|
949
|
+
@click="goToListItem(item, 'feedbacks')"
|
|
950
|
+
>
|
|
951
|
+
View
|
|
952
|
+
</button>
|
|
1121
953
|
</div>
|
|
1122
954
|
</div>
|
|
1123
955
|
<DashboardEmptyState v-else />
|
|
@@ -3182,17 +3014,6 @@ function getInitials(name?: string) {
|
|
|
3182
3014
|
|
|
3183
3015
|
// ─── Status Style Helpers ────────────────────────────────────────────────────
|
|
3184
3016
|
|
|
3185
|
-
function getStatusPillStyle(status: any) {
|
|
3186
|
-
const tone = getStatusTone(status);
|
|
3187
|
-
const map: Record<string, { backgroundColor: string; color: string }> = {
|
|
3188
|
-
success: { backgroundColor: "var(--ok-bg)", color: "var(--ok)" },
|
|
3189
|
-
warning: { backgroundColor: "var(--warn-bg)", color: "var(--warn)" },
|
|
3190
|
-
error: { backgroundColor: "var(--err-bg)", color: "var(--err)" },
|
|
3191
|
-
neutral: { backgroundColor: "var(--hover)", color: "var(--text2)" },
|
|
3192
|
-
};
|
|
3193
|
-
return map[tone] || map.neutral;
|
|
3194
|
-
}
|
|
3195
|
-
|
|
3196
3017
|
/**
|
|
3197
3018
|
* The pills are drawn by inline style, so the literal colours lived here rather
|
|
3198
3019
|
* than in the stylesheet - which is why they survived the dark-mode repair and
|
|
@@ -3207,17 +3028,6 @@ function getPatrolStatusStyle(status: any) {
|
|
|
3207
3028
|
return { backgroundColor: "var(--hover)", color: "var(--text2)" };
|
|
3208
3029
|
}
|
|
3209
3030
|
|
|
3210
|
-
function getStaffStatusPillStyle(status: any) {
|
|
3211
|
-
const s = String(status || "").toLowerCase();
|
|
3212
|
-
if (s === "on duty" || s === "on-duty")
|
|
3213
|
-
return { backgroundColor: "var(--ok-bg)", color: "var(--ok)" };
|
|
3214
|
-
if (s === "on break" || s === "on-break")
|
|
3215
|
-
return { backgroundColor: "var(--warn-bg)", color: "var(--warn)" };
|
|
3216
|
-
if (s === "absent")
|
|
3217
|
-
return { backgroundColor: "var(--err-bg)", color: "var(--err)" };
|
|
3218
|
-
return { backgroundColor: "var(--hover)", color: "var(--text2)" };
|
|
3219
|
-
}
|
|
3220
|
-
|
|
3221
3031
|
function getStatusProgressStyle(item: { percent: number; color: string }) {
|
|
3222
3032
|
const percent = Math.min(100, Math.max(0, Number(item.percent) || 0));
|
|
3223
3033
|
return { backgroundColor: item.color, width: `${percent}%` };
|
|
@@ -4367,6 +4177,61 @@ function formatDashboardTime(value?: string) {
|
|
|
4367
4177
|
justify-self: end;
|
|
4368
4178
|
}
|
|
4369
4179
|
|
|
4180
|
+
/* The service-vertical and security rows carry two more cells than the
|
|
4181
|
+
property rows do - who it is assigned to, and the status. Same row, four
|
|
4182
|
+
columns instead of three; there is no second row style. */
|
|
4183
|
+
.figma-list-row--wide {
|
|
4184
|
+
grid-template-columns:
|
|
4185
|
+
minmax(0, 1fr) minmax(0, auto) auto minmax(38px, auto);
|
|
4186
|
+
}
|
|
4187
|
+
|
|
4188
|
+
.figma-list-person {
|
|
4189
|
+
align-items: center;
|
|
4190
|
+
color: var(--muted);
|
|
4191
|
+
display: flex;
|
|
4192
|
+
font-family: var(--font-sans);
|
|
4193
|
+
font-size: 11px;
|
|
4194
|
+
font-weight: 700;
|
|
4195
|
+
gap: 8px;
|
|
4196
|
+
min-width: 0;
|
|
4197
|
+
}
|
|
4198
|
+
|
|
4199
|
+
.figma-list-person span {
|
|
4200
|
+
overflow: hidden;
|
|
4201
|
+
text-overflow: ellipsis;
|
|
4202
|
+
white-space: nowrap;
|
|
4203
|
+
}
|
|
4204
|
+
|
|
4205
|
+
/* A figure, not a status - the neutral pill, so a number is never coloured as
|
|
4206
|
+
if it were a word `utils/status.ts` recognised. */
|
|
4207
|
+
/* The same pill StatusChip draws for `tone-neutral` - `--hover` on `--text2`,
|
|
4208
|
+
3px/10px, `--r-pill` - reproduced rather than reused because StatusChip's
|
|
4209
|
+
rules are scoped to its own file. */
|
|
4210
|
+
.figma-row-figure {
|
|
4211
|
+
background: var(--hover);
|
|
4212
|
+
border-radius: var(--r-pill);
|
|
4213
|
+
color: var(--text2);
|
|
4214
|
+
font-family: var(--font-sans);
|
|
4215
|
+
font-size: var(--fs-chip);
|
|
4216
|
+
font-weight: var(--fw-chip);
|
|
4217
|
+
justify-self: end;
|
|
4218
|
+
line-height: 1.4;
|
|
4219
|
+
padding: 3px 10px;
|
|
4220
|
+
white-space: nowrap;
|
|
4221
|
+
}
|
|
4222
|
+
|
|
4223
|
+
/* Below the design's tablet break the four columns will not hold a readable
|
|
4224
|
+
title, so the row stacks - the same thing the property rows do. */
|
|
4225
|
+
@media (max-width: 700px) {
|
|
4226
|
+
.figma-list-row--wide {
|
|
4227
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
4228
|
+
}
|
|
4229
|
+
|
|
4230
|
+
.figma-list-row--wide .figma-list-main {
|
|
4231
|
+
grid-column: 1 / -1;
|
|
4232
|
+
}
|
|
4233
|
+
}
|
|
4234
|
+
|
|
4370
4235
|
.figma-event-dot {
|
|
4371
4236
|
align-self: center;
|
|
4372
4237
|
border-radius: 50%;
|
|
@@ -4447,7 +4312,10 @@ function formatDashboardTime(value?: string) {
|
|
|
4447
4312
|
border: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
|
|
4448
4313
|
border-radius: 999px;
|
|
4449
4314
|
display: inline-flex;
|
|
4450
|
-
|
|
4315
|
+
/* `1 1 auto` let the chip GROW to fill the column, so one assignee drew as a
|
|
4316
|
+
full-width bordered box that reads as an empty text input. It is a chip -
|
|
4317
|
+
it shrinks, it does not grow. */
|
|
4318
|
+
flex: 0 1 auto;
|
|
4451
4319
|
gap: 6px;
|
|
4452
4320
|
max-width: 100%;
|
|
4453
4321
|
min-width: 0;
|
|
@@ -1,31 +1,37 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
THE DASHBOARD PANEL.
|
|
3
|
+
|
|
4
|
+
The `isPropertyMode` branch of DashboardMain already draws its panels the
|
|
5
|
+
design's way, inline: a `.dashboard-card` surface carrying `.figma-panel`
|
|
6
|
+
padding, a header whose `h2` is the card title and whose action is a bare
|
|
7
|
+
text affordance, then the body. This component is what the OTHER two
|
|
8
|
+
branches use, and it was still a `v-card` with Vuetify typography - which is
|
|
9
|
+
why the same dashboard looked new for property-management and old for the
|
|
10
|
+
five service verticals.
|
|
11
|
+
|
|
12
|
+
So it now draws that same construction, with the property branch's literal
|
|
13
|
+
values, on `AppCard`. Copied here rather than reached for across components:
|
|
14
|
+
the `.figma-*` rules are global to DashboardMain, and depending on a
|
|
15
|
+
sibling's stylesheet is how a panel silently loses its padding later.
|
|
16
|
+
-->
|
|
1
17
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class="d-flex flex-column w-100"
|
|
7
|
-
style="min-height: 200px"
|
|
8
|
-
>
|
|
9
|
-
<div class="d-flex align-center justify-space-between pa-5 pb-3">
|
|
10
|
-
<h2 class="text-body-1 font-weight-black text-high-emphasis mb-0">
|
|
11
|
-
{{ title }}
|
|
12
|
-
</h2>
|
|
13
|
-
<v-btn
|
|
18
|
+
<AppCard class="dashboard-panel">
|
|
19
|
+
<div class="dashboard-panel__header">
|
|
20
|
+
<h2>{{ title }}</h2>
|
|
21
|
+
<button
|
|
14
22
|
v-if="actionLabel"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
size="small"
|
|
18
|
-
class="text-none font-weight-bold"
|
|
23
|
+
class="dashboard-panel__action"
|
|
24
|
+
type="button"
|
|
19
25
|
@click="$emit('action')"
|
|
20
26
|
>
|
|
21
27
|
{{ actionLabel }}
|
|
22
|
-
</
|
|
28
|
+
</button>
|
|
23
29
|
</div>
|
|
24
30
|
|
|
25
|
-
<div class="
|
|
31
|
+
<div class="dashboard-panel__body">
|
|
26
32
|
<slot />
|
|
27
33
|
</div>
|
|
28
|
-
</
|
|
34
|
+
</AppCard>
|
|
29
35
|
</template>
|
|
30
36
|
|
|
31
37
|
<script setup lang="ts">
|
|
@@ -36,9 +42,66 @@ defineProps({
|
|
|
36
42
|
},
|
|
37
43
|
actionLabel: {
|
|
38
44
|
type: String,
|
|
39
|
-
default:
|
|
45
|
+
default: "",
|
|
40
46
|
},
|
|
41
47
|
});
|
|
42
48
|
|
|
43
|
-
defineEmits([
|
|
49
|
+
defineEmits(["action"]);
|
|
44
50
|
</script>
|
|
51
|
+
|
|
52
|
+
<style scoped>
|
|
53
|
+
/* `.dashboard-card` + `.dashboard-panel` + `.figma-panel`, resolved: the
|
|
54
|
+
figma layer wins the shadow and the padding, so the panel is a flat 14px
|
|
55
|
+
card at 26px/28px/24px and 276px tall. */
|
|
56
|
+
.dashboard-panel {
|
|
57
|
+
box-shadow: none;
|
|
58
|
+
display: flex;
|
|
59
|
+
flex-direction: column;
|
|
60
|
+
font-family: var(--font-sans);
|
|
61
|
+
height: 100%;
|
|
62
|
+
min-height: 276px;
|
|
63
|
+
padding: 26px 28px 24px;
|
|
64
|
+
width: 100%;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.dashboard-panel__header {
|
|
68
|
+
align-items: center;
|
|
69
|
+
display: flex;
|
|
70
|
+
gap: 16px;
|
|
71
|
+
justify-content: space-between;
|
|
72
|
+
min-height: 18px;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* The panel heading is the design's card title: 15.5px/800, sentence case. */
|
|
76
|
+
.dashboard-panel__header h2 {
|
|
77
|
+
color: var(--text);
|
|
78
|
+
font-family: var(--font-sans);
|
|
79
|
+
font-size: var(--fs-card-title);
|
|
80
|
+
font-weight: var(--fw-card-title);
|
|
81
|
+
letter-spacing: 0;
|
|
82
|
+
line-height: 1.2;
|
|
83
|
+
margin: 0;
|
|
84
|
+
text-transform: none;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/* Not an AppButton: the design's panel action is a text affordance, 12px/800
|
|
88
|
+
with no box - the same one the property branch already ships. */
|
|
89
|
+
.dashboard-panel__action {
|
|
90
|
+
appearance: none;
|
|
91
|
+
background: transparent;
|
|
92
|
+
border: 0;
|
|
93
|
+
color: rgb(var(--v-theme-primary));
|
|
94
|
+
cursor: pointer;
|
|
95
|
+
font-size: 12px;
|
|
96
|
+
font-weight: 800;
|
|
97
|
+
line-height: 1;
|
|
98
|
+
padding: 0;
|
|
99
|
+
white-space: nowrap;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.dashboard-panel__body {
|
|
103
|
+
flex: 1;
|
|
104
|
+
margin-top: 20px;
|
|
105
|
+
min-width: 0;
|
|
106
|
+
}
|
|
107
|
+
</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.126",
|
|
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.",
|