add business_owner
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="app-shell-root min-h-[100dvh] w-full bg-surface-2">
|
<div class="app-shell-root min-h-[100dvh] w-full bg-surface-2">
|
||||||
<div
|
<div
|
||||||
class="app-shell-frame mx-auto flex w-full min-w-0 max-w-full flex-col bg-surface shadow-xl shadow-black/5 dark:shadow-black/30 max-w-app max-lg:h-[100dvh] max-lg:max-h-[100dvh] max-lg:overflow-hidden lg:min-h-dvh"
|
class="app-shell-frame mx-auto flex h-[100dvh] max-h-[100dvh] w-full min-w-0 max-w-full flex-col overflow-hidden bg-surface shadow-xl shadow-black/5 dark:shadow-black/30 max-w-app"
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+15
-17
@@ -34,25 +34,23 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1023px) {
|
html,
|
||||||
html,
|
body,
|
||||||
body,
|
#app {
|
||||||
#app {
|
height: 100%;
|
||||||
height: 100%;
|
overflow: hidden;
|
||||||
overflow: hidden;
|
}
|
||||||
|
|
||||||
|
@supports (-webkit-touch-callout: none) {
|
||||||
|
.app-shell-root {
|
||||||
|
min-height: 100%;
|
||||||
|
min-height: -webkit-fill-available;
|
||||||
}
|
}
|
||||||
|
|
||||||
@supports (-webkit-touch-callout: none) {
|
.app-shell-frame {
|
||||||
.app-shell-root {
|
height: 100%;
|
||||||
min-height: 100%;
|
max-height: 100%;
|
||||||
min-height: -webkit-fill-available;
|
min-height: -webkit-fill-available;
|
||||||
}
|
|
||||||
|
|
||||||
.app-shell-frame {
|
|
||||||
height: 100%;
|
|
||||||
max-height: 100%;
|
|
||||||
min-height: -webkit-fill-available;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,13 @@
|
|||||||
<AppSelect id="filterActive" v-model="filterActive" :options="activeFilterOptions" />
|
<AppSelect id="filterActive" v-model="filterActive" :options="activeFilterOptions" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<p
|
||||||
|
v-if="infoMessage"
|
||||||
|
class="mt-4 rounded-xl border border-emerald-500/30 bg-emerald-500/10 px-4 py-3 text-sm text-emerald-700 dark:text-emerald-400"
|
||||||
|
>
|
||||||
|
{{ infoMessage }}
|
||||||
|
</p>
|
||||||
|
|
||||||
<p
|
<p
|
||||||
v-if="error"
|
v-if="error"
|
||||||
class="mt-4 rounded-xl border border-red-500/30 bg-red-500/10 px-4 py-3 text-sm text-red-600"
|
class="mt-4 rounded-xl border border-red-500/30 bg-red-500/10 px-4 py-3 text-sm text-red-600"
|
||||||
@@ -249,6 +256,7 @@ const filterCategoryId = ref('');
|
|||||||
const filterActive = ref('all');
|
const filterActive = ref('all');
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
const error = ref('');
|
const error = ref('');
|
||||||
|
const infoMessage = ref('');
|
||||||
const saving = ref(false);
|
const saving = ref(false);
|
||||||
|
|
||||||
const formOpen = ref(false);
|
const formOpen = ref(false);
|
||||||
@@ -322,6 +330,33 @@ function parseCoord(value: string): number | undefined {
|
|||||||
return Number.isFinite(num) ? num : undefined;
|
return Number.isFinite(num) ? num : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function backfillMissingOwners(
|
||||||
|
bizList: Business[],
|
||||||
|
users: User[],
|
||||||
|
): Promise<number> {
|
||||||
|
const usersByMobile = new Map(
|
||||||
|
users.map((user) => [normalizeIranMobile(user.mobile), user]),
|
||||||
|
);
|
||||||
|
|
||||||
|
let filled = 0;
|
||||||
|
for (const biz of bizList) {
|
||||||
|
if (biz.ownerId) continue;
|
||||||
|
const mobile = normalizeIranMobile(biz.contactPhone ?? '');
|
||||||
|
if (!isValidIranMobile(mobile)) continue;
|
||||||
|
|
||||||
|
const existing = usersByMobile.get(mobile);
|
||||||
|
const fullName = existing?.fullName?.trim() || `مدیر ${biz.title}`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await assignBusinessOwner(biz.id, { mobile, fullName });
|
||||||
|
filled += 1;
|
||||||
|
} catch {
|
||||||
|
/* continue with remaining businesses */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filled;
|
||||||
|
}
|
||||||
|
|
||||||
async function load() {
|
async function load() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
error.value = '';
|
error.value = '';
|
||||||
@@ -330,12 +365,21 @@ async function load() {
|
|||||||
if (filterCategoryId.value) params.categoryId = filterCategoryId.value;
|
if (filterCategoryId.value) params.categoryId = filterCategoryId.value;
|
||||||
if (filterActive.value !== 'all') params.isActive = filterActive.value === 'true';
|
if (filterActive.value !== 'all') params.isActive = filterActive.value === 'true';
|
||||||
|
|
||||||
const [bizList, cats, users] = await Promise.all([
|
let [bizList, cats, users] = await Promise.all([
|
||||||
fetchBusinesses(params),
|
fetchBusinesses(params),
|
||||||
fetchCategories(),
|
fetchCategories(),
|
||||||
fetchUsers().catch(() => []),
|
fetchUsers().catch(() => [] as User[]),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const filled = await backfillMissingOwners(bizList, users);
|
||||||
|
if (filled > 0) {
|
||||||
|
infoMessage.value = `${filled} مدیر برای کسبوکارهای بدون مالک با نام «مدیر + عنوان» اضافه شد.`;
|
||||||
|
[bizList, users] = await Promise.all([
|
||||||
|
fetchBusinesses(params),
|
||||||
|
fetchUsers().catch(() => [] as User[]),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
businesses.value = bizList;
|
businesses.value = bizList;
|
||||||
categories.value = cats;
|
categories.value = cats;
|
||||||
usersById.value = Object.fromEntries(users.map((u) => [u.id, u]));
|
usersById.value = Object.fromEntries(users.map((u) => [u.id, u]));
|
||||||
@@ -507,8 +551,8 @@ async function openAssign(biz: Business) {
|
|||||||
}
|
}
|
||||||
assignUser.value = owner;
|
assignUser.value = owner;
|
||||||
assignForm.value = {
|
assignForm.value = {
|
||||||
mobile: owner?.mobile ?? '',
|
mobile: owner?.mobile ?? biz.contactPhone ?? '',
|
||||||
fullName: owner?.fullName ?? '',
|
fullName: owner?.fullName ?? (biz.title ? `مدیر ${biz.title}` : ''),
|
||||||
};
|
};
|
||||||
} finally {
|
} finally {
|
||||||
assignLoading.value = false;
|
assignLoading.value = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user