feat(activities): split customer column, wider search, custom activity types with type-specific fields

- Table: separate assignee and customer columns; search by assignee and activity type
- ActivityTypeDef model with per-type field definitions (text, select, checklist, participants, ...)
- Default types incl. meeting subject/participants and task checklist; admins manage types
- Participants see activities in their lists and get notified

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-07 12:29:23 +03:30
co-authored by Cursor
parent aa2f39256a
commit 13668c4ba4
17 changed files with 3371 additions and 147 deletions
@@ -5,10 +5,10 @@ import axios from 'axios';
import type {
ActivityDto,
ActivityStageDto,
ActivityType,
PaginatedResponse,
} from '@mento/shared';
import { api } from '@/lib/api';
import { activityTypeView } from '@/lib/activity-types';
import { calendarDaysBetween, formatClockFa, formatJalaliDay, startOfLocalDay, toFaDigits } from '@/lib/jalali';
import PipelineBoard from '@/components/pipeline/PipelineBoard.vue';
import DealCardOverlay from '@/components/pipeline/DealCardOverlay.vue';
@@ -59,13 +59,6 @@ const moving = ref(false);
const stageBusy = ref(false);
const localOrder = ref<string[] | null>(null);
const typeLabel: Record<ActivityType, string> = {
call: 'تماس',
meeting: 'جلسه',
task: 'وظیفه',
note: 'پیام',
};
const KIND_BADGE: Record<ActivityStageDto['kind'], string | undefined> = {
open: undefined,
done: 'انجام‌شده',
@@ -109,7 +102,7 @@ function toCard(item: ActivityDto, stageId: string): PipelineDeal {
return {
id: item.id,
title: item.title,
description: [typeLabel[item.type], party].filter(Boolean).join(' · '),
description: [activityTypeView(item).name, party].filter(Boolean).join(' · '),
amount: null,
date: dateText(item),
initials: initialsFromTitle(party || item.title),