@eeplatform/nuxt-layer-common 1.6.0 → 1.7.0

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.
@@ -1,597 +0,0 @@
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
-
11
- <v-card-text style="max-height: 100vh; overflow-y: auto">
12
- <v-form v-model="formValid" :disabled="disable">
13
- <v-row no-gutters>
14
- <v-col cols="12" class="mt-2">
15
- <v-row no-gutters>
16
- <InputLabel
17
- class="text-capitalize"
18
- title="Curriculum"
19
- :required="props.mode !== 'view'"
20
- />
21
- <v-col cols="12">
22
- <v-combobox
23
- v-model="curriculumSubject.curriculum"
24
- v-model:search="searchCurriculum"
25
- density="comfortable"
26
- :rules="[requiredRule]"
27
- :return-object="false"
28
- :items="curriculums"
29
- item-title="name"
30
- item-value="_id"
31
- :error-messages="errorCurriculum"
32
- :readonly="props.mode === 'view'"
33
- >
34
- <template v-slot:no-data>
35
- <v-list-item>
36
- <v-list-item-title>
37
- No results matching "<strong>{{
38
- searchCurriculum
39
- }}</strong
40
- >". Click the search button and try again.
41
- </v-list-item-title>
42
- </v-list-item>
43
- </template>
44
-
45
- <template #append>
46
- <v-btn
47
- variant="tonal"
48
- :disabled="curriculumReqStatus"
49
- class="text-none"
50
- size="48"
51
- width="100"
52
- icon
53
- @click="_getAllCurriculum()"
54
- >
55
- <v-icon>ph:magnifying-glass-bold</v-icon>
56
- </v-btn>
57
- </template>
58
- </v-combobox>
59
- </v-col>
60
- </v-row>
61
- </v-col>
62
-
63
- <v-col cols="12" class="mt-2">
64
- <v-row no-gutters>
65
- <InputLabel
66
- class="text-capitalize"
67
- title="Education Level"
68
- :required="props.mode !== 'view'"
69
- />
70
- <v-col cols="12">
71
- <v-combobox
72
- v-model="curriculumSubject.educationLevel"
73
- density="comfortable"
74
- :rules="[requiredRule]"
75
- :return-object="false"
76
- :items="educationLevels"
77
- :readonly="props.mode === 'view'"
78
- ></v-combobox>
79
- </v-col>
80
- </v-row>
81
- </v-col>
82
-
83
- <v-col cols="12" class="mt-2">
84
- <v-row no-gutters>
85
- <InputLabel
86
- class="text-capitalize"
87
- title="Grade Level"
88
- :required="props.mode !== 'view'"
89
- />
90
- <v-col cols="12">
91
- <v-autocomplete
92
- v-model="curriculumSubject.gradeLevel"
93
- density="comfortable"
94
- :rules="[requiredRule]"
95
- :items="selectedGradeLevels"
96
- :readonly="props.mode === 'view'"
97
- multiple
98
- chips
99
- ></v-autocomplete>
100
- </v-col>
101
- </v-row>
102
- </v-col>
103
-
104
- <v-col cols="12" class="mt-2">
105
- <v-row no-gutters>
106
- <InputLabel
107
- class="text-capitalize"
108
- title="Subject Code"
109
- :required="props.mode !== 'view'"
110
- />
111
- <v-col cols="12">
112
- <v-text-field
113
- v-model="curriculumSubject.subjectCode"
114
- density="comfortable"
115
- :rules="[requiredRule]"
116
- :readonly="props.mode === 'view'"
117
- ></v-text-field>
118
- </v-col>
119
- </v-row>
120
- </v-col>
121
-
122
- <v-col cols="12" class="mt-2">
123
- <v-row no-gutters>
124
- <InputLabel
125
- class="text-capitalize"
126
- title="Subject Name"
127
- :required="props.mode !== 'view'"
128
- />
129
- <v-col cols="12">
130
- <v-text-field
131
- v-model="curriculumSubject.subjectName"
132
- density="comfortable"
133
- :rules="[requiredRule]"
134
- :readonly="props.mode === 'view'"
135
- ></v-text-field>
136
- </v-col>
137
- </v-row>
138
- </v-col>
139
-
140
- <v-col cols="12" class="mt-2">
141
- <v-row no-gutters>
142
- <InputLabel
143
- class="text-capitalize"
144
- title="Subject Type"
145
- :required="props.mode !== 'view'"
146
- />
147
- <v-col cols="12">
148
- <v-autocomplete
149
- v-model="curriculumSubject.subjectType"
150
- density="comfortable"
151
- :rules="[requiredRule]"
152
- :items="subjectTypes"
153
- :readonly="props.mode === 'view'"
154
- ></v-autocomplete>
155
- </v-col>
156
- </v-row>
157
- </v-col>
158
-
159
- <v-col cols="12" class="mt-2">
160
- <v-row no-gutters>
161
- <InputLabel
162
- class="text-capitalize"
163
- title="Session Frequency (Classes per week)"
164
- :required="props.mode !== 'view'"
165
- />
166
- <v-col cols="12">
167
- <v-combobox
168
- v-model.number="curriculumSubject.sessionFrequency"
169
- :items="sessionPerWeekOptions"
170
- density="comfortable"
171
- :rules="[requiredRule]"
172
- type="number"
173
- :readonly="props.mode === 'view'"
174
- ></v-combobox>
175
- </v-col>
176
- </v-row>
177
- </v-col>
178
-
179
- <v-col cols="12" class="mt-2">
180
- <v-row no-gutters>
181
- <InputLabel
182
- class="text-capitalize"
183
- title="Session Duration (Minutes per class)"
184
- :required="props.mode !== 'view'"
185
- />
186
- <v-col cols="12">
187
- <v-combobox
188
- v-model.number="curriculumSubject.sessionDuration"
189
- density="comfortable"
190
- :rules="[requiredRule]"
191
- :items="sessionDurationOptions"
192
- type="number"
193
- :readonly="props.mode === 'view'"
194
- ></v-combobox>
195
- </v-col>
196
- </v-row>
197
- </v-col>
198
-
199
- <v-col v-if="props.mode === 'create'" cols="12">
200
- <v-checkbox v-model="createMore" density="comfortable" hide-details>
201
- <template #label>
202
- <span class="text-subtitle-2 font-weight-bold">
203
- Create more
204
- </span>
205
- </template>
206
- </v-checkbox>
207
- </v-col>
208
-
209
- <v-col v-if="message" cols="12" class="my-2">
210
- <v-row no-gutters>
211
- <v-col cols="12" class="text-center">
212
- <span
213
- class="text-none text-subtitle-2 font-weight-medium text-error"
214
- >
215
- {{ message }}
216
- </span>
217
- </v-col>
218
- </v-row>
219
- </v-col>
220
- </v-row>
221
- </v-form>
222
- </v-card-text>
223
-
224
- <v-toolbar density="compact">
225
- <v-row no-gutters>
226
- <v-col
227
- v-if="modeViewEdit && (props.canEdit || props.canDelete)"
228
- :cols="props.canEdit || props.canDelete ? 6 : 12"
229
- >
230
- <v-btn
231
- tile
232
- block
233
- variant="text"
234
- class="text-none"
235
- size="48"
236
- @click="emit('cancel')"
237
- >
238
- Close
239
- </v-btn>
240
- </v-col>
241
-
242
- <v-col
243
- v-if="modeViewEdit && props.canEdit && !props.canDelete"
244
- :cols="props.canEdit ? 6 : 12"
245
- >
246
- <v-btn
247
- tile
248
- block
249
- variant="flat"
250
- color="black"
251
- class="text-none"
252
- size="48"
253
- @click="emit('cancel')"
254
- >
255
- Edit curriculum
256
- </v-btn>
257
- </v-col>
258
-
259
- <v-col
260
- v-if="modeViewEdit && props.canDelete && !props.canEdit"
261
- :cols="props.canDelete ? 6 : 12"
262
- >
263
- <v-btn
264
- tile
265
- block
266
- variant="flat"
267
- class="text-none text-error"
268
- size="48"
269
- @click="emit('cancel')"
270
- >
271
- Delete curriculum
272
- </v-btn>
273
- </v-col>
274
-
275
- <v-col v-if="hasMoreActions" cols="6">
276
- <v-menu>
277
- <template #activator="{ props }">
278
- <v-btn
279
- block
280
- variant="flat"
281
- color="black"
282
- class="text-none"
283
- height="48"
284
- v-bind="props"
285
- tile
286
- >
287
- More actions
288
- </v-btn>
289
- </template>
290
-
291
- <v-list class="pa-0">
292
- <v-list-item @click="emit('edit')">
293
- <v-list-item-title class="text-subtitle-2">
294
- Edit curriculum
295
- </v-list-item-title>
296
- </v-list-item>
297
-
298
- <v-list-item @click="emit('delete')" class="text-red">
299
- <v-list-item-title class="text-subtitle-2">
300
- Delete curriculum
301
- </v-list-item-title>
302
- </v-list-item>
303
- </v-list>
304
- </v-menu>
305
- </v-col>
306
-
307
- <v-col v-if="props.mode === 'edit'" cols="6">
308
- <v-btn
309
- tile
310
- block
311
- variant="flat"
312
- color="black"
313
- class="text-none"
314
- size="48"
315
- :disabled="!formValid"
316
- @click="submitUpdate"
317
- >
318
- Submit update
319
- </v-btn>
320
- </v-col>
321
-
322
- <v-col v-if="props.mode === 'create'" cols="6">
323
- <v-btn
324
- tile
325
- block
326
- variant="text"
327
- class="text-none"
328
- size="48"
329
- @click="emit('cancel')"
330
- >
331
- Cancel
332
- </v-btn>
333
- </v-col>
334
-
335
- <v-col v-if="props.mode === 'create'" cols="6">
336
- <v-btn
337
- tile
338
- block
339
- variant="flat"
340
- color="black"
341
- class="text-none"
342
- size="48"
343
- :disabled="!formValid"
344
- @click="submit"
345
- >
346
- Submit
347
- </v-btn>
348
- </v-col>
349
- </v-row>
350
- </v-toolbar>
351
- </v-card>
352
- </template>
353
-
354
- <script setup lang="ts">
355
- const props = defineProps({
356
- title: {
357
- type: String,
358
- default: "Subject Form",
359
- },
360
- mode: {
361
- type: String,
362
- default: "create",
363
- },
364
- data: {
365
- type: Object as PropType<TCurriculumSubject>,
366
- default: () => ({}),
367
- },
368
- canEdit: {
369
- type: Boolean,
370
- default: false,
371
- },
372
- canDelete: {
373
- type: Boolean,
374
- default: false,
375
- },
376
- });
377
-
378
- const emit = defineEmits([
379
- "cancel",
380
- "edit",
381
- "delete",
382
- "success",
383
- "success:create-more",
384
- ]);
385
-
386
- const formValid = ref(false);
387
-
388
- const curriculums = ref<Array<TCurriculum>>([]);
389
- const searchCurriculum = ref("");
390
-
391
- const { getAll: getAllCurriculum } = useCurriculum();
392
-
393
- const {
394
- data: getCurriculumReq,
395
- refresh: _getAllCurriculum,
396
- status: getAllCurriculumStatus,
397
- } = await useLazyAsyncData(
398
- `curriculums-as-options-list-${searchCurriculum.value ?? "search"}`,
399
- () =>
400
- getAllCurriculum({
401
- limit: 20,
402
- search: searchCurriculum.value,
403
- })
404
- );
405
-
406
- const curriculumReqStatus = computed(
407
- () => getAllCurriculumStatus.value === "pending"
408
- );
409
-
410
- watchEffect(() => {
411
- if (getCurriculumReq.value) {
412
- curriculums.value = getCurriculumReq.value.items;
413
- }
414
- });
415
-
416
- const curriculumSubject = ref<TCurriculumSubject>({
417
- educationLevel: "",
418
- gradeLevel: [],
419
- subjectCode: "",
420
- subjectName: "",
421
- subjectType: "",
422
- sessionFrequency: 0,
423
- sessionDuration: 0,
424
- totalMinutesPerWeek: 0,
425
- curriculum: "",
426
- curriculumName: "",
427
- });
428
-
429
- watchEffect(() => {
430
- if (curriculumSubject.value.curriculum) {
431
- const selected = curriculums.value.find(
432
- (curr) => curr._id === curriculumSubject.value.curriculum
433
- );
434
-
435
- if (selected) {
436
- curriculumSubject.value.curriculumName = selected.name;
437
- curriculumSubject.value.effectiveSchoolYear = selected.effectiveSchoolYear
438
- .split("-")
439
- .map((year: any) => parseInt(year));
440
- } else {
441
- curriculumSubject.value.curriculumName = "";
442
- curriculumSubject.value.effectiveSchoolYear = [];
443
- }
444
- }
445
- });
446
-
447
- const selectedCurriculum = computed(() =>
448
- curriculums.value.find(
449
- (curr) => curr._id === curriculumSubject.value.curriculum
450
- )
451
- );
452
-
453
- const errorCurriculum = computed(() => {
454
- return !selectedCurriculum.value && curriculumSubject.value.curriculum
455
- ? ["Please select a valid curriculum"]
456
- : [];
457
- });
458
-
459
- if (["view", "edit"].includes(props.mode) && props.data) {
460
- Object.assign(
461
- curriculumSubject.value,
462
- JSON.parse(JSON.stringify(props.data))
463
- );
464
- }
465
-
466
- watchEffect(() => {
467
- curriculumSubject.value.totalMinutesPerWeek =
468
- curriculumSubject.value.sessionFrequency *
469
- curriculumSubject.value.sessionDuration;
470
- });
471
-
472
- const subjectHeaders = [
473
- { title: "Education Level", value: "educationLevel", width: "140px" },
474
- { title: "Grade Level", value: "gradeLevel", width: "120px" },
475
- { title: "Code", value: "subjectCode", width: "100px" },
476
- { title: "Name", value: "subjectName" },
477
- { title: "Type", value: "subjectType", width: "100px" },
478
- { title: "Session Frequency", value: "sessionFrequency", width: "100px" },
479
- { title: "Session Duration", value: "sessionDuration", width: "100px" },
480
- { title: "Minutes Per Week", value: "totalMinutesPerWeek", width: "120px" },
481
- ];
482
-
483
- const dialogSubject = ref(false);
484
- const formSubject = ref(false);
485
-
486
- const { generateSchoolYears, gradeLevels } = useBasicEdu();
487
-
488
- const effectiveSchoolYearOptions = computed(() =>
489
- generateSchoolYears(5, "future")
490
- );
491
-
492
- const selectedGradeLevels = computed(() => {
493
- return curriculumSubject.value.educationLevel
494
- ? gradeLevels.filter(
495
- (level) => level.level === curriculumSubject.value.educationLevel
496
- )
497
- : [];
498
- });
499
-
500
- const { educationLevels } = useBasicEdu();
501
-
502
- const subjectTypes = ["Core", "Applied", "Specialized", "Elective", "Other"];
503
-
504
- const sessionPerWeekOptions = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
505
-
506
- const sessionDurationOptions = [30, 35, 40, 45, 50, 55, 60, 75, 90, 120];
507
-
508
- const createMore = ref(false);
509
- const disable = ref(false);
510
-
511
- const { requiredRule } = useUtils();
512
-
513
- const message = ref("");
514
- const type = defineModel("type", {
515
- type: String,
516
- default: "",
517
- });
518
-
519
- const { add, updateById } = useCurriculumSubject();
520
-
521
- async function submit() {
522
- disable.value = true;
523
- try {
524
- if (props.mode === "create") {
525
- await add(curriculumSubject.value);
526
- }
527
-
528
- console.log(props.mode === "edit");
529
-
530
- if (props.mode === "edit") {
531
- await updateById(curriculumSubject.value._id ?? "", {
532
- curriculum: curriculumSubject.value.curriculum,
533
- educationLevel: curriculumSubject.value.educationLevel,
534
- gradeLevel: curriculumSubject.value.gradeLevel,
535
- subjectCode: curriculumSubject.value.subjectCode,
536
- subjectName: curriculumSubject.value.subjectName,
537
- subjectType: curriculumSubject.value.subjectType,
538
- sessionFrequency: curriculumSubject.value.sessionFrequency,
539
- sessionDuration: curriculumSubject.value.sessionDuration,
540
- totalMinutesPerWeek: curriculumSubject.value.totalMinutesPerWeek,
541
- });
542
- }
543
-
544
- if (createMore.value) {
545
- message.value = "";
546
- emit("success:create-more");
547
- return;
548
- }
549
-
550
- emit("success");
551
- } catch (error: any) {
552
- message.value = error.response._data.message;
553
- } finally {
554
- disable.value = false;
555
- }
556
- }
557
-
558
- const canAdd = computed(() => {
559
- return ["create", "edit"].includes(props.mode);
560
- });
561
-
562
- async function submitUpdate() {
563
- disable.value = true;
564
- try {
565
- await updateById(curriculumSubject.value._id ?? "", {
566
- curriculum: curriculumSubject.value.curriculum,
567
- educationLevel: curriculumSubject.value.educationLevel,
568
- gradeLevel: curriculumSubject.value.gradeLevel,
569
- subjectCode: curriculumSubject.value.subjectCode,
570
- subjectName: curriculumSubject.value.subjectName,
571
- subjectType: curriculumSubject.value.subjectType,
572
- sessionFrequency: curriculumSubject.value.sessionFrequency,
573
- sessionDuration: curriculumSubject.value.sessionDuration,
574
- totalMinutesPerWeek: curriculumSubject.value.totalMinutesPerWeek,
575
- });
576
- if (createMore.value) {
577
- message.value = "";
578
- emit("success:create-more");
579
- return;
580
- }
581
-
582
- emit("success");
583
- } catch (error: any) {
584
- message.value = error.response._data.message;
585
- } finally {
586
- disable.value = false;
587
- }
588
- }
589
-
590
- const modeViewEdit = computed(() => {
591
- return ["view", "edit"].includes(props.mode);
592
- });
593
-
594
- const hasMoreActions = computed(() => {
595
- return props.mode === "view" && props.canEdit && props.canDelete;
596
- });
597
- </script>
@@ -1,58 +0,0 @@
1
- export default function useCurriculumSubject() {
2
- const resource = "basic-education/curriculum/subjects";
3
-
4
- function add(value: TCurriculumSubject) {
5
- return $fetch<Record<string, any>>(`/api/${resource}`, {
6
- method: "POST",
7
- body: value,
8
- });
9
- }
10
-
11
- async function getAll({
12
- page = 1,
13
- search = "",
14
- limit = 10,
15
- status = "active",
16
- schoolYear = 0,
17
- gradeLevel = "",
18
- } = {}) {
19
- return $fetch<Record<string, any>>(`/api/${resource}`, {
20
- method: "GET",
21
- query: { page, limit, search, status, schoolYear, gradeLevel },
22
- });
23
- }
24
-
25
- function updateById(
26
- id: string,
27
- value: Pick<
28
- TCurriculumSubject,
29
- | "curriculum"
30
- | "educationLevel"
31
- | "gradeLevel"
32
- | "subjectCode"
33
- | "subjectName"
34
- | "subjectType"
35
- | "sessionFrequency"
36
- | "sessionDuration"
37
- | "totalMinutesPerWeek"
38
- >
39
- ) {
40
- return $fetch<Record<string, any>>(`/api/${resource}/${id}`, {
41
- method: "PUT",
42
- body: value,
43
- });
44
- }
45
-
46
- function deleteById(id: string) {
47
- return $fetch<Record<string, any>>(`/api/${resource}/${id}`, {
48
- method: "DELETE",
49
- });
50
- }
51
-
52
- return {
53
- add,
54
- getAll,
55
- updateById,
56
- deleteById,
57
- };
58
- }