diff --git a/apps/web/src/components/activities/RelatedActivitiesPanel.vue b/apps/web/src/components/activities/RelatedActivitiesPanel.vue new file mode 100644 index 0000000..6f39329 --- /dev/null +++ b/apps/web/src/components/activities/RelatedActivitiesPanel.vue @@ -0,0 +1,393 @@ + + + diff --git a/apps/web/src/components/pipeline/DealCard.vue b/apps/web/src/components/pipeline/DealCard.vue index a4bd9d9..556f7c4 100644 --- a/apps/web/src/components/pipeline/DealCard.vue +++ b/apps/web/src/components/pipeline/DealCard.vue @@ -1,5 +1,5 @@ + + diff --git a/apps/web/src/lib/pipeline-board.ts b/apps/web/src/lib/pipeline-board.ts index 7162445..c7b1923 100644 --- a/apps/web/src/lib/pipeline-board.ts +++ b/apps/web/src/lib/pipeline-board.ts @@ -20,6 +20,8 @@ export type PipelineDeal = { assigneeNames?: string[]; ownerId?: string | null; assigneeIds?: string[]; + personId?: string | null; + companyId?: string | null; /** متن‌های قابل جستجو (مشتری، شرکت، یادداشت، مسئولان …) */ searchFields?: Array; /** اولویت فعالیت؛ فقط روی کارت فعالیت نشان داده می‌شود */ @@ -36,6 +38,8 @@ export type PipelineUiCopy = { hideAmount?: boolean; /** کارت فعالیت: پرچم کنار عنوان و پنجرهٔ خلاصه به‌جای ورود مستقیم به جزئیات */ quickView?: boolean; + /** گوشه کارت: ایجاد سریع فعالیت برای معامله */ + quickActivity?: boolean; }; export const DEAL_BOARD_COPY: PipelineUiCopy = { @@ -45,6 +49,7 @@ export const DEAL_BOARD_COPY: PipelineUiCopy = { addItemAria: 'افزودن معامله به این مرحله', itemMenuAria: 'گزینه‌های معامله', listColTitle: 'معامله', + quickActivity: true, }; export const PROJECT_BOARD_COPY: PipelineUiCopy = { @@ -185,8 +190,8 @@ export function mapBoardToStages( expectedCloseAt: string | null; createdAt: string; promotedFromPriorAt: string | null; - person: { fullName: string } | null; - company: { name: string } | null; + person: { id?: string; fullName: string } | null; + company: { id?: string; name: string } | null; owner?: { id: string; fullName: string } | null; assignees?: Array<{ id: string; fullName: string }>; }>; @@ -239,6 +244,8 @@ export function mapBoardToStages( assigneeNames, ownerId: deal.owner?.id ?? null, assigneeIds: (deal.assignees ?? []).map((a) => a.id), + personId: deal.person?.id ?? null, + companyId: deal.company?.id ?? null, searchFields: [ deal.notes, deal.company?.name, diff --git a/apps/web/src/views/ActivityFormView.vue b/apps/web/src/views/ActivityFormView.vue index 77c76dc..8add5e6 100644 --- a/apps/web/src/views/ActivityFormView.vue +++ b/apps/web/src/views/ActivityFormView.vue @@ -544,6 +544,16 @@ async function load() { personId.value = incomingPerson; } leadId.value = typeof route.query.leadId === 'string' ? route.query.leadId : ''; + const incomingDeal = + typeof route.query.dealId === 'string' ? route.query.dealId : ''; + if (incomingDeal) { + dealId.value = incomingDeal; + const linkedDeal = deals.value.find((d) => d.id === incomingDeal); + if (linkedDeal?.person?.id && !personId.value) { + await ensurePersonLoaded(linkedDeal.person.id); + personId.value = linkedDeal.person.id; + } + } const incomingDef = typeof route.query.typeDefId === 'string' ? activityTypes.byId.value.get(route.query.typeDefId) diff --git a/apps/web/src/views/DealFormView.vue b/apps/web/src/views/DealFormView.vue index fde84b4..ba7dd38 100644 --- a/apps/web/src/views/DealFormView.vue +++ b/apps/web/src/views/DealFormView.vue @@ -45,6 +45,7 @@ import { toFaDigits } from '@/lib/jalali'; import { currencySuffix, formatMoney } from '@/lib/money'; import CustomFieldsSection from '@/components/CustomFieldsSection.vue'; import EntityTimeline from '@/components/EntityTimeline.vue'; +import RelatedActivitiesPanel from '@/components/activities/RelatedActivitiesPanel.vue'; import RelatedTasksPanel from '@/components/routines/RelatedTasksPanel.vue'; import JalaliDateInput from '@/components/JalaliDateInput.vue'; import MoneyInput from '@/components/MoneyInput.vue'; @@ -1014,6 +1015,14 @@ onMounted(load); +