@eeplatform/nuxt-layer-common 1.2.11 → 1.3.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 +12 -0
- package/components/Calendar.vue +199 -0
- package/components/CalendarDay.vue +531 -0
- package/components/CalendarMonth.vue +452 -0
- package/components/CalendarWeek.vue +545 -0
- package/components/CalendarYear.vue +295 -0
- package/components/Layout/Header.vue +18 -16
- package/components/Layout/NavigationDrawer.vue +2 -0
- package/components/OfficeForm.vue +194 -0
- package/components/OfficeMain.vue +126 -0
- package/components/SchoolFormUpload.vue +7 -50
- package/composables/useOffice.ts +40 -0
- package/composables/usePlantilla.ts +52 -0
- package/package.json +1 -1
- package/plugins/API.ts +12 -0
- package/plugins/vuetify.ts +9 -0
- package/types/office.d.ts +12 -0
- package/types/plantilla.d.ts +29 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="year-view" :style="{ height: calendarHeight }">
|
|
3
|
+
<div class="year-grid">
|
|
4
|
+
<div
|
|
5
|
+
v-for="month in yearMonths"
|
|
6
|
+
:key="month.month"
|
|
7
|
+
class="mini-month"
|
|
8
|
+
@click="onMonthClick(month)"
|
|
9
|
+
>
|
|
10
|
+
<div class="mini-month-header">
|
|
11
|
+
{{ month.name }}
|
|
12
|
+
</div>
|
|
13
|
+
<div class="mini-month-grid">
|
|
14
|
+
<!-- Weekday headers for mini calendar -->
|
|
15
|
+
<div class="mini-weekday-header">
|
|
16
|
+
<div
|
|
17
|
+
v-for="day in ['S', 'M', 'T', 'W', 'T', 'F', 'S']"
|
|
18
|
+
:key="day"
|
|
19
|
+
class="mini-weekday"
|
|
20
|
+
>
|
|
21
|
+
{{ day }}
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
<!-- Calendar weeks -->
|
|
25
|
+
<div
|
|
26
|
+
v-for="(week, weekIndex) in month.weeks"
|
|
27
|
+
:key="weekIndex"
|
|
28
|
+
class="mini-week"
|
|
29
|
+
>
|
|
30
|
+
<div
|
|
31
|
+
v-for="(day, dayIndex) in week"
|
|
32
|
+
:key="dayIndex"
|
|
33
|
+
class="mini-day"
|
|
34
|
+
:class="{
|
|
35
|
+
'has-events': day.hasEvents,
|
|
36
|
+
today: day.isToday,
|
|
37
|
+
'other-month': day.isOtherMonth,
|
|
38
|
+
'current-month': !day.isOtherMonth && day.dayNumber,
|
|
39
|
+
}"
|
|
40
|
+
>
|
|
41
|
+
{{ day.dayNumber }}
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
</template>
|
|
49
|
+
|
|
50
|
+
<script setup>
|
|
51
|
+
import { computed } from "vue";
|
|
52
|
+
|
|
53
|
+
const props = defineProps({
|
|
54
|
+
current: {
|
|
55
|
+
type: Date,
|
|
56
|
+
required: true,
|
|
57
|
+
},
|
|
58
|
+
events: {
|
|
59
|
+
type: Array,
|
|
60
|
+
default: () => [],
|
|
61
|
+
},
|
|
62
|
+
calendarHeight: {
|
|
63
|
+
type: String,
|
|
64
|
+
default: "calc(100vh - 100px)",
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const emit = defineEmits(["monthClick"]);
|
|
69
|
+
|
|
70
|
+
// Helper functions for event calculations
|
|
71
|
+
const isSameDay = (date1, date2) => {
|
|
72
|
+
return date1.toDateString() === date2.toDateString();
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const isDateInRange = (date, startDate, endDate) => {
|
|
76
|
+
const checkDate = new Date(date);
|
|
77
|
+
checkDate.setHours(0, 0, 0, 0);
|
|
78
|
+
const start = new Date(startDate);
|
|
79
|
+
start.setHours(0, 0, 0, 0);
|
|
80
|
+
const end = new Date(endDate);
|
|
81
|
+
end.setHours(0, 0, 0, 0);
|
|
82
|
+
|
|
83
|
+
return checkDate >= start && checkDate <= end;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const getEventsForDate = (date) => {
|
|
87
|
+
return props.events.filter((event) =>
|
|
88
|
+
isDateInRange(date, event.startDate, event.endDate)
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// Year view computed properties
|
|
93
|
+
const yearMonths = computed(() => {
|
|
94
|
+
const months = [];
|
|
95
|
+
const year = props.current.getFullYear();
|
|
96
|
+
|
|
97
|
+
for (let month = 0; month < 12; month++) {
|
|
98
|
+
const monthData = {
|
|
99
|
+
month,
|
|
100
|
+
name: new Date(year, month, 1).toLocaleDateString("en-US", {
|
|
101
|
+
month: "long",
|
|
102
|
+
}),
|
|
103
|
+
weeks: [],
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const firstDay = new Date(year, month, 1).getDay();
|
|
107
|
+
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
108
|
+
const prevMonth = month === 0 ? 11 : month - 1;
|
|
109
|
+
const prevYear = month === 0 ? year - 1 : year;
|
|
110
|
+
const prevMonthDays = new Date(prevYear, prevMonth + 1, 0).getDate();
|
|
111
|
+
|
|
112
|
+
let week = [];
|
|
113
|
+
|
|
114
|
+
// Add days from previous month to fill the beginning of the first week
|
|
115
|
+
for (let i = firstDay - 1; i >= 0; i--) {
|
|
116
|
+
week.push({
|
|
117
|
+
dayNumber: prevMonthDays - i,
|
|
118
|
+
date: new Date(prevYear, prevMonth, prevMonthDays - i),
|
|
119
|
+
isToday: false,
|
|
120
|
+
hasEvents: false,
|
|
121
|
+
isOtherMonth: true,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Add days of the current month
|
|
126
|
+
for (let day = 1; day <= daysInMonth; day++) {
|
|
127
|
+
const date = new Date(year, month, day);
|
|
128
|
+
const eventsForDate = getEventsForDate(date);
|
|
129
|
+
|
|
130
|
+
week.push({
|
|
131
|
+
dayNumber: day,
|
|
132
|
+
date: date,
|
|
133
|
+
isToday: isSameDay(date, new Date()),
|
|
134
|
+
hasEvents: eventsForDate.length > 0,
|
|
135
|
+
isOtherMonth: false,
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
if (week.length === 7) {
|
|
139
|
+
monthData.weeks.push(week);
|
|
140
|
+
week = [];
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Add days from next month to complete the last week
|
|
145
|
+
let nextMonthDay = 1;
|
|
146
|
+
while (week.length < 7) {
|
|
147
|
+
const nextMonth = month === 11 ? 0 : month + 1;
|
|
148
|
+
const nextYear = month === 11 ? year + 1 : year;
|
|
149
|
+
|
|
150
|
+
week.push({
|
|
151
|
+
dayNumber: nextMonthDay,
|
|
152
|
+
date: new Date(nextYear, nextMonth, nextMonthDay),
|
|
153
|
+
isToday: false,
|
|
154
|
+
hasEvents: false,
|
|
155
|
+
isOtherMonth: true,
|
|
156
|
+
});
|
|
157
|
+
nextMonthDay++;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (week.length > 0) {
|
|
161
|
+
monthData.weeks.push(week);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
months.push(monthData);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return months;
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// Handle month click in year view
|
|
171
|
+
const onMonthClick = (monthData) => {
|
|
172
|
+
emit("monthClick", monthData);
|
|
173
|
+
};
|
|
174
|
+
</script>
|
|
175
|
+
|
|
176
|
+
<style scoped>
|
|
177
|
+
/* Year View Styles */
|
|
178
|
+
.year-view {
|
|
179
|
+
padding: 20px;
|
|
180
|
+
overflow-y: auto;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.year-grid {
|
|
184
|
+
display: grid;
|
|
185
|
+
grid-template-columns: repeat(4, 1fr);
|
|
186
|
+
gap: 20px;
|
|
187
|
+
width: 100%;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.mini-month {
|
|
191
|
+
border: 1px solid #e0e0e0;
|
|
192
|
+
border-radius: 8px;
|
|
193
|
+
overflow: hidden;
|
|
194
|
+
cursor: pointer;
|
|
195
|
+
transition: all 0.2s ease;
|
|
196
|
+
background: white;
|
|
197
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.mini-month:hover {
|
|
201
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
202
|
+
transform: translateY(-1px);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.mini-month-header {
|
|
206
|
+
background-color: #1976d2;
|
|
207
|
+
color: white;
|
|
208
|
+
padding: 12px;
|
|
209
|
+
text-align: center;
|
|
210
|
+
font-weight: 600;
|
|
211
|
+
font-size: 1rem;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.mini-month-grid {
|
|
215
|
+
padding: 12px;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.mini-weekday-header {
|
|
219
|
+
display: grid;
|
|
220
|
+
grid-template-columns: repeat(7, 1fr);
|
|
221
|
+
gap: 2px;
|
|
222
|
+
margin-bottom: 4px;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.mini-weekday {
|
|
226
|
+
text-align: center;
|
|
227
|
+
font-size: 0.7rem;
|
|
228
|
+
font-weight: 600;
|
|
229
|
+
color: #666;
|
|
230
|
+
padding: 4px 0;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.mini-week {
|
|
234
|
+
display: grid;
|
|
235
|
+
grid-template-columns: repeat(7, 1fr);
|
|
236
|
+
gap: 2px;
|
|
237
|
+
margin-bottom: 2px;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.mini-day {
|
|
241
|
+
aspect-ratio: 1;
|
|
242
|
+
display: flex;
|
|
243
|
+
align-items: center;
|
|
244
|
+
justify-content: center;
|
|
245
|
+
font-size: 0.8rem;
|
|
246
|
+
border-radius: 4px;
|
|
247
|
+
cursor: pointer;
|
|
248
|
+
transition: all 0.15s ease;
|
|
249
|
+
min-height: 24px;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.mini-day:hover {
|
|
253
|
+
background-color: #e3f2fd;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.mini-day.current-month {
|
|
257
|
+
color: #333;
|
|
258
|
+
font-weight: 500;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
.mini-day.has-events {
|
|
262
|
+
background-color: #e3f2fd;
|
|
263
|
+
color: #1976d2;
|
|
264
|
+
font-weight: 600;
|
|
265
|
+
position: relative;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.mini-day.has-events::after {
|
|
269
|
+
content: "";
|
|
270
|
+
position: absolute;
|
|
271
|
+
bottom: 2px;
|
|
272
|
+
left: 50%;
|
|
273
|
+
transform: translateX(-50%);
|
|
274
|
+
width: 4px;
|
|
275
|
+
height: 4px;
|
|
276
|
+
background-color: #1976d2;
|
|
277
|
+
border-radius: 50%;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.mini-day.today {
|
|
281
|
+
background-color: #1976d2;
|
|
282
|
+
color: white;
|
|
283
|
+
font-weight: 700;
|
|
284
|
+
box-shadow: 0 2px 4px rgba(25, 118, 210, 0.3);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.mini-day.today.has-events::after {
|
|
288
|
+
background-color: white;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.mini-day.other-month {
|
|
292
|
+
color: #ccc;
|
|
293
|
+
font-weight: 400;
|
|
294
|
+
}
|
|
295
|
+
</style>
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
<v-col cols="12">
|
|
50
50
|
<v-card width="100%" variant="tonal" rounded="t-xl b-0">
|
|
51
51
|
<v-row class="pa-4">
|
|
52
|
-
<template v-for="item in
|
|
52
|
+
<template v-for="item in props.defaults">
|
|
53
53
|
<v-col cols="4">
|
|
54
54
|
<v-btn
|
|
55
55
|
:prepend-icon="item.icon"
|
|
@@ -204,6 +204,23 @@ const props = defineProps({
|
|
|
204
204
|
type: String,
|
|
205
205
|
default: "Title",
|
|
206
206
|
},
|
|
207
|
+
defaults: {
|
|
208
|
+
type: Array as PropType<Array<TApp>>,
|
|
209
|
+
default: () => [
|
|
210
|
+
{
|
|
211
|
+
title: "Account",
|
|
212
|
+
icon: "ph:user-circle-bold",
|
|
213
|
+
link: "",
|
|
214
|
+
landingPage: "home",
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
title: "Admin",
|
|
218
|
+
icon: "ph:shield-checkered-bold",
|
|
219
|
+
link: "",
|
|
220
|
+
landingPage: "home",
|
|
221
|
+
},
|
|
222
|
+
],
|
|
223
|
+
},
|
|
207
224
|
apps: {
|
|
208
225
|
type: Array as PropType<Array<TApp>>,
|
|
209
226
|
default: () => [],
|
|
@@ -267,21 +284,6 @@ const name = computed(() => {
|
|
|
267
284
|
|
|
268
285
|
return name;
|
|
269
286
|
});
|
|
270
|
-
|
|
271
|
-
const defaultApps = computed<Array<TApp>>(() => [
|
|
272
|
-
{
|
|
273
|
-
title: "Account",
|
|
274
|
-
icon: "ph:user-circle-bold",
|
|
275
|
-
link: APP_ACCOUNT,
|
|
276
|
-
landingPage: "home",
|
|
277
|
-
},
|
|
278
|
-
{
|
|
279
|
-
title: "Admin",
|
|
280
|
-
icon: "ph:shield-checkered-bold",
|
|
281
|
-
link: APP_ADMIN,
|
|
282
|
-
landingPage: "home",
|
|
283
|
-
},
|
|
284
|
-
]);
|
|
285
287
|
</script>
|
|
286
288
|
|
|
287
289
|
<style scoped>
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-card width="100%">
|
|
3
|
+
<v-toolbar>
|
|
4
|
+
<v-row no-gutters class="fill-height px-6" align="center">
|
|
5
|
+
<span class="font-weight-bold text-h5">
|
|
6
|
+
{{ props.title }}
|
|
7
|
+
</span>
|
|
8
|
+
</v-row>
|
|
9
|
+
</v-toolbar>
|
|
10
|
+
<v-card-text style="max-height: 100vh; overflow-y: auto">
|
|
11
|
+
<v-form v-model="validForm" :disabled="disable">
|
|
12
|
+
<v-row no-gutters>
|
|
13
|
+
<v-col cols="12" class="mt-2">
|
|
14
|
+
<v-row no-gutters>
|
|
15
|
+
<InputLabel class="text-capitalize" title="Type" required />
|
|
16
|
+
<v-col cols="12">
|
|
17
|
+
<v-autocomplete
|
|
18
|
+
v-model="office.type"
|
|
19
|
+
density="comfortable"
|
|
20
|
+
:rules="[requiredRule]"
|
|
21
|
+
:items="officeTypes"
|
|
22
|
+
></v-autocomplete>
|
|
23
|
+
</v-col>
|
|
24
|
+
</v-row>
|
|
25
|
+
</v-col>
|
|
26
|
+
|
|
27
|
+
<v-col cols="12" class="mt-2">
|
|
28
|
+
<v-row no-gutters>
|
|
29
|
+
<InputLabel class="text-capitalize" title="Code" required />
|
|
30
|
+
<v-col cols="12">
|
|
31
|
+
<v-text-field
|
|
32
|
+
v-model="office.code"
|
|
33
|
+
density="comfortable"
|
|
34
|
+
:rules="[requiredRule]"
|
|
35
|
+
></v-text-field>
|
|
36
|
+
</v-col>
|
|
37
|
+
</v-row>
|
|
38
|
+
</v-col>
|
|
39
|
+
|
|
40
|
+
<v-col cols="12" class="mt-2">
|
|
41
|
+
<v-row no-gutters>
|
|
42
|
+
<InputLabel class="text-capitalize" title="Name" required />
|
|
43
|
+
<v-col cols="12">
|
|
44
|
+
<v-text-field
|
|
45
|
+
v-model="office.name"
|
|
46
|
+
density="comfortable"
|
|
47
|
+
:rules="[requiredRule]"
|
|
48
|
+
></v-text-field>
|
|
49
|
+
</v-col>
|
|
50
|
+
</v-row>
|
|
51
|
+
</v-col>
|
|
52
|
+
|
|
53
|
+
<v-col v-if="hasParent" cols="12" class="mt-2">
|
|
54
|
+
<v-row no-gutters>
|
|
55
|
+
<InputLabel class="text-capitalize" title="Parent" required />
|
|
56
|
+
<v-col cols="12">
|
|
57
|
+
<v-autocomplete
|
|
58
|
+
v-model="office.parent"
|
|
59
|
+
density="comfortable"
|
|
60
|
+
:rules="[requiredRule]"
|
|
61
|
+
></v-autocomplete>
|
|
62
|
+
</v-col>
|
|
63
|
+
</v-row>
|
|
64
|
+
</v-col>
|
|
65
|
+
|
|
66
|
+
<v-col cols="12" class="mt-2">
|
|
67
|
+
<v-checkbox v-model="createMore" density="comfortable" hide-details>
|
|
68
|
+
<template #label>
|
|
69
|
+
<span class="text-subtitle-2 font-weight-bold">
|
|
70
|
+
Create more
|
|
71
|
+
</span>
|
|
72
|
+
</template>
|
|
73
|
+
</v-checkbox>
|
|
74
|
+
</v-col>
|
|
75
|
+
|
|
76
|
+
<v-col cols="12" class="my-2">
|
|
77
|
+
<v-row no-gutters>
|
|
78
|
+
<v-col cols="12" class="text-center">
|
|
79
|
+
<span
|
|
80
|
+
class="text-none text-subtitle-2 font-weight-medium text-error"
|
|
81
|
+
>
|
|
82
|
+
{{ message }}
|
|
83
|
+
</span>
|
|
84
|
+
</v-col>
|
|
85
|
+
</v-row>
|
|
86
|
+
</v-col>
|
|
87
|
+
</v-row>
|
|
88
|
+
</v-form>
|
|
89
|
+
</v-card-text>
|
|
90
|
+
|
|
91
|
+
<v-toolbar density="compact">
|
|
92
|
+
<v-row no-gutters>
|
|
93
|
+
<v-col cols="6">
|
|
94
|
+
<v-btn
|
|
95
|
+
tile
|
|
96
|
+
block
|
|
97
|
+
variant="text"
|
|
98
|
+
class="text-none"
|
|
99
|
+
size="48"
|
|
100
|
+
@click="cancel"
|
|
101
|
+
>
|
|
102
|
+
Cancel
|
|
103
|
+
</v-btn>
|
|
104
|
+
</v-col>
|
|
105
|
+
|
|
106
|
+
<v-col cols="6">
|
|
107
|
+
<v-btn
|
|
108
|
+
tile
|
|
109
|
+
block
|
|
110
|
+
variant="flat"
|
|
111
|
+
color="black"
|
|
112
|
+
class="text-none"
|
|
113
|
+
size="48"
|
|
114
|
+
:disabled="!validForm"
|
|
115
|
+
@click="submit"
|
|
116
|
+
>
|
|
117
|
+
Submit
|
|
118
|
+
</v-btn>
|
|
119
|
+
</v-col>
|
|
120
|
+
</v-row>
|
|
121
|
+
</v-toolbar>
|
|
122
|
+
</v-card>
|
|
123
|
+
</template>
|
|
124
|
+
|
|
125
|
+
<script setup lang="ts">
|
|
126
|
+
const props = defineProps({
|
|
127
|
+
title: {
|
|
128
|
+
type: String,
|
|
129
|
+
default: "Office Form",
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const emit = defineEmits(["cancel", "success", "success:create-more"]);
|
|
134
|
+
|
|
135
|
+
const validForm = ref(false);
|
|
136
|
+
|
|
137
|
+
const office = ref({
|
|
138
|
+
type: "",
|
|
139
|
+
code: "",
|
|
140
|
+
parent: "",
|
|
141
|
+
name: "",
|
|
142
|
+
path: "",
|
|
143
|
+
status: "active",
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
watchEffect(() => {
|
|
147
|
+
if (office.value.code) {
|
|
148
|
+
office.value.path = office.value.code.toUpperCase();
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const officeTypes = ["office", "section", "unit"];
|
|
153
|
+
|
|
154
|
+
const hasParent = computed(() => {
|
|
155
|
+
return ["section", "unit"].includes(office.value.type);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
const createMore = ref(false);
|
|
159
|
+
const disable = ref(false);
|
|
160
|
+
|
|
161
|
+
const { requiredRule } = useUtils();
|
|
162
|
+
|
|
163
|
+
const message = ref("");
|
|
164
|
+
const type = defineModel("type", {
|
|
165
|
+
type: String,
|
|
166
|
+
default: "",
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
const { add } = useOffice();
|
|
170
|
+
|
|
171
|
+
async function submit() {
|
|
172
|
+
disable.value = true;
|
|
173
|
+
try {
|
|
174
|
+
await add(office.value);
|
|
175
|
+
if (createMore.value) {
|
|
176
|
+
message.value = "";
|
|
177
|
+
emit("success:create-more");
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
emit("success");
|
|
182
|
+
} catch (error: any) {
|
|
183
|
+
message.value = error.response._data.message;
|
|
184
|
+
} finally {
|
|
185
|
+
disable.value = false;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function cancel() {
|
|
190
|
+
createMore.value = false;
|
|
191
|
+
message.value = "";
|
|
192
|
+
emit("cancel");
|
|
193
|
+
}
|
|
194
|
+
</script>
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-row no-gutters>
|
|
3
|
+
<v-col cols="12" class="mb-2">
|
|
4
|
+
<v-row no-gutters>
|
|
5
|
+
<v-btn
|
|
6
|
+
class="text-none mr-2"
|
|
7
|
+
rounded="pill"
|
|
8
|
+
variant="tonal"
|
|
9
|
+
@click="dialogCreate = true"
|
|
10
|
+
size="large"
|
|
11
|
+
>
|
|
12
|
+
Add
|
|
13
|
+
</v-btn>
|
|
14
|
+
</v-row>
|
|
15
|
+
</v-col>
|
|
16
|
+
|
|
17
|
+
<v-col cols="12">
|
|
18
|
+
<v-card width="100%" variant="outlined" border="thin" rounded="lg">
|
|
19
|
+
<v-toolbar density="compact" color="grey-lighten-4">
|
|
20
|
+
<template #prepend>
|
|
21
|
+
<v-btn fab icon density="comfortable" @click="">
|
|
22
|
+
<v-icon>mdi-refresh</v-icon>
|
|
23
|
+
</v-btn>
|
|
24
|
+
</template>
|
|
25
|
+
|
|
26
|
+
<template #append>
|
|
27
|
+
<v-row no-gutters justify="end" align="center">
|
|
28
|
+
<span class="mr-2 text-caption text-fontgray">
|
|
29
|
+
{{ pageRange }}
|
|
30
|
+
</span>
|
|
31
|
+
<local-pagination
|
|
32
|
+
v-model="page"
|
|
33
|
+
:length="pages"
|
|
34
|
+
@update:value=""
|
|
35
|
+
/>
|
|
36
|
+
</v-row>
|
|
37
|
+
</template>
|
|
38
|
+
</v-toolbar>
|
|
39
|
+
|
|
40
|
+
<v-data-table
|
|
41
|
+
:headers="headers"
|
|
42
|
+
:items="items"
|
|
43
|
+
item-value="_id"
|
|
44
|
+
items-per-page="20"
|
|
45
|
+
fixed-header
|
|
46
|
+
hide-default-footer
|
|
47
|
+
@click:row="tableRowClickHandler"
|
|
48
|
+
style="max-height: calc(100vh - (200px))"
|
|
49
|
+
>
|
|
50
|
+
</v-data-table>
|
|
51
|
+
</v-card>
|
|
52
|
+
</v-col>
|
|
53
|
+
|
|
54
|
+
<!-- dialog -->
|
|
55
|
+
<v-dialog v-model="dialogCreate" persistent width="450">
|
|
56
|
+
<OfficeForm
|
|
57
|
+
title="Add"
|
|
58
|
+
@cancel="dialogCreate = false"
|
|
59
|
+
@success="successHandler()"
|
|
60
|
+
/>
|
|
61
|
+
</v-dialog>
|
|
62
|
+
</v-row>
|
|
63
|
+
</template>
|
|
64
|
+
|
|
65
|
+
<script setup lang="ts">
|
|
66
|
+
definePageMeta({
|
|
67
|
+
middleware: ["01-auth", "org"],
|
|
68
|
+
secured: true,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const headers = [
|
|
72
|
+
{
|
|
73
|
+
title: "Code",
|
|
74
|
+
value: "code",
|
|
75
|
+
width: "120px",
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
title: "Name",
|
|
79
|
+
value: "name",
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
title: "Type",
|
|
83
|
+
value: "type",
|
|
84
|
+
width: "120px",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
title: "Status",
|
|
88
|
+
value: "status",
|
|
89
|
+
width: "120px",
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
const page = ref(1);
|
|
94
|
+
const pages = ref(0);
|
|
95
|
+
const pageRange = ref("-- - -- of --");
|
|
96
|
+
|
|
97
|
+
const items = ref<Array<Record<string, any>>>([]);
|
|
98
|
+
|
|
99
|
+
const { getAll } = useOffice();
|
|
100
|
+
|
|
101
|
+
const { data: getItems, refresh: refreshOfficeItems } = useLazyAsyncData(
|
|
102
|
+
"get-offices-" + page.value,
|
|
103
|
+
() => getAll(),
|
|
104
|
+
{
|
|
105
|
+
watch: [page],
|
|
106
|
+
immediate: true,
|
|
107
|
+
}
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
watchEffect(() => {
|
|
111
|
+
if (getItems.value) {
|
|
112
|
+
items.value = getItems.value.items;
|
|
113
|
+
pages.value = getItems.value.pages;
|
|
114
|
+
pageRange.value = getItems.value.pageRange;
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
function tableRowClickHandler(_: any, data: any) {}
|
|
119
|
+
|
|
120
|
+
const dialogCreate = ref(false);
|
|
121
|
+
|
|
122
|
+
function successHandler() {
|
|
123
|
+
dialogCreate.value = false;
|
|
124
|
+
refreshOfficeItems();
|
|
125
|
+
}
|
|
126
|
+
</script>
|