@7365admin1/layer-common 1.11.37 → 1.11.39

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,17 @@
1
1
  # @iservice365/layer-common
2
2
 
3
+ ## 1.11.39
4
+
5
+ ### Patch Changes
6
+
7
+ - 59c813e: Update Layer-common new version
8
+
9
+ ## 1.11.38
10
+
11
+ ### Patch Changes
12
+
13
+ - 79f3f90: Update Layer-common
14
+
3
15
  ## 1.11.37
4
16
 
5
17
  ### Patch Changes
@@ -11,12 +11,21 @@
11
11
  <v-card-text style="max-height: 100vh; overflow-y: auto" class="pa-5 my-5">
12
12
  <v-form ref="formRef" v-model="validForm" :disabled="disable">
13
13
  <v-row no-gutters class="pt-4">
14
+ <v-col v-if="isCCTV" cols="12">
15
+ <InputLabel class="text-capitalize" title="Camera Name" required />
16
+ <v-text-field
17
+ v-model.trim="camera.name"
18
+ density="comfortable"
19
+ :rules="[requiredRule]"
20
+ placeholder="Enter CCTV camera name"
21
+ />
22
+ </v-col>
14
23
  <v-col cols="12">
15
24
  <InputLabel class="text-capitalize" title="URL" required />
16
25
  <v-text-field
17
26
  v-model.trim="camera.host"
18
27
  density="comfortable"
19
- :rules="[requiredRule, isValidBaseURL]"
28
+ :rules="[requiredRule, hostRule]"
20
29
  placeholder="Enter camera URL"
21
30
  />
22
31
  </v-col>
@@ -32,7 +41,7 @@
32
41
  </v-col>
33
42
 
34
43
  <v-col v-if="isANPR" cols="12">
35
- <InputLabel class="text-capitalize" title="Direction" required />
44
+ <InputLabel class="text-capitalize" title="Type" required />
36
45
  <v-select
37
46
  v-model="camera.direction"
38
47
  :items="anprDirectionOptions"
@@ -50,7 +59,7 @@
50
59
  />
51
60
  </v-col>
52
61
 
53
- <v-col cols="12">
62
+ <v-col v-if="isANPR" cols="12">
54
63
  <InputLabel class="text-capitalize" title="User" required />
55
64
  <v-text-field
56
65
  v-model.trim="camera.username"
@@ -60,7 +69,7 @@
60
69
  />
61
70
  </v-col>
62
71
 
63
- <v-col cols="12">
72
+ <v-col v-if="isANPR" cols="12">
64
73
  <InputLabel class="text-capitalize" title="Password" required />
65
74
  <v-text-field
66
75
  v-model.trim="camera.password"
@@ -70,6 +79,20 @@
70
79
  placeholder="Enter password"
71
80
  />
72
81
  </v-col>
82
+
83
+ <v-col v-if="isANPR" cols="12">
84
+ <InputLabel class="text-capitalize" title="Status" />
85
+ <v-switch
86
+ v-model="camera.status"
87
+ hide-details
88
+ inset
89
+ density="comfortable"
90
+ true-value="active"
91
+ false-value="inactive"
92
+ :color="camera.status === 'active' ? 'success' : 'grey'"
93
+ :label="camera.status === 'active' ? 'Active' : 'Inactive'"
94
+ ></v-switch>
95
+ </v-col>
73
96
  </v-row>
74
97
  </v-form>
75
98
  </v-card-text>
@@ -107,7 +130,7 @@
107
130
  </template>
108
131
 
109
132
  <script setup lang="ts">
110
- import useSiteSettings from '../composables/useSiteSettings';
133
+ import useSiteSettings from "../composables/useSiteSettings";
111
134
 
112
135
  const prop = defineProps({
113
136
  title: {
@@ -139,9 +162,10 @@ const prop = defineProps({
139
162
  password: "",
140
163
  type: "ip",
141
164
  category: "standard",
142
- direction: "none",
165
+ direction: "both",
143
166
  guardPost: null,
144
167
  status: "active",
168
+ name: "",
145
169
  }),
146
170
  },
147
171
  });
@@ -149,6 +173,23 @@ const prop = defineProps({
149
173
  const { requiredRule, isValidBaseURL } = useUtils();
150
174
  const emit = defineEmits(["cancel", "select", "success", "error"]);
151
175
 
176
+ const hostRule = computed(() => {
177
+ return (v: string | any) => {
178
+ if (!v) return true;
179
+
180
+ const isAnpr = prop.type === 'anpr';
181
+
182
+ const anprRegex = /^http:\/\/[a-z0-9.-]+\.[a-z]{2,}(:\d+)?$/i;
183
+ const defaultRegex = /^https:\/\/[a-z0-9.-]+\.[a-z]{2,}\/[a-z0-9._-]+$/i;
184
+
185
+ if (isAnpr) {
186
+ return anprRegex.test(v) || 'Format: http://domain:port';
187
+ }
188
+
189
+ return defaultRegex.test(v) || 'Format: https://domain/path';
190
+ };
191
+ });
192
+
152
193
  const camera = ref<TSiteCamera>({
153
194
  site: "",
154
195
  host: "",
@@ -156,7 +197,8 @@ const camera = ref<TSiteCamera>({
156
197
  password: "",
157
198
  type: "ip",
158
199
  category: "standard",
159
- direction: "none",
200
+ direction: "both",
201
+ name: "",
160
202
  guardPost: null,
161
203
  status: "active",
162
204
  });
@@ -166,11 +208,11 @@ camera.value.site = prop.site;
166
208
  if (prop.mode === "edit") {
167
209
  camera.value = JSON.parse(JSON.stringify(prop.camera));
168
210
  }
169
-
211
+ console.log("prop.camera", prop?.camera);
170
212
  camera.value.site = prop.site;
171
213
  camera.value.type = prop.type;
172
- camera.value.category = prop.type === "anpr" ? "resident" : "standard";
173
- camera.value.direction = prop.type === "anpr" ? "both" : "none";
214
+ camera.value.category = prop.camera?.category && prop.title == "Edit Camera" ? prop.camera?.category : prop.type == "anpr" ? "resident" : "standard";
215
+ camera.value.direction = prop.camera?.direction && prop.title == "Edit Camera" ? prop.camera?.direction : prop.type == "anpr" ? "both" : "none";
174
216
 
175
217
  const validForm = ref(false);
176
218
  const formRef = ref<HTMLFormElement | null>(null);
@@ -178,6 +220,7 @@ const disable = ref(false);
178
220
  const message = ref("");
179
221
 
180
222
  const isANPR = computed(() => prop.type === "anpr");
223
+ const isCCTV = computed(() => prop.type === "ip");
181
224
 
182
225
  const anprCategoryOptions = computed(() => [
183
226
  { title: "Resident", value: "resident" },
@@ -187,8 +230,7 @@ const anprCategoryOptions = computed(() => [
187
230
  const anprDirectionOptions = computed(() => [
188
231
  { title: "Entry", value: "entry" },
189
232
  { title: "Exit", value: "exit" },
190
- { title: "Both", value: "both" },
191
- { title: "None", value: "none" },
233
+ { title: "Both Entry and Exit", value: "both" },
192
234
  ]);
193
235
 
194
236
  function back() {
@@ -210,7 +252,8 @@ const hasChanges = computed(() => {
210
252
  camera.value.password !== prop.camera.password ||
211
253
  camera.value.category !== prop.camera.category ||
212
254
  camera.value.guardPost !== prop.camera.guardPost ||
213
- camera.value.direction !== prop.camera.direction
255
+ camera.value.direction !== prop.camera.direction ||
256
+ camera.value.name !== prop.camera.name
214
257
  );
215
258
  }
216
259
 
@@ -237,6 +280,8 @@ async function submit() {
237
280
  category: camera.value.category,
238
281
  guardPost: camera.value.guardPost,
239
282
  direction: camera.value.direction,
283
+ status: camera.value.status,
284
+ name: camera.value.name,
240
285
  });
241
286
  }
242
287
 
@@ -24,7 +24,7 @@
24
24
 
25
25
  <v-card-text class="pa-0 bg-red">
26
26
  <v-data-table
27
- :headers="prop.headers"
27
+ :headers="computedHeaders"
28
28
  :items="items"
29
29
  fixed-header
30
30
  hide-default-footer
@@ -92,6 +92,12 @@
92
92
  class="pa-5 my-5 px-7"
93
93
  >
94
94
  <v-row no-gutters>
95
+ <v-col v-if="camera.type === 'ip'" cols="12" class="mb-2">
96
+ Camera Name:
97
+ <span class="font-weight-bold">
98
+ {{ camera.name }}
99
+ </span>
100
+ </v-col>
95
101
  <v-col cols="12" class="mb-2">
96
102
  Host:
97
103
  <span class="font-weight-bold">
@@ -99,14 +105,14 @@
99
105
  </span>
100
106
  </v-col>
101
107
 
102
- <v-col cols="12" class="mb-2">
108
+ <v-col v-if="camera.type === 'anpr'" cols="12" class="mb-2">
103
109
  Username:
104
110
  <span class="font-weight-bold">
105
111
  {{ camera.username }}
106
112
  </span>
107
113
  </v-col>
108
114
 
109
- <v-col cols="12" class="mb-2">
115
+ <v-col v-if="camera.type === 'anpr'" cols="12" class="mb-2">
110
116
  Password:
111
117
  <span class="font-weight-bold">
112
118
  {{ camera.password }}
@@ -275,6 +281,15 @@ const prop = defineProps({
275
281
  },
276
282
  });
277
283
 
284
+ const computedHeaders = computed(() => {
285
+ if (prop.type === "ip") {
286
+ const base = [...prop.headers];
287
+ base.splice(0, 0, { text: "Name", value: "name" });
288
+ return base;
289
+ }
290
+ return prop.headers;
291
+ });
292
+
278
293
  const items = ref<Array<TCamera>>([]);
279
294
  const page = ref(1);
280
295
  const pages = ref(0);
@@ -341,6 +356,7 @@ const camera = ref<TSiteCamera>({
341
356
  });
342
357
 
343
358
  function handleRowClick(_: any, data: any) {
359
+ console.log("row clicked", data.item);
344
360
  dialogPreview.value = true;
345
361
  camera.value = JSON.parse(JSON.stringify(data.item));
346
362
  }
@@ -1,14 +1,15 @@
1
1
  <template>
2
2
  <v-row no-gutters>
3
3
  <v-col cols="12">
4
- <TableMain
4
+ <TableMain
5
+
5
6
  :headers="currentHeaders"
6
7
  :items="items"
7
8
  :loading="loading"
8
9
  :page="page"
9
10
  :pages="pages"
10
- :pageRange="pageRange"
11
- :items-per-page="-1"
11
+ :page-range="pageRange"
12
+ :items-per-page="limit"
12
13
  :extension-height="120"
13
14
  :offset="300"
14
15
  show-header
@@ -25,30 +26,16 @@
25
26
  </v-tabs>
26
27
 
27
28
  <div class="px-3 py-2 w-100">
28
- <v-text-field
29
- v-model="search"
30
- density="compact"
31
- placeholder="Search"
32
- clearable
33
- max-width="300"
34
- append-inner-icon="mdi-magnify"
35
- hide-details
36
- @update:model-value="handleSearch"
37
- />
29
+ <v-text-field v-model="search" density="compact" placeholder="Search" clearable max-width="300"
30
+ append-inner-icon="mdi-magnify" hide-details @update:model-value="handleSearch" />
38
31
  </div>
39
32
  </v-row>
40
33
  </template>
41
34
 
42
35
  <!-- ACTIONS -->
43
36
  <template #actions>
44
- <v-btn
45
- v-if="tab !== 'suspended'"
46
- class="text-none"
47
- rounded="pill"
48
- variant="tonal"
49
- size="large"
50
- @click="openInviteDialog"
51
- >
37
+ <v-btn v-if="tab !== 'suspended'" class="text-none" rounded="pill" variant="tonal" size="large"
38
+ @click="openInviteDialog">
52
39
  Invite Client
53
40
  </v-btn>
54
41
  </template>
@@ -60,26 +47,16 @@
60
47
 
61
48
  <!-- STATUS CELL -->
62
49
  <template #item.status="{ value }">
63
- <v-chip
64
- size="small"
65
- :color="value === 'suspended' ? 'error' : 'success'"
66
- variant="flat"
67
- >
50
+ <v-chip size="small" :color="value === 'suspended' ? 'error' : 'success'" variant="flat">
68
51
  {{ value }}
69
52
  </v-chip>
70
53
  </template>
71
54
 
72
55
  <!-- ACTION CELL (pending only) -->
73
56
  <template #item.action="{ item }">
74
- <v-btn
75
- v-if="tab === 'pending'"
76
- size="small"
77
- color="error"
78
- variant="tonal"
79
- :loading="cancelLoadingId === item._id"
80
- :disabled="cancelLoadingId === item._id"
81
- @click="cancelInvite(item)"
82
- >
57
+ <v-btn v-if="tab === 'pending'" size="small" color="error" variant="tonal"
58
+ :loading="cancelLoadingId === item._id" :disabled="cancelLoadingId === item._id"
59
+ @click="cancelInvite(item)">
83
60
  Cancel Invite
84
61
  </v-btn>
85
62
  </template>
@@ -88,11 +65,7 @@
88
65
 
89
66
  <!-- DIALOG -->
90
67
  <v-dialog v-model="dialog" max-width="500">
91
- <InvitationClientForm
92
- title="Invite Client"
93
- @success="handleSuccess"
94
- @cancel="dialog = false"
95
- />
68
+ <InvitationClientForm title="Invite Client" @success="handleSuccess" @cancel="dialog = false" />
96
69
  </v-dialog>
97
70
  </v-row>
98
71
  </template>
@@ -125,6 +98,17 @@ const search = ref('')
125
98
  const totalItems = ref(0)
126
99
  const cancelLoadingId = ref<string | null>(null)
127
100
 
101
+
102
+ const APP_LIST = [
103
+ { title: "Organization", value: "organization" },
104
+ { title: "Security Agency", value: "security_agency" },
105
+ { title: "Cleaning Services", value: "cleaning_services" },
106
+ { title: "Property Management Agency", value: "property_management_agency" },
107
+ { title: "Mechanical & Electrical Services", value: "mechanical_electrical_services" },
108
+ { title: "Pest Control Services", value: "pest_control_services" },
109
+ { title: "Landscaping Services", value: "landscaping_services" },
110
+ { title: "Pool Maintenance Services", value: "pool_maintenance_services" },
111
+ ]
128
112
  /* ================= HEADERS ================= */
129
113
  const orgHeaders = [
130
114
  { title: 'Organization Name', key: 'name' },
@@ -172,10 +156,15 @@ async function resolveRoleName(id: string) {
172
156
  roleCache.value[id] = roleName
173
157
  return roleName
174
158
  }
175
-
159
+ const limit = ref(10)
176
160
  /* ================= FETCH ================= */
177
161
  async function fetchActive() {
178
- const res = await getAll({ page: page.value, search: search.value })
162
+ const res = await getAll({
163
+ page: page.value,
164
+ search: search.value,
165
+ limit: limit.value,
166
+ })
167
+
179
168
  const orgs = res?.data?.items || res?.items || []
180
169
 
181
170
  const mapped = await Promise.all(
@@ -188,6 +177,7 @@ async function fetchActive() {
188
177
 
189
178
  try {
190
179
  const siteRes = await getCustomerSitesByOrgId(org._id)
180
+
191
181
  sitesCount =
192
182
  siteRes?.data?.totalItems ||
193
183
  siteRes?.totalItems ||
@@ -197,6 +187,7 @@ async function fetchActive() {
197
187
 
198
188
  const subRes = await getSubscriptionByOrgId(org._id)
199
189
  const subscription = subRes?.data || subRes
190
+
200
191
  if (subscription) {
201
192
  planType = subscription?.paidType || '-'
202
193
  billingCycle = subscription?.billingCycle || '-'
@@ -204,25 +195,33 @@ async function fetchActive() {
204
195
  subscriptionEnd = formatDate(subscription?.nextBillingDate)
205
196
  }
206
197
  } catch (e) {
207
- console.error('Error mapping org:', org._id, e)
198
+ console.error(e)
208
199
  }
209
200
 
210
201
  return {
211
- _id: org._id,
202
+ _id: `${org._id}-${page.value}`,
212
203
  ...org,
213
204
  sites: `${sitesCount} Sites`,
214
205
  planType,
215
206
  billingCycle,
216
207
  subscriptionStart,
217
208
  subscriptionEnd,
218
- status: org?.status || 'Active',
209
+ status: org?.status || 'active',
219
210
  }
220
211
  })
221
212
  )
222
213
 
223
- items.value = mapped
224
- pages.value = res?.data?.totalPages || res?.totalPages || 1
225
- totalItems.value = res?.data?.totalItems || res?.totalItems || mapped.length
214
+ items.value = []
215
+
216
+ await nextTick()
217
+
218
+ items.value = [...mapped]
219
+
220
+ pages.value = res?.pages || 1
221
+
222
+ const match = res?.pageRange?.match(/of\s+(\d+)/i)
223
+
224
+ totalItems.value = match ? Number(match[1]) : mapped.length
226
225
  }
227
226
 
228
227
  async function fetchSuspended() {
@@ -275,9 +274,13 @@ async function fetchSuspended() {
275
274
  })
276
275
  )
277
276
 
278
- items.value = mapped
279
- pages.value = res?.data?.totalPages || res?.totalPages || 1
280
- totalItems.value = res?.data?.totalItems || res?.totalItems || mapped.length
277
+ items.value = [...mapped]
278
+
279
+ pages.value = res?.pages || 1
280
+
281
+ const match = res?.pageRange?.match(/of\s+(\d+)/i)
282
+
283
+ totalItems.value = match ? Number(match[1]) : mapped.length
281
284
  }
282
285
 
283
286
  async function fetchPending() {
@@ -286,57 +289,75 @@ async function fetchPending() {
286
289
  type: 'user-invite',
287
290
  page: page.value,
288
291
  search: search.value,
289
- app: 'organization',
290
292
  })
291
293
 
292
- items.value = await Promise.all(
294
+ items.value = [
295
+ ...(await Promise.all(
293
296
  (res?.items || []).map(async (i: any) => ({
294
297
  ...i,
295
- app: i.metadata?.app ?? '-',
298
+ app:
299
+ APP_LIST.find(a => a.value === i.metadata?.app)?.title ||
300
+ i.metadata?.app ||
301
+ '-',
302
+
296
303
  role: await resolveRoleName(i.metadata?.role),
297
304
  }))
298
- )
305
+ ))
306
+ ]
299
307
 
300
308
  pages.value = res?.pages || 1
301
- totalItems.value = res?.total || items.value.length
309
+
310
+ const match = res?.pageRange?.match(/of\s+(\d+)/i)
311
+
312
+ totalItems.value = match
313
+ ? Number(match[1])
314
+ : items.value.length
302
315
  }
303
316
 
304
317
  async function fetchData() {
305
318
  loading.value = true
319
+
306
320
  try {
307
- if (tab.value === 'suspended') {
321
+ if (tab.value === 'active') {
322
+ await fetchActive()
323
+ }
324
+ else if (tab.value === 'suspended') {
308
325
  items.value = []
309
326
  pages.value = 1
310
327
  totalItems.value = 0
311
- return
312
328
  }
313
- if (tab.value === 'active') await fetchActive()
314
- else await fetchPending()
329
+ else {
330
+ await fetchPending()
331
+ }
315
332
  } finally {
316
333
  loading.value = false
317
334
  }
318
335
  }
319
336
 
320
337
  /* ================= EVENTS ================= */
321
- function onTabChange() {
322
- page.value = 1
323
- fetchData()
324
- }
325
-
326
- function handleUpdatePage(p: number) {
338
+ async function handleUpdatePage(p: number) {
327
339
  page.value = p
328
- fetchData()
340
+ await fetchData()
341
+ }
342
+ async function onTabChange() {
343
+ page.value = 1
344
+ await fetchData()
329
345
  }
330
346
 
331
347
  function handleRefresh() {
332
348
  fetchData()
333
349
  }
334
350
 
351
+ let searchTimeout: any = null
352
+
335
353
  function handleSearch() {
336
- page.value = 1
337
- fetchData()
338
- }
354
+ clearTimeout(searchTimeout)
339
355
 
356
+ searchTimeout = setTimeout(async () => {
357
+ page.value = 1
358
+ await fetchData()
359
+ }, 500)
360
+ }
340
361
  /* ================= DIALOG ================= */
341
362
  function openInviteDialog() {
342
363
  dialog.value = true
@@ -119,17 +119,18 @@
119
119
  import { computed, ref, reactive, watchEffect } from 'vue'
120
120
  import useCustomerSite from '../composables/useCustomerSite'
121
121
  import useLocal from '../composables/useLocal'
122
- import { useLocalSetup } from '../composables/useLocalSetup'
123
122
  import useRole from '../composables/useRole'
124
123
  import useUser from '../composables/useUser'
125
124
  import useUtils from '../composables/useUtils'
125
+ import useOrg from '../composables/useOrg'
126
+ import { watch } from 'vue'
126
127
 
127
128
  const APP = useRuntimeConfig().public.APP
128
129
 
129
130
  /* ================= PROPS ================= */
130
131
  const props = defineProps({
131
132
  title: { type: String, default: "Invite Form" },
132
- app: { type: String, default: "organization" },
133
+ app: { type: String, default: "" },
133
134
  org: { type: String, default: "" },
134
135
  mode: { type: String, default: "create" },
135
136
  })
@@ -162,17 +163,23 @@ if (props.mode === "create") {
162
163
 
163
164
  /* ================= APP LIST ================= */
164
165
  const APP_LIST = [
165
- { title: "Organization", value: "organization" },
166
+ { title: "Property Management Agency", value: "property_management_agency" },
166
167
  { title: "Security Agency", value: "security_agency" },
167
168
  { title: "Cleaning Services", value: "cleaning_services" },
168
- { title: "Property Management Agency", value: "property_management_agency" },
169
169
  { title: "Mechanical & Electrical Services", value: "mechanical_electrical_services" },
170
170
  { title: "Pest Control Services", value: "pest_control_services" },
171
- { title: "Landscaping Services", value: "landscaping_services" },
172
171
  { title: "Pool Maintenance Services", value: "pool_maintenance_services" },
173
172
  ]
174
-
175
- const { orgNature } = useLocalSetup()
173
+ const { getByName } = useOrg()
174
+ const org = ref<any>(null)
175
+ watch(
176
+ () => props.org,
177
+ async (name) => {
178
+ if (!name) return
179
+ org.value = await getByName(name)
180
+ },
181
+ { immediate: true }
182
+ )
176
183
 
177
184
  const apps = computed(() => APP_LIST)
178
185
 
@@ -188,7 +195,7 @@ const { getAll: getAllCustomerSite } = useCustomerSite()
188
195
 
189
196
  const { data: siteData, refresh: refreshSiteData } = await useLazyAsyncData(
190
197
  "sites",
191
- () => getAllCustomerSite({ org: props.org, limit: 50 })
198
+ () => getAllCustomerSite({ org: org.value?._id, limit: 50 })
192
199
  )
193
200
 
194
201
  watchEffect(() => {
@@ -200,9 +207,13 @@ watchEffect(() => {
200
207
  }
201
208
  })
202
209
 
203
- watchEffect(() => {
204
- if (hasSite.value) refreshSiteData()
205
- })
210
+ watch(
211
+ () => org.value?._id,
212
+ async (id) => {
213
+ if (!id) return
214
+ await refreshSiteData()
215
+ }
216
+ )
206
217
 
207
218
  /* ================= ROLE ================= */
208
219
  const roles = ref<any[]>([])
@@ -211,18 +222,24 @@ const { getRoles } = useRole()
211
222
  const { data: roleData, refresh: refreshRoles } = await useLazyAsyncData(
212
223
  "roles",
213
224
  () =>
214
- getRoles({
215
- org: props.org,
216
- type: props.app,
217
- limit: 50,
218
- }),
225
+ getRoles({
226
+ org: org.value?._id,
227
+ type: props.app,
228
+ limit: 50,
229
+ }),
219
230
  { watch: [() => props.app] }
220
231
  )
221
232
 
222
233
  watchEffect(() => {
223
234
  if (roleData.value) roles.value = roleData.value.items
224
235
  })
225
-
236
+ watch(
237
+ () => org.value?._id,
238
+ async (id) => {
239
+ if (!id) return
240
+ await refreshRoles()
241
+ }
242
+ )
226
243
  /* ================= EVENTS ================= */
227
244
  async function handleUpdateApp(value: string[]) {
228
245
  invite.value.role = ""
@@ -255,7 +272,8 @@ async function submit() {
255
272
  email: invite.value.email,
256
273
  app,
257
274
  role: invite.value.role,
258
- org: invite.value.org,
275
+ // org: invite.value.org,
276
+ org: org.value?._id,
259
277
  site: invite.value.site,
260
278
  siteName: invite.value.siteName,
261
279
  // isMemberInvite: invite.value.isMemberInvite,
@@ -269,7 +287,7 @@ async function submit() {
269
287
  email: "",
270
288
  app: [],
271
289
  role: "",
272
- org: props.org,
290
+ org: org.value?._id || "",
273
291
  site: "",
274
292
  siteName: "",
275
293
  isMemberInvite: false,