@7365admin1/layer-common 4.118.0 → 4.118.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @iservice365/layer-common
2
2
 
3
+ ## 4.118.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 83b3d6d: Incident Report PDF: the header now carries the report status (new optional
8
+ `status` prop on `IncidentInformationDownload`), cells use one consistent 1px
9
+ border with no half-row page splits, and the dates print as DD/MM/YYYY in
10
+ Singapore time. They printed as MM/DD/YYYY, and from a UTC server an 8 Oct date
11
+ showed as 07/10. No field removed; NRIC masking unchanged.
12
+
3
13
  ## 4.118.0
4
14
 
5
15
  ### Minor Changes
@@ -3123,11 +3133,11 @@ Monthly report: a month that had patrols opens the list of that month's patrol r
3123
3133
  `utils/console-tier.ts` + `composables/useConsoleTier.ts` mirror the server's
3124
3134
  own rule from two endpoints the console already calls, unprojected:
3125
3135
 
3126
- GET /api/members/user/:user/app/admin the Seven365 staff membership
3127
- GET /api/roles/id/:role that membership's role document
3136
+ GET /api/members/user/:user/app/admin the Seven365 staff membership
3137
+ GET /api/roles/id/:role that membership's role document
3128
3138
 
3129
- owner = member.type === "admin" && role.type === "admin" && role.default === true
3130
- staff = member.type === "admin" && role.type === "admin"
3139
+ owner = member.type === "admin" && role.type === "admin" && role.default === true
3140
+ staff = member.type === "admin" && role.type === "admin"
3131
3141
 
3132
3142
  `role.default` is the marker because it is the only property of a platform
3133
3143
  staff role no API caller can set - `role.controller.ts` validates create and
@@ -1,42 +1,40 @@
1
1
  <template>
2
- <v-row no-gutters class="px-5 pt-4">
3
- <!-- Site Information -->
4
- <p
5
- class="text-uppercase text-center w-100 text-h6 bg-error text-on-error"
6
- style="padding: 10px"
7
- >
8
- Incident Report
9
- </p>
10
- <v-row no-gutters class="mt-5 border pb-5">
11
- <p
12
- class="w-100 text-h6 pa-2 text-center bg-warning text-on-warning"
13
- >
2
+ <div class="ir-doc px-5 pt-4">
3
+ <!-- Report header: title with the status inside it, so the two never float apart. -->
4
+ <div class="ir-title bg-error text-on-error">
5
+ <p class="text-uppercase text-h6 ma-0">Incident Report</p>
6
+ <p v-if="status" class="ir-status ma-0 mt-2" :class="`ir-status--${statusKey}`">
7
+ Status: {{ String(status).toUpperCase() }}
8
+ </p>
9
+ </div>
10
+ <v-row no-gutters class="ir-box mt-5">
11
+ <p class="ir-section w-100 text-h6 pa-2 text-center bg-warning text-on-warning">
14
12
  Incident Information
15
13
  </p>
16
14
 
17
- <v-col cols="6" class="pa-3 border-b border-e">
15
+ <v-col cols="6" class="pa-3 ir-cell ir-e">
18
16
  <p class="font-weight-bold">Site</p>
19
17
  <p>{{ siteName || "-" }}</p>
20
18
  </v-col>
21
- <v-col cols="6" class="pa-3 border-b">
19
+ <v-col cols="6" class="pa-3 ir-cell">
22
20
  <p class="font-weight-bold">Reference</p>
23
21
  <p>{{ incidentInformation?.siteInfo?.irNumber || "-" }}</p>
24
22
  </v-col>
25
23
 
26
- <v-col cols="6" class="pa-3 border-b border-e">
24
+ <v-col cols="6" class="pa-3 ir-cell ir-e">
27
25
  <p class="font-weight-bold">Place of Incident</p>
28
26
  <p>
29
27
  {{ incidentInformation?.placeOfIncident?.incidentLocation || "-" }}
30
28
  </p>
31
29
  </v-col>
32
- <v-col cols="6" class="pa-3 border-b">
30
+ <v-col cols="6" class="pa-3 ir-cell">
33
31
  <p class="font-weight-bold">Type of Incident</p>
34
32
  <p>
35
33
  {{ incidentInformation?.incidentTypeAndTime?.typeOfIncident || "-" }}
36
34
  </p>
37
35
  </v-col>
38
36
 
39
- <v-col cols="6" class="pa-3 border-b border-e">
37
+ <v-col cols="6" class="pa-3 ir-cell ir-e">
40
38
  <p class="font-weight-bold">Date of Incident</p>
41
39
  <p>
42
40
  {{
@@ -46,55 +44,58 @@
46
44
  }}
47
45
  </p>
48
46
  </v-col>
49
- <v-col cols="6" class="pa-3 border-b">
47
+ <v-col cols="6" class="pa-3 ir-cell">
50
48
  <p class="font-weight-bold">Incident Start Time</p>
51
49
  <p>
52
50
  {{ incidentInformation?.incidentTypeAndTime?.incidentStart || "-" }}
53
51
  </p>
54
52
  </v-col>
55
53
 
56
- <v-col cols="6" class="pa-3 border-b border-e">
54
+ <v-col cols="6" class="pa-3 ir-cell ir-e">
57
55
  <p class="font-weight-bold">Time of Response (From 1st Contact)</p>
58
56
  <p>
59
57
  {{ incidentInformation?.incidentTypeAndTime?.timeOfResponse || "-" }}
60
58
  </p>
61
59
  </v-col>
62
- <v-col cols="6" class="pa-3 border-b">
60
+ <v-col cols="6" class="pa-3 ir-cell">
63
61
  <p class="font-weight-bold">Incident End Time</p>
64
62
  <p>
65
63
  {{ incidentInformation?.incidentTypeAndTime?.incidentEnd || "-" }}
66
64
  </p>
67
65
  </v-col>
68
66
 
69
- <v-col cols="6" class="pa-3 border-b border-e">
67
+ <v-col cols="6" class="pa-3 ir-cell ir-e">
70
68
  <p class="font-weight-bold">Date of Report Submission</p>
71
- {{
72
- toLocalDate(incidentInformation?.submissionForm?.dateOfReport) || "NA"
73
- }}
69
+ <p>
70
+ {{
71
+ toLocalDate(incidentInformation?.submissionForm?.dateOfReport) ||
72
+ "NA"
73
+ }}
74
+ </p>
74
75
  </v-col>
75
- <v-col cols="6" class="pa-3 border-b">
76
+ <v-col cols="6" class="pa-3 ir-cell">
76
77
  <p class="font-weight-bold">Time of Report Submission</p>
77
78
  <p>{{ incidentInformation?.submissionForm?.time || "-" }}</p>
78
79
  </v-col>
79
80
 
80
- <v-col cols="6" class="pa-3 border-b border-e">
81
+ <v-col cols="6" class="pa-3 ir-cell ir-e">
81
82
  <p class="font-weight-bold">Report Submitted By</p>
82
83
  <p>{{ incidentInformation?.siteInfo?.submittedBy || "-" }}</p>
83
84
  </v-col>
84
- <v-col cols="6" class="pa-3 border-b">
85
+ <v-col cols="6" class="pa-3 ir-cell">
85
86
  <p class="font-weight-bold">Designation</p>
86
87
  <p>{{ incidentInformation?.siteInfo?.designation || "-" }}</p>
87
88
  </v-col>
88
89
 
89
- <v-col cols="4" class="pa-3 border-b border-e">
90
+ <v-col cols="4" class="pa-3 ir-cell ir-e">
90
91
  <p class="font-weight-bold">Name of Informant/Complainant</p>
91
92
  <p>{{ incidentInformation?.complaintInfo?.complainant || "-" }}</p>
92
93
  </v-col>
93
- <v-col cols="4" class="pa-3 border-b border-e">
94
+ <v-col cols="4" class="pa-3 ir-cell ir-e">
94
95
  <p class="font-weight-bold">Contact No.</p>
95
96
  <p>{{ incidentInformation?.complaintInfo?.contact || "-" }}</p>
96
97
  </v-col>
97
- <v-col cols="4" class="pa-3 border-b">
98
+ <v-col cols="4" class="pa-3 ir-cell">
98
99
  <p class="font-weight-bold">NRIC/WP No.</p>
99
100
  <p>
100
101
  {{
@@ -105,17 +106,17 @@
105
106
  </p>
106
107
  </v-col>
107
108
 
108
- <v-col cols="4" class="pa-3 border-b border-e">
109
+ <v-col cols="4" class="pa-3 ir-cell ir-e">
109
110
  <p class="font-weight-bold">
110
111
  Name of Recipient of Complaint (1st Contact)
111
112
  </p>
112
113
  <p>{{ incidentInformation?.recipientOfComplaint?.recipient || "-" }}</p>
113
114
  </v-col>
114
- <v-col cols="4" class="pa-3 border-b border-e">
115
+ <v-col cols="4" class="pa-3 ir-cell ir-e">
115
116
  <p class="font-weight-bold">Contact No.</p>
116
117
  <p>{{ incidentInformation?.recipientOfComplaint?.contact || "-" }}</p>
117
118
  </v-col>
118
- <v-col cols="4" class="pa-3 border-b">
119
+ <v-col cols="4" class="pa-3 ir-cell">
119
120
  <p class="font-weight-bold">NRIC/WP No.</p>
120
121
  <p>
121
122
  {{
@@ -126,7 +127,7 @@
126
127
  </p>
127
128
  </v-col>
128
129
 
129
- <v-col cols="12" class="pa-3 border-b border-e">
130
+ <v-col cols="12" class="pa-3 ir-cell">
130
131
  <p class="font-weight-bold">Complaint Received through</p>
131
132
  <p
132
133
  v-if="
@@ -142,7 +143,7 @@
142
143
  }}
143
144
  </p>
144
145
  </v-col>
145
- <v-col cols="12" class="pa-3">
146
+ <v-col cols="12" class="pa-3 ir-cell ir-last">
146
147
  <p class="font-weight-bold">Brief Description</p>
147
148
  <p>
148
149
  {{
@@ -151,7 +152,7 @@
151
152
  </p>
152
153
  </v-col>
153
154
  </v-row>
154
- </v-row>
155
+ </div>
155
156
  </template>
156
157
 
157
158
  <script lang="ts" setup>
@@ -162,8 +163,15 @@ const props = defineProps({
162
163
  type: Object as PropType<Record<string, any> | null>,
163
164
  required: true,
164
165
  },
166
+ // Optional report status (pending/approved/rejected), printed inside the header.
167
+ status: {
168
+ type: String,
169
+ default: "",
170
+ },
165
171
  });
166
172
 
173
+ const statusKey = computed(() => String(props.status || "").toLowerCase());
174
+
167
175
  // utilities
168
176
  const { getSiteById } = useSiteSettings();
169
177
  const route = useRoute();
@@ -204,11 +212,16 @@ watch(
204
212
  { immediate: true }
205
213
  );
206
214
 
215
+ // DD/MM/YYYY in Singapore time. The PDF is rendered on a server whose clock is
216
+ // UTC, so without the zone an 8 Oct (SGT) date prints as 07/10.
207
217
  function toLocalDate(utcString: string) {
208
- return new Date(utcString).toLocaleString("en-US", {
218
+ const d = new Date(utcString);
219
+ if (!utcString || isNaN(d.getTime())) return "";
220
+ return d.toLocaleDateString("en-GB", {
209
221
  year: "numeric",
210
222
  month: "2-digit",
211
223
  day: "2-digit",
224
+ timeZone: "Asia/Singapore",
212
225
  });
213
226
  }
214
227
 
@@ -218,3 +231,48 @@ const maskNRIC = (value: any) => {
218
231
  return value.replace(/.(?=.{3})/g, "*");
219
232
  };
220
233
  </script>
234
+
235
+ <style scoped>
236
+ /* One consistent 1px grey rule for every cell edge; rows never split across pages. */
237
+ .ir-title {
238
+ text-align: center;
239
+ padding: 10px;
240
+ }
241
+ .ir-status {
242
+ display: inline-block;
243
+ background: #fff;
244
+ color: #b26a00;
245
+ border: 1px solid currentColor;
246
+ border-radius: 4px;
247
+ padding: 2px 14px;
248
+ font-size: 0.95rem;
249
+ font-weight: 700;
250
+ letter-spacing: 0.03em;
251
+ }
252
+ .ir-status--approved { color: #2e7d32; }
253
+ .ir-status--rejected { color: #c62828; }
254
+ .ir-box {
255
+ border: 1px solid #8a8a8a;
256
+ }
257
+ .ir-cell {
258
+ border-bottom: 1px solid #8a8a8a;
259
+ break-inside: avoid;
260
+ page-break-inside: avoid;
261
+ }
262
+ .ir-e {
263
+ border-right: 1px solid #8a8a8a;
264
+ }
265
+ .ir-last {
266
+ border-bottom: 0;
267
+ /* The long free-text answer may flow onto the next page, but never leave
268
+ one or two stray lines behind. */
269
+ break-inside: auto;
270
+ page-break-inside: auto;
271
+ orphans: 3;
272
+ widows: 3;
273
+ }
274
+ .ir-section {
275
+ break-after: avoid;
276
+ border-bottom: 1px solid #8a8a8a;
277
+ }
278
+ </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": "4.118.0",
5
+ "version": "4.118.1",
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.",