@eeplatform/nuxt-layer-common 1.2.9 → 1.2.10

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,11 @@
1
1
  # @eeplatform/nuxt-layer-common
2
2
 
3
+ ## 1.2.10
4
+
5
+ ### Patch Changes
6
+
7
+ - c16019c: School Mgmt - Admin only, implement add and bulk add
8
+
3
9
  ## 1.2.9
4
10
 
5
11
  ### Patch Changes
@@ -323,14 +323,16 @@ const {
323
323
  data: getAllReq,
324
324
  refresh: getAll,
325
325
  status: getAllReqStatus,
326
- } = useLazyAsyncData("get-all-members-by-status" + props.status, () =>
327
- _getAll({
328
- status: props.status,
329
- org: props.orgId,
330
- search: headerSearch.value,
331
- page: page.value,
332
- type: props.type,
333
- })
326
+ } = useLazyAsyncData(
327
+ "get-all-members-by-status" + props.status + "-" + props.orgId,
328
+ () =>
329
+ _getAll({
330
+ status: props.status,
331
+ org: props.orgId,
332
+ search: headerSearch.value,
333
+ page: page.value,
334
+ type: props.type,
335
+ })
334
336
  );
335
337
 
336
338
  const loading = computed(() => getAllReqStatus.value === "pending");
@@ -217,7 +217,7 @@ const {
217
217
  refresh: getRoles,
218
218
  status: getRoleReqStatus,
219
219
  } = useLazyAsyncData(
220
- "roles-permissions-get-all",
220
+ "roles-permissions-get-all" + "-" + props.id,
221
221
  () =>
222
222
  _getRoles({
223
223
  page: page.value,
@@ -2,9 +2,7 @@
2
2
  <v-card width="100%">
3
3
  <v-toolbar>
4
4
  <v-row no-gutters class="fill-height px-6" align="center">
5
- <span class="font-weight-bold text-h5">
6
- Create School
7
- </span>
5
+ <span class="font-weight-bold text-h5"> Create School </span>
8
6
  </v-row>
9
7
  </v-toolbar>
10
8
  <v-card-text style="max-height: 100vh; overflow-y: auto">
@@ -12,7 +10,11 @@
12
10
  <v-row no-gutters>
13
11
  <v-col cols="12" class="mt-2">
14
12
  <v-row no-gutters>
15
- <InputLabel class="text-capitalize" title="School Name" required />
13
+ <InputLabel
14
+ class="text-capitalize"
15
+ title="School Name"
16
+ required
17
+ />
16
18
  <v-col cols="12">
17
19
  <v-text-field
18
20
  v-model="name"
@@ -145,7 +147,7 @@ const { requiredRule } = useUtils();
145
147
 
146
148
  const message = ref("");
147
149
 
148
- const { createSchool } = useSchool();
150
+ const { addSchool } = useSchool();
149
151
  const { getAll: getDivisions } = useDivision();
150
152
 
151
153
  // Load divisions for selection
@@ -158,7 +160,7 @@ onMounted(async () => {
158
160
  const response = await getDivisions({ page: 1, limit: 100 });
159
161
  divisionOptions.value = response.items || [];
160
162
  } catch (error) {
161
- console.error('Failed to load divisions:', error);
163
+ console.error("Failed to load divisions:", error);
162
164
  } finally {
163
165
  divisionsLoading.value = false;
164
166
  }
@@ -167,7 +169,7 @@ onMounted(async () => {
167
169
  async function submit() {
168
170
  disable.value = true;
169
171
  try {
170
- const payload: Record<string, any> = {
172
+ const payload: TSchool = {
171
173
  name: name.value,
172
174
  };
173
175
 
@@ -184,7 +186,7 @@ async function submit() {
184
186
  payload.address = address.value.trim();
185
187
  }
186
188
 
187
- await createSchool(payload);
189
+ await addSchool(payload);
188
190
 
189
191
  if (createMore.value) {
190
192
  name.value = "";
@@ -0,0 +1,403 @@
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"> Bulk Upload Schools </span>
6
+ </v-row>
7
+ </v-toolbar>
8
+ <v-card-text style="max-height: 100vh; overflow-y: auto">
9
+ <v-form v-model="validForm" :disabled="disable">
10
+ <v-row no-gutters>
11
+ <v-col cols="12" class="mt-2">
12
+ <v-row no-gutters>
13
+ <InputLabel class="text-capitalize" title="Region" required />
14
+ <v-col cols="12">
15
+ <v-select
16
+ v-model="selectedRegion"
17
+ :items="regionOptions"
18
+ item-title="name"
19
+ item-value="_id"
20
+ density="comfortable"
21
+ :rules="[requiredRule]"
22
+ placeholder="Select a region"
23
+ :loading="regionsLoading"
24
+ return-object
25
+ ></v-select>
26
+ </v-col>
27
+ </v-row>
28
+ </v-col>
29
+
30
+ <v-col cols="12" class="mt-2">
31
+ <v-row no-gutters>
32
+ <InputLabel class="text-capitalize" title="Division" required />
33
+ <v-col cols="12">
34
+ <v-select
35
+ v-model="selectedDivision"
36
+ :items="divisionOptions"
37
+ item-title="name"
38
+ item-value="_id"
39
+ density="comfortable"
40
+ :rules="[requiredRule]"
41
+ placeholder="Select a division"
42
+ :loading="divisionsLoading"
43
+ return-object
44
+ ></v-select>
45
+ </v-col>
46
+ </v-row>
47
+ </v-col>
48
+
49
+ <v-col cols="12" class="mt-4">
50
+ <v-row no-gutters>
51
+ <v-col cols="12">
52
+ <v-btn
53
+ variant="outlined"
54
+ color="primary"
55
+ class="text-none"
56
+ size="large"
57
+ block
58
+ prepend-icon="mdi-download"
59
+ @click="downloadTemplate"
60
+ :disabled="disable"
61
+ >
62
+ Download Template
63
+ </v-btn>
64
+ </v-col>
65
+ </v-row>
66
+ </v-col>
67
+
68
+ <v-col cols="12" class="mt-2">
69
+ <v-divider></v-divider>
70
+ </v-col>
71
+
72
+ <v-file-input
73
+ ref="fileInputRef"
74
+ v-model="selectedFile"
75
+ v-show="false"
76
+ accept=".csv,.xlsx,.xls"
77
+ @change="handleFileSelect"
78
+ ></v-file-input>
79
+
80
+ <v-col cols="12">
81
+ <v-btn
82
+ block
83
+ variant="flat"
84
+ color="black"
85
+ class="text-none"
86
+ size="large"
87
+ @click="triggerFileInput"
88
+ :disabled="disable"
89
+ >
90
+ {{ selectedFile ? "Change File" : "Select Excel/CSV File" }}
91
+ </v-btn>
92
+ </v-col>
93
+
94
+ <v-col v-if="selectedFile" cols="12" class="mt-2">
95
+ <v-card variant="outlined">
96
+ <v-card-text class="py-2">
97
+ <v-row no-gutters align="center">
98
+ <v-col>
99
+ <div class="d-flex align-center">
100
+ <v-icon class="me-2" color="success"
101
+ >mdi-file-check</v-icon
102
+ >
103
+ <div>
104
+ <div class="text-subtitle-2 font-weight-medium">
105
+ {{ selectedFile.name }}
106
+ </div>
107
+ <div class="text-caption text-medium-emphasis">
108
+ {{ formatFileSize(selectedFile.size) }}
109
+ </div>
110
+ </div>
111
+ </div>
112
+ </v-col>
113
+ <v-col cols="auto">
114
+ <v-btn
115
+ icon="mdi-close"
116
+ variant="text"
117
+ size="small"
118
+ @click="clearFile"
119
+ :disabled="disable"
120
+ ></v-btn>
121
+ </v-col>
122
+ </v-row>
123
+ </v-card-text>
124
+ </v-card>
125
+ </v-col>
126
+
127
+ <v-col v-if="!selectedFile" cols="12" class="mt-2">
128
+ <v-alert type="info" variant="tonal" class="text-caption">
129
+ <strong>File Requirements:</strong><br />
130
+ • Supported formats: CSV, Excel (.xlsx, .xls)<br />
131
+ • Required columns: schoolName, schoolId, district<br />
132
+ • Maximum file size: 16MB<br />
133
+ • Download the template above for the correct format
134
+ </v-alert>
135
+ </v-col>
136
+
137
+ <v-col cols="12" class="my-2">
138
+ <v-row no-gutters>
139
+ <v-col cols="12" class="text-center">
140
+ <span
141
+ class="text-none text-subtitle-2 font-weight-medium text-error"
142
+ >
143
+ {{ message }}
144
+ </span>
145
+ </v-col>
146
+ </v-row>
147
+ </v-col>
148
+ </v-row>
149
+ </v-form>
150
+ </v-card-text>
151
+
152
+ <v-toolbar>
153
+ <v-row class="px-6">
154
+ <v-col cols="6">
155
+ <v-btn
156
+ block
157
+ variant="text"
158
+ class="text-none"
159
+ size="large"
160
+ @click="cancel"
161
+ :disabled="disable"
162
+ >
163
+ Cancel
164
+ </v-btn>
165
+ </v-col>
166
+
167
+ <v-col cols="6">
168
+ <v-btn
169
+ block
170
+ variant="flat"
171
+ color="black"
172
+ class="text-none"
173
+ size="large"
174
+ :disabled="!isFormValid || disable"
175
+ @click="submit"
176
+ :loading="disable"
177
+ >
178
+ Upload Schools
179
+ </v-btn>
180
+ </v-col>
181
+ </v-row>
182
+ </v-toolbar>
183
+ </v-card>
184
+ </template>
185
+
186
+ <script setup lang="ts">
187
+ const emit = defineEmits(["cancel", "success", "success:create-more"]);
188
+
189
+ const validForm = ref(false);
190
+
191
+ const selectedRegion = ref<Record<string, any> | null>(null);
192
+ const selectedDivision = ref<Record<string, any> | null>(null);
193
+ const disable = ref(false);
194
+
195
+ // File upload variables
196
+ const selectedFile = ref<File | null>(null);
197
+ const fileInputRef = ref<HTMLInputElement | null>(null);
198
+
199
+ const { requiredRule } = useUtils();
200
+
201
+ const message = ref("");
202
+
203
+ const { bulkAdd } = useSchool();
204
+
205
+ const { getAll: getAllRegions } = useRegion();
206
+
207
+ const regionOptions = ref<Array<Record<string, any>>>([]);
208
+
209
+ const { data: getAllRegionReq, status: getRegionStatus } =
210
+ await useLazyAsyncData("get-all-regions", () =>
211
+ getAllRegions({
212
+ page: 1,
213
+ limit: 100,
214
+ })
215
+ );
216
+
217
+ const regionsLoading = computed(() => getRegionStatus.value === "pending");
218
+
219
+ watchEffect(() => {
220
+ if (getAllRegionReq.value) {
221
+ regionOptions.value = getAllRegionReq.value.items;
222
+ }
223
+ });
224
+
225
+ const { getAll: getDivisions } = useDivision();
226
+
227
+ // Load divisions for selection
228
+ const divisionOptions = ref<Array<Record<string, any>>>([]);
229
+
230
+ const { data: getSDOData, status } = await useLazyAsyncData(
231
+ "get-all-school-division-offices",
232
+ () => getDivisions({ page: 1, limit: 100 })
233
+ );
234
+
235
+ watchEffect(() => {
236
+ if (getSDOData.value) {
237
+ divisionOptions.value = getSDOData.value.items || [];
238
+ }
239
+ });
240
+
241
+ const divisionsLoading = computed(() => status.value === "pending");
242
+
243
+ // Form validation - ensure all required fields are filled
244
+ const isFormValid = computed(() => {
245
+ return selectedRegion.value && selectedDivision.value && selectedFile.value;
246
+ });
247
+
248
+ // File handling methods
249
+ function triggerFileInput() {
250
+ if (fileInputRef.value) {
251
+ fileInputRef.value.click();
252
+ }
253
+ }
254
+
255
+ function handleFileSelect(event: Event) {
256
+ const target = event.target as HTMLInputElement;
257
+ const file = target.files?.[0];
258
+
259
+ if (file) {
260
+ // Validate file type
261
+ const allowedTypes = [
262
+ "text/csv",
263
+ "application/vnd.ms-excel",
264
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
265
+ ];
266
+
267
+ const allowedExtensions = [".csv", ".xls", ".xlsx"];
268
+ const fileExtension = "." + file.name.split(".").pop()?.toLowerCase();
269
+
270
+ if (
271
+ !allowedTypes.includes(file.type) &&
272
+ !allowedExtensions.includes(fileExtension)
273
+ ) {
274
+ message.value = "Please select a valid CSV or Excel file";
275
+ selectedFile.value = null;
276
+ return;
277
+ }
278
+
279
+ // Validate file size (16MB limit)
280
+ const maxSize = 16 * 1024 * 1024; // 16MB in bytes
281
+ if (file.size > maxSize) {
282
+ message.value = "File size must be less than 16MB";
283
+ selectedFile.value = null;
284
+ return;
285
+ }
286
+
287
+ selectedFile.value = file;
288
+ message.value = "";
289
+ }
290
+ }
291
+
292
+ function clearFile() {
293
+ selectedFile.value = null;
294
+ if (fileInputRef.value) {
295
+ fileInputRef.value.value = "";
296
+ }
297
+ }
298
+
299
+ function formatFileSize(bytes: number): string {
300
+ if (bytes === 0) return "0 Bytes";
301
+
302
+ const k = 1024;
303
+ const sizes = ["Bytes", "KB", "MB", "GB"];
304
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
305
+
306
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
307
+ }
308
+
309
+ function downloadTemplate() {
310
+ // Create CSV template with the expected format
311
+ const headers = ["schoolName", "schoolId", "district"];
312
+ const sampleData = ["Sample Elementary School", "ELEM001", "District 1"];
313
+
314
+ const csvContent = [
315
+ headers.join(","),
316
+ sampleData.map((field) => `"${field}"`).join(","),
317
+ ].join("\n");
318
+
319
+ // Create and download file
320
+ const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
321
+ const link = document.createElement("a");
322
+ const url = URL.createObjectURL(blob);
323
+
324
+ link.setAttribute("href", url);
325
+ link.setAttribute("download", "school-bulk-upload-template.csv");
326
+ link.style.visibility = "hidden";
327
+
328
+ document.body.appendChild(link);
329
+ link.click();
330
+ document.body.removeChild(link);
331
+ }
332
+
333
+ async function submit() {
334
+ disable.value = true;
335
+ try {
336
+ // Validate required fields
337
+ if (
338
+ !selectedRegion.value ||
339
+ !selectedDivision.value ||
340
+ !selectedFile.value
341
+ ) {
342
+ message.value = "Please fill in all required fields and select a file";
343
+ disable.value = false;
344
+ return;
345
+ }
346
+
347
+ // Call the bulk upload API
348
+ const result = await bulkAdd(
349
+ selectedFile.value,
350
+ selectedRegion.value._id,
351
+ selectedDivision.value._id
352
+ );
353
+
354
+ // Display success message with details
355
+ const details = result.details;
356
+ let successMessage = result.message;
357
+
358
+ if (details.failed > 0) {
359
+ successMessage += ` ${details.failed} schools failed to upload.`;
360
+ if (details.errors.length > 0) {
361
+ console.warn("Upload errors:", details.errors);
362
+ message.value = `${successMessage} Check console for error details.`;
363
+ }
364
+ }
365
+
366
+ // Reset form on success
367
+ selectedRegion.value = null;
368
+ selectedDivision.value = null;
369
+ selectedFile.value = null;
370
+ if (fileInputRef.value) {
371
+ fileInputRef.value.value = "";
372
+ }
373
+
374
+ // Show success and emit event
375
+ if (details.failed === 0) {
376
+ message.value = "";
377
+ emit("success");
378
+ } else {
379
+ // Partial success - show warning but still emit success
380
+ emit("success");
381
+ }
382
+ } catch (error: any) {
383
+ console.error("Bulk upload error:", error);
384
+ message.value =
385
+ error.message ||
386
+ error.response?._data?.message ||
387
+ "Failed to upload schools";
388
+ } finally {
389
+ disable.value = false;
390
+ }
391
+ }
392
+
393
+ function cancel() {
394
+ selectedRegion.value = null;
395
+ selectedDivision.value = null;
396
+ selectedFile.value = null;
397
+ if (fileInputRef.value) {
398
+ fileInputRef.value.value = "";
399
+ }
400
+ message.value = "";
401
+ emit("cancel");
402
+ }
403
+ </script>
@@ -1,5 +1,31 @@
1
1
  <template>
2
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
+ v-if="canCreate"
12
+ >
13
+ Add School
14
+ </v-btn>
15
+
16
+ <v-btn
17
+ class="text-none"
18
+ rounded="pill"
19
+ variant="tonal"
20
+ @click="dialogUpload = true"
21
+ size="large"
22
+ v-if="canUpload"
23
+ >
24
+ Upload Schools
25
+ </v-btn>
26
+ </v-row>
27
+ </v-col>
28
+
3
29
  <v-col cols="12">
4
30
  <v-card
5
31
  width="100%"
@@ -54,7 +80,11 @@
54
80
  hide-default-footer
55
81
  hide-default-header
56
82
  @click:row="tableRowClickHandler"
57
- style="max-height: calc(100vh - (180px))"
83
+ :style="`max-height: ${
84
+ canCreate || canUpload
85
+ ? 'calc(100vh - (240px))'
86
+ : 'calc(100vh - (180px))'
87
+ } `"
58
88
  >
59
89
  <template #item.createdAt="{ value }">
60
90
  {{ new Date(value).toLocaleDateString() }}
@@ -64,26 +94,35 @@
64
94
  </v-col>
65
95
 
66
96
  <!-- Create Dialog -->
67
- <v-dialog v-model="createDialog" width="500" persistent>
97
+ <v-dialog v-model="dialogCreate" width="500" persistent>
68
98
  <SchoolFormCreate
69
- @cancel="createDialog = false"
99
+ @cancel="dialogCreate = false"
100
+ @success="successCreate()"
101
+ @success:create-more="getSchools()"
102
+ />
103
+ </v-dialog>
104
+
105
+ <!-- Upload Dialog -->
106
+ <v-dialog v-model="dialogUpload" width="500" persistent>
107
+ <SchoolFormUpload
108
+ @cancel="dialogUpload = false"
70
109
  @success="successCreate()"
71
110
  @success:create-more="getSchools()"
72
111
  />
73
112
  </v-dialog>
74
113
 
75
114
  <!-- Edit Dialog -->
76
- <v-dialog v-model="editDialog" width="500" persistent>
115
+ <v-dialog v-model="dialogEdit" width="500" persistent>
77
116
  <SchoolFormEdit
78
117
  v-if="selectedSchool"
79
- @cancel="editDialog = false"
118
+ @cancel="dialogEdit = false"
80
119
  @success="successUpdate()"
81
120
  :school="selectedSchool"
82
121
  />
83
122
  </v-dialog>
84
123
 
85
124
  <!-- Preview Dialog -->
86
- <v-dialog v-model="previewDialog" width="500" persistent>
125
+ <v-dialog v-model="dialogPreview" width="500" persistent>
87
126
  <v-card width="100%">
88
127
  <v-card-text style="max-height: 100vh; overflow-y: auto" class="pb-0">
89
128
  <v-row no-gutters v-if="selectedSchool">
@@ -134,7 +173,7 @@
134
173
  class="text-none"
135
174
  height="48"
136
175
  tile
137
- @click="previewDialog = false"
176
+ @click="dialogPreview = false"
138
177
  >
139
178
  Close
140
179
  </v-btn>
@@ -272,6 +311,10 @@ const prop = defineProps({
272
311
  type: Boolean,
273
312
  default: true,
274
313
  },
314
+ canUpload: {
315
+ type: Boolean,
316
+ default: true,
317
+ },
275
318
  canUpdate: {
276
319
  type: Boolean,
277
320
  default: true,
@@ -322,7 +365,7 @@ const {
322
365
  refresh: getSchools,
323
366
  status: getSchoolReqStatus,
324
367
  } = useLazyAsyncData(
325
- "schools-get-all-" + prop.status,
368
+ "schools-get-all-" + prop.status + "-" + prop.org,
326
369
  () =>
327
370
  _getSchools({
328
371
  page: page.value,
@@ -348,35 +391,36 @@ watchEffect(() => {
348
391
 
349
392
  function tableRowClickHandler(_: any, data: any) {
350
393
  selectedSchool.value = data.item;
351
- previewDialog.value = true;
394
+ dialogPreview.value = true;
352
395
  }
353
396
 
354
- const createDialog = ref(false);
355
- const editDialog = ref(false);
356
- const previewDialog = ref(false);
397
+ const dialogCreate = ref(false);
398
+ const dialogUpload = ref(false);
399
+ const dialogEdit = ref(false);
400
+ const dialogPreview = ref(false);
357
401
  const selectedSchool = ref<Record<string, any> | null>(null);
358
402
 
359
403
  function successCreate() {
360
- createDialog.value = false;
404
+ dialogCreate.value = false;
361
405
  getSchools();
362
406
  showMessage("School created successfully!", "success");
363
407
  }
364
408
 
365
409
  function successUpdate() {
366
- editDialog.value = false;
367
- previewDialog.value = false;
410
+ dialogEdit.value = false;
411
+ dialogPreview.value = false;
368
412
  getSchools();
369
413
  showMessage("School updated successfully!", "success");
370
414
  }
371
415
 
372
416
  function openEditDialog(school: Record<string, any>) {
373
417
  selectedSchool.value = school;
374
- editDialog.value = true;
418
+ dialogEdit.value = true;
375
419
  }
376
420
 
377
421
  function editFromPreview() {
378
- previewDialog.value = false;
379
- editDialog.value = true;
422
+ dialogPreview.value = false;
423
+ dialogEdit.value = true;
380
424
  }
381
425
 
382
426
  const confirmDialog = ref(false);
@@ -386,8 +430,8 @@ const deleteLoading = ref(false);
386
430
  function openDeleteDialog(id: string) {
387
431
  selectedSchoolId.value = id;
388
432
  confirmDialog.value = true;
389
- if (previewDialog.value) {
390
- previewDialog.value = false;
433
+ if (dialogPreview.value) {
434
+ dialogPreview.value = false;
391
435
  }
392
436
  }
393
437
 
@@ -422,7 +466,7 @@ async function submitApproval() {
422
466
  error?.response?._data?.message || "Failed to delete school";
423
467
  showMessage(errorMessage, "error");
424
468
  } finally {
425
- previewDialog.value = false;
469
+ dialogPreview.value = false;
426
470
  selectedSchoolId.value = null;
427
471
  }
428
472
  }
@@ -1,4 +1,11 @@
1
1
  export default function useSchool() {
2
+ function addSchool(school: TSchool) {
3
+ return useNuxtApp().$api<{ message: string }>("/api/schools", {
4
+ method: "POST",
5
+ body: school,
6
+ });
7
+ }
8
+
2
9
  function registerSchool(school: TSchool) {
3
10
  return useNuxtApp().$api("/api/schools/register", {
4
11
  method: "POST",
@@ -37,10 +44,37 @@ export default function useSchool() {
37
44
  });
38
45
  }
39
46
 
47
+ function bulkAdd(file: File | null, region: string, division: string) {
48
+ if (!file) {
49
+ throw new Error("File not found.");
50
+ }
51
+
52
+ const formData = new FormData();
53
+ formData.append("file", file);
54
+ formData.append("region", region);
55
+ formData.append("division", division);
56
+
57
+ return useNuxtApp().$api<{
58
+ message: string;
59
+ details: {
60
+ successful: number;
61
+ failed: number;
62
+ total: number;
63
+ totalSizeMB: number;
64
+ errors: string[];
65
+ };
66
+ }>("/api/schools/bulk", {
67
+ method: "POST",
68
+ body: formData,
69
+ });
70
+ }
71
+
40
72
  return {
73
+ addSchool,
41
74
  registerSchool,
42
75
  getPendingByCreatedBy,
43
76
  getAll,
44
77
  approvedById,
78
+ bulkAdd,
45
79
  };
46
80
  }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@eeplatform/nuxt-layer-common",
3
3
  "license": "MIT",
4
4
  "type": "module",
5
- "version": "1.2.9",
5
+ "version": "1.2.10",
6
6
  "main": "./nuxt.config.ts",
7
7
  "publishConfig": {
8
8
  "access": "public"
package/types/school.d.ts CHANGED
@@ -1,20 +1,20 @@
1
1
  declare type TSchool = {
2
2
  _id?: string;
3
- id: string;
3
+ id?: string;
4
4
  name: string;
5
- country: string;
6
- address: string;
7
- continuedAddress: string;
8
- city: string;
9
- province: string;
10
- postalCode: string;
11
- courses: Array<string>;
12
- principalName: string;
13
- principalEmail: string;
14
- principalNumber: string;
15
- region: string;
5
+ country?: string;
6
+ address?: string;
7
+ continuedAddress?: string;
8
+ city?: string;
9
+ province?: string;
10
+ postalCode?: string;
11
+ courses?: Array<string>;
12
+ principalName?: string;
13
+ principalEmail?: string;
14
+ principalNumber?: string;
15
+ region?: string;
16
16
  regionName?: string;
17
- division: string;
17
+ division?: string;
18
18
  divisionName?: string;
19
19
  status?: string;
20
20
  createdAt?: string;