feat: customer groups for people and companies with tahesab group sync and bulk register

Multiple groups per contact, legacy group text migrated, excel import/export, contacts filter and column, richer create-in-tahesab, match-first bulk export
This commit is contained in:
2026-10-21 17:16:31 +03:30
parent ce27df20ca
commit 29d99cbded
27 changed files with 1728 additions and 26 deletions
+53
View File
@@ -0,0 +1,53 @@
import { ref } from 'vue';
import type { CustomerGroupColor, CustomerGroupDto } from '@mento/shared';
import { api } from '@/lib/api';
export const CUSTOMER_GROUP_COLOR_LABELS: Record<CustomerGroupColor, string> = {
teal: 'سبزآبی',
sky: 'آبی',
violet: 'بنفش',
rose: 'قرمز',
amber: 'نارنجی',
pink: 'صورتی',
slate: 'خاکستری',
};
/** رنگ متن/پس‌زمینهٔ چیپ گروه (پالت داده، نه رنگ‌های قالب) */
export const CUSTOMER_GROUP_SWATCH: Record<CustomerGroupColor, { fg: string; bg: string }> = {
teal: { fg: '#0f766e', bg: '#ccfbf1' },
sky: { fg: '#0369a1', bg: '#e0f2fe' },
violet: { fg: '#6d28d9', bg: '#ede9fe' },
rose: { fg: '#be123c', bg: '#ffe4e6' },
amber: { fg: '#b45309', bg: '#fef3c7' },
pink: { fg: '#be185d', bg: '#fce7f3' },
slate: { fg: '#334155', bg: '#e2e8f0' },
};
export function groupSwatch(color: string | null | undefined) {
return CUSTOMER_GROUP_SWATCH[(color ?? 'teal') as CustomerGroupColor] ?? CUSTOMER_GROUP_SWATCH.teal;
}
const groups = ref<CustomerGroupDto[]>([]);
const loaded = ref(false);
let pending: Promise<CustomerGroupDto[]> | null = null;
/** فهرست گروه‌های مشتری محیط (مشترک بین صفحه‌ها) */
export function useCustomerGroups() {
async function load(force = false): Promise<CustomerGroupDto[]> {
if (loaded.value && !force) return groups.value;
if (pending && !force) return pending;
pending = api
.get<CustomerGroupDto[]>('/customer-groups')
.then(({ data }) => {
groups.value = data;
loaded.value = true;
return data;
})
.finally(() => {
pending = null;
});
return pending;
}
return { groups, loaded, load };
}