From 960e01938d38918fdb046fd27fb6ea5bd20826da Mon Sep 17 00:00:00 2001 From: Mahdi Date: Sat, 17 Oct 2026 19:12:48 +0330 Subject: [PATCH] fix(web): apply prior lens on user ProfileView timeline Filter my-desk activities and deals by archive cutoff so current work stays clean. Co-authored-by: Cursor --- apps/web/src/views/ProfileView.vue | 46 ++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/apps/web/src/views/ProfileView.vue b/apps/web/src/views/ProfileView.vue index ea2ebe3..8d85851 100644 --- a/apps/web/src/views/ProfileView.vue +++ b/apps/web/src/views/ProfileView.vue @@ -93,9 +93,39 @@ const roleLabel = computed(() => auth.user?.role ? USER_ROLE_LABELS[auth.user.role] : 'کاربر', ); const myId = computed(() => auth.user?.id ?? ''); +const priorArchiveOn = computed(() => Boolean(auth.user?.priorArchive)); +const priorLens = computed(() => auth.user?.priorArchive?.lens ?? null); + +function isPriorActivity(row: ActivityDto) { + const cutoff = auth.user?.priorArchive?.cutoffAt; + if (!auth.user?.priorArchive || !cutoff) return false; + if (row.promotedFromPriorAt) return false; + return new Date(row.createdAt).getTime() < new Date(cutoff).getTime(); +} + +function isPriorDeal(row: DealDto) { + const cutoff = auth.user?.priorArchive?.cutoffAt; + if (!auth.user?.priorArchive || !cutoff) return false; + if (row.promotedFromPriorAt) return false; + return new Date(row.createdAt).getTime() < new Date(cutoff).getTime(); +} + +function inActiveLensActivity(row: ActivityDto) { + if (!priorArchiveOn.value || !auth.user?.priorArchive?.cutoffAt) return true; + const prior = isPriorActivity(row); + return priorLens.value === 'archive' ? prior : !prior; +} + +function inActiveLensDeal(row: DealDto) { + if (!priorArchiveOn.value || !auth.user?.priorArchive?.cutoffAt) return true; + const prior = isPriorDeal(row); + return priorLens.value === 'archive' ? prior : !prior; +} + +const lensActivities = computed(() => activities.value.filter(inActiveLensActivity)); const myDeals = computed(() => - deals.value.filter((d) => d.owner?.id === myId.value), + deals.value.filter((d) => d.owner?.id === myId.value && inActiveLensDeal(d)), ); const openDeals = computed(() => myDeals.value.filter((d) => d.status === 'open')); const dealTotal = computed(() => @@ -109,11 +139,11 @@ const myCards = computed(() => const nextActivity = computed(() => { const now = Date.now(); return ( - activities.value + lensActivities.value .filter((a) => a.status === 'open' && a.dueAt) .sort((a, b) => new Date(a.dueAt!).getTime() - new Date(b.dueAt!).getTime()) .find((a) => new Date(a.dueAt!).getTime() >= now - 60 * 60 * 1000) ?? - activities.value + lensActivities.value .filter((a) => a.status === 'open' && a.dueAt) .sort((a, b) => new Date(a.dueAt!).getTime() - new Date(b.dueAt!).getTime())[0] ?? null @@ -121,7 +151,7 @@ const nextActivity = computed(() => { }); const lastTouchAt = computed(() => { - const stamps = activities.value + const stamps = lensActivities.value .map((a) => a.completedAt || a.dueAt || a.createdAt) .filter(Boolean) .sort((a, b) => new Date(b).getTime() - new Date(a).getTime()); @@ -144,7 +174,7 @@ const probability = computed(() => const smartText = computed(() => { if (aiBrief.value) return aiBrief.value; - const overdue = activities.value.filter( + const overdue = lensActivities.value.filter( (a) => a.status === 'open' && a.dueAt && new Date(a.dueAt).getTime() < Date.now(), ).length; const bits: string[] = []; @@ -246,7 +276,7 @@ function timelineIcon(tone: TimelineTone) { } const timeline = computed(() => - activities.value + lensActivities.value .map((a) => { const badge = activityBadge(a); return { @@ -266,7 +296,7 @@ const timeline = computed(() => const summaryTimeline = computed(() => timeline.value.slice(0, 6)); -const summaryEmpty = computed(() => !activities.value.length && !myDeals.value.length); +const summaryEmpty = computed(() => !lensActivities.value.length && !myDeals.value.length); const activitiesEmpty = computed(() => !timeline.value.length); const dealsEmpty = computed(() => !myDeals.value.length); const cardsEmpty = computed(() => !myCards.value.length); @@ -410,7 +440,7 @@ async function load() { try { const [actRes, boardRes] = await Promise.all([ api.get>('/activities', { - params: { filter: 'all', limit: 80 }, + params: { filter: 'all', desk: 'mine', limit: 80 }, }), api.get('/pipelines/board'), ]);