@7365admin1/layer-common 3.0.18 → 3.0.20
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 +12 -0
- package/components/BuildingManagement/buildings.vue +7 -4
- package/components/BuildingManagement/units.vue +187 -9
- package/components/CleaningScheduleMain.vue +4 -0
- package/components/ClientMain.vue +189 -39
- package/components/DashboardMain.vue +1 -7
- package/components/HidAccessLogDashboard.vue +184 -21
- package/components/HidReaderForm.vue +20 -12
- package/components/HidReaderManagement.vue +113 -80
- package/components/Input/DateTimePicker.vue +152 -137
- package/components/MemberInformation.vue +240 -163
- package/components/PassInformation.vue +6 -4
- package/components/ServiceProviderMain.vue +43 -20
- package/components/VisitorForm.vue +41 -18
- package/composables/useBuilding.ts +14 -0
- package/composables/useServiceProvider.ts +2 -1
- package/composables/useVisitor.ts +19 -15
- package/package.json +1 -1
- package/pages/[org]/[site]/access-mgmt/access-logs/index.vue +3 -1
- package/types/visitor.d.ts +1 -1
|
@@ -1,186 +1,201 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
<div class="d-flex flex-column">
|
|
3
|
+
<v-text-field
|
|
4
|
+
v-bind="$attrs"
|
|
5
|
+
ref="dateTimePickerRef"
|
|
6
|
+
:model-value="dateTimeFormattedReadOnly"
|
|
7
|
+
autocomplete="off"
|
|
8
|
+
:placeholder="inputPlaceholder"
|
|
9
|
+
:rules="rules"
|
|
10
|
+
style="z-index: 10"
|
|
11
|
+
@click="openDatePicker"
|
|
12
|
+
>
|
|
13
|
+
<template #append-inner>
|
|
14
|
+
<v-icon icon="mdi-calendar" @click.stop="openDatePicker" />
|
|
15
|
+
</template>
|
|
16
|
+
</v-text-field>
|
|
17
|
+
<div class="w-100 d-flex align-end ga-3 hidden-input">
|
|
18
|
+
<input
|
|
19
|
+
ref="dateInput"
|
|
20
|
+
:type="inputType"
|
|
21
|
+
v-model="dateTime"
|
|
22
|
+
:min="minValue"
|
|
23
|
+
/>
|
|
12
24
|
</div>
|
|
25
|
+
</div>
|
|
13
26
|
</template>
|
|
14
27
|
|
|
15
28
|
<script setup lang="ts">
|
|
16
|
-
import { ref, computed, watch } from
|
|
29
|
+
import { ref, computed, watch } from "vue";
|
|
17
30
|
|
|
18
31
|
const prop = defineProps({
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
const { formatDateISO8601 } = useUtils()
|
|
38
|
-
const dateTime = defineModel<string | null>({ default: null }) //2025-10-10T13:09 format
|
|
39
|
-
const dateTimeUTC = defineModel<string | null>(
|
|
40
|
-
|
|
41
|
-
const dateTimeFormattedReadOnly = ref<string | null>(null)
|
|
42
|
-
const inputType = computed(() => (prop.dateOnly ?
|
|
43
|
-
|
|
32
|
+
rules: {
|
|
33
|
+
type: Array as PropType<Array<any>>,
|
|
34
|
+
default: () => [],
|
|
35
|
+
},
|
|
36
|
+
placeholder: {
|
|
37
|
+
type: String,
|
|
38
|
+
default: "DD/MM/YYYY, HH:MM AM/PM",
|
|
39
|
+
},
|
|
40
|
+
dateOnly: {
|
|
41
|
+
type: Boolean,
|
|
42
|
+
default: false,
|
|
43
|
+
},
|
|
44
|
+
min: {
|
|
45
|
+
type: String,
|
|
46
|
+
default: undefined,
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const { formatDateISO8601 } = useUtils();
|
|
51
|
+
const dateTime = defineModel<string | null>({ default: null }); //2025-10-10T13:09 format
|
|
52
|
+
const dateTimeUTC = defineModel<string | null>("utc", { default: null }); // UTC format
|
|
53
|
+
|
|
54
|
+
const dateTimeFormattedReadOnly = ref<string | null>(null);
|
|
55
|
+
const inputType = computed(() => (prop.dateOnly ? "date" : "datetime-local"));
|
|
44
56
|
|
|
45
57
|
const minValue = computed(() => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
})
|
|
52
|
-
const inputPlaceholder = computed(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const isInitialLoad = ref(true)
|
|
58
|
+
if (!prop.min) return undefined;
|
|
59
|
+
if (/^\d{4}-\d{2}-\d{2}$/.test(prop.min)) {
|
|
60
|
+
return prop.dateOnly ? prop.min : `${prop.min}T00:00`;
|
|
61
|
+
}
|
|
62
|
+
return prop.min;
|
|
63
|
+
});
|
|
64
|
+
const inputPlaceholder = computed(
|
|
65
|
+
() =>
|
|
66
|
+
prop.placeholder ||
|
|
67
|
+
(prop.dateOnly ? "MM/DD/YYYY" : "DD/MM/YYYY, HH:MM AM/PM")
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const dateInput = ref<HTMLInputElement | null>(null);
|
|
71
|
+
const dateTimePickerRef = ref<HTMLInputElement | null>(null);
|
|
72
|
+
|
|
73
|
+
const isInitialLoad = ref(true);
|
|
63
74
|
|
|
64
75
|
function openDatePicker() {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
76
|
+
setTimeout(() => {
|
|
77
|
+
dateInput.value?.showPicker?.();
|
|
78
|
+
}, 0);
|
|
68
79
|
}
|
|
69
80
|
|
|
70
81
|
function validate() {
|
|
71
|
-
|
|
82
|
+
(dateTimePickerRef.value as any)?.validate();
|
|
72
83
|
}
|
|
73
84
|
|
|
74
85
|
function convertToReadableFormat(dateStr: string): string {
|
|
86
|
+
if (!dateStr) return "";
|
|
75
87
|
|
|
76
|
-
|
|
88
|
+
const date = new Date(dateStr);
|
|
89
|
+
if (Number.isNaN(date.getTime())) return "";
|
|
77
90
|
|
|
78
|
-
|
|
79
|
-
|
|
91
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
92
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
93
|
+
const year = date.getFullYear();
|
|
80
94
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
95
|
+
if (prop.dateOnly) {
|
|
96
|
+
return `${day}/${month}/${year}`;
|
|
97
|
+
}
|
|
84
98
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
99
|
+
let hours = date.getHours();
|
|
100
|
+
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
88
101
|
|
|
89
|
-
|
|
90
|
-
|
|
102
|
+
const ampm = hours >= 12 ? "PM" : "AM";
|
|
103
|
+
hours = hours % 12;
|
|
104
|
+
hours = hours ? hours : 12;
|
|
91
105
|
|
|
92
|
-
|
|
93
|
-
hours = hours % 12
|
|
94
|
-
hours = hours ? hours : 12
|
|
106
|
+
const formattedTime = `${String(hours).padStart(2, "0")}:${minutes} ${ampm}`;
|
|
95
107
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
return `${day}/${month}/${year}, ${formattedTime}`
|
|
108
|
+
return `${day}/${month}/${year}, ${formattedTime}`;
|
|
99
109
|
}
|
|
100
110
|
|
|
101
111
|
function toDateOnlyInputValue(dateStr: string): string {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
112
|
+
if (!dateStr) return "";
|
|
113
|
+
if (/^\d{4}-\d{2}-\d{2}$/.test(dateStr)) return dateStr;
|
|
114
|
+
const date = new Date(dateStr);
|
|
115
|
+
if (Number.isNaN(date.getTime())) return "";
|
|
116
|
+
const year = date.getFullYear();
|
|
117
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
118
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
119
|
+
return `${year}-${month}-${day}`;
|
|
110
120
|
}
|
|
111
121
|
|
|
112
|
-
function handleInitialDate(){
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
} else {
|
|
128
|
-
const localDate = new Date(dateUTC)
|
|
129
|
-
dateTime.value = formatDateISO8601(localDate)
|
|
130
|
-
}
|
|
122
|
+
function handleInitialDate() {
|
|
123
|
+
const dateDefault = dateTime.value;
|
|
124
|
+
const dateUTC = dateTimeUTC.value;
|
|
125
|
+
if (dateDefault) {
|
|
126
|
+
dateTimeFormattedReadOnly.value = convertToReadableFormat(dateDefault);
|
|
127
|
+
if (prop.dateOnly) {
|
|
128
|
+
dateTimeUTC.value = toDateOnlyInputValue(dateDefault);
|
|
129
|
+
} else {
|
|
130
|
+
const localDate = new Date(dateDefault);
|
|
131
|
+
dateTimeUTC.value = localDate.toISOString();
|
|
132
|
+
}
|
|
133
|
+
} else if (dateUTC) {
|
|
134
|
+
dateTimeFormattedReadOnly.value = convertToReadableFormat(dateUTC);
|
|
135
|
+
if (prop.dateOnly) {
|
|
136
|
+
dateTime.value = toDateOnlyInputValue(dateUTC);
|
|
131
137
|
} else {
|
|
132
|
-
|
|
138
|
+
const localDate = new Date(dateUTC);
|
|
139
|
+
dateTime.value = formatDateISO8601(localDate);
|
|
133
140
|
}
|
|
141
|
+
} else {
|
|
142
|
+
dateTimeFormattedReadOnly.value = null;
|
|
143
|
+
}
|
|
134
144
|
}
|
|
135
145
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
146
|
+
watch(
|
|
147
|
+
dateTime,
|
|
148
|
+
(dateVal) => {
|
|
149
|
+
if (isInitialLoad.value) return; // ignore the first run
|
|
139
150
|
if (!dateVal) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
151
|
+
dateTimeFormattedReadOnly.value = null;
|
|
152
|
+
dateTimeUTC.value = null;
|
|
153
|
+
return;
|
|
143
154
|
}
|
|
144
155
|
|
|
145
|
-
dateTimeFormattedReadOnly.value = convertToReadableFormat(dateVal)
|
|
156
|
+
dateTimeFormattedReadOnly.value = convertToReadableFormat(dateVal);
|
|
146
157
|
if (prop.dateOnly) {
|
|
147
|
-
|
|
158
|
+
dateTimeUTC.value = toDateOnlyInputValue(dateVal);
|
|
148
159
|
} else {
|
|
149
|
-
|
|
150
|
-
|
|
160
|
+
const localDate = new Date(dateVal);
|
|
161
|
+
dateTimeUTC.value = localDate.toISOString();
|
|
151
162
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
163
|
+
},
|
|
164
|
+
{ immediate: false }
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
watch(
|
|
168
|
+
dateTimeUTC,
|
|
169
|
+
() => {
|
|
170
|
+
handleInitialDate();
|
|
171
|
+
},
|
|
172
|
+
{ immediate: true }
|
|
173
|
+
);
|
|
159
174
|
|
|
160
175
|
onMounted(async () => {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
173
|
-
|
|
176
|
+
await nextTick();
|
|
177
|
+
isInitialLoad.value = false;
|
|
178
|
+
// Wait until Vuetify renders its internal input
|
|
179
|
+
const nativeInput = (dateTimePickerRef.value as any)?.$el?.querySelector(
|
|
180
|
+
"input"
|
|
181
|
+
);
|
|
182
|
+
if (nativeInput) {
|
|
183
|
+
nativeInput.addEventListener("click", (e: MouseEvent) => {
|
|
184
|
+
e.stopPropagation();
|
|
185
|
+
openDatePicker();
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
});
|
|
174
189
|
|
|
175
190
|
defineExpose({
|
|
176
|
-
|
|
177
|
-
})
|
|
191
|
+
validate,
|
|
192
|
+
});
|
|
178
193
|
</script>
|
|
179
194
|
|
|
180
195
|
<style scoped>
|
|
181
196
|
.hidden-input {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
197
|
+
opacity: 0;
|
|
198
|
+
height: 0;
|
|
199
|
+
width: 1px;
|
|
185
200
|
}
|
|
186
201
|
</style>
|