feat(automations): form-driven branching rules, round-robin assignment, lead-linked activities
This commit is contained in:
@@ -17,12 +17,15 @@ import {
|
||||
} from '@/components/ui';
|
||||
import RelatedTasksPanel from '@/components/routines/RelatedTasksPanel.vue';
|
||||
import type {
|
||||
ActivityDto,
|
||||
ConvertLeadResult,
|
||||
LeadDto,
|
||||
LeadEventDto,
|
||||
LeadStageDto,
|
||||
OrgUserDto,
|
||||
PaginatedResponse,
|
||||
} from '@mento/shared';
|
||||
import { ACTIVITY_TYPE_LABELS } from '@mento/shared';
|
||||
|
||||
type LeadDetail = LeadDto & { events: LeadEventDto[] };
|
||||
|
||||
@@ -39,6 +42,7 @@ const okMsg = ref('');
|
||||
const lead = ref<LeadDetail | null>(null);
|
||||
const stages = ref<LeadStageDto[]>([]);
|
||||
const users = ref<OrgUserDto[]>([]);
|
||||
const activities = ref<ActivityDto[]>([]);
|
||||
|
||||
const stageId = ref('');
|
||||
const assigneeId = ref('');
|
||||
@@ -85,12 +89,18 @@ async function load() {
|
||||
loading.value = true;
|
||||
error.value = '';
|
||||
try {
|
||||
const [leadRes, stagesRes, usersRes] = await Promise.all([
|
||||
const [leadRes, stagesRes, usersRes, actRes] = await Promise.all([
|
||||
api.get<LeadDetail>(`/leads/${id.value}`),
|
||||
api.get<LeadStageDto[]>('/leads/stages'),
|
||||
api.get<OrgUserDto[]>('/users').catch(() => ({ data: [] as OrgUserDto[] })),
|
||||
api
|
||||
.get<PaginatedResponse<ActivityDto>>('/activities', {
|
||||
params: { filter: 'all', leadId: id.value, limit: 30 },
|
||||
})
|
||||
.catch(() => null),
|
||||
]);
|
||||
lead.value = leadRes.data;
|
||||
activities.value = actRes?.data.items ?? [];
|
||||
stages.value = stagesRes.data;
|
||||
users.value = usersRes.data.filter((u) => u.isActive !== false);
|
||||
stageId.value = leadRes.data.stageId;
|
||||
@@ -394,6 +404,22 @@ onMounted(load);
|
||||
|
||||
<RelatedTasksPanel :entity="{ type: 'lead', id: lead.id, label: lead.title }" />
|
||||
|
||||
<UiCard v-if="activities.length" title="فعالیتهای مرتبط">
|
||||
<ul class="lead-acts">
|
||||
<li v-for="a in activities" :key="a.id">
|
||||
<RouterLink :to="{ name: 'activity-detail', params: { id: a.id } }">
|
||||
<strong>{{ a.title }}</strong>
|
||||
</RouterLink>
|
||||
<span class="muted">
|
||||
{{ a.typeDef?.name || ACTIVITY_TYPE_LABELS[a.type] }}
|
||||
· {{ a.assignee?.fullName || 'بدون مسئول' }}
|
||||
· {{ formatDate(a.dueAt) }}
|
||||
· {{ a.status === 'done' ? 'انجام شد' : a.status === 'canceled' ? 'لغو شده' : 'باز' }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</UiCard>
|
||||
|
||||
<UiCard title="جدول زمانی">
|
||||
<ul v-if="lead.events.length" class="timeline">
|
||||
<li v-for="ev in lead.events" :key="ev.id">
|
||||
@@ -538,6 +564,39 @@ onMounted(load);
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.lead-acts {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: grid;
|
||||
gap: 0.6rem;
|
||||
}
|
||||
|
||||
.lead-acts li {
|
||||
display: grid;
|
||||
gap: 0.15rem;
|
||||
padding-bottom: 0.55rem;
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
}
|
||||
|
||||
.lead-acts li:last-child {
|
||||
border-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.lead-acts a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.lead-acts a:hover strong {
|
||||
color: var(--accent, #0f766e);
|
||||
}
|
||||
|
||||
.lead-acts .muted {
|
||||
font-size: 0.78rem;
|
||||
}
|
||||
|
||||
.timeline {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
|
||||
Reference in New Issue
Block a user