fix(activities): keep board filters and make card drops reliable

Return to the filtered desk after marking an activity done, widen the detail title, and stop a stuck column-drag id from blocking card moves.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-11-11 13:05:26 +03:30
co-authored by Cursor
parent f13a1249af
commit 871d7bba1a
4 changed files with 82 additions and 42 deletions
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import { computed, nextTick, ref, watch } from 'vue';
import { useRouter } from 'vue-router';
import axios from 'axios';
import type {
@@ -227,7 +227,8 @@ function onMenuActivity(id: string) {
}
function onDragStart(deal: PipelineDeal, event: DragEvent) {
if (quickId.value) closeQuick();
// اگر شناسهٔ درگ ستون گیر کرده باشد، دراپ کارت را ستون‌جابه‌جا می‌بیند
draggingColumnId.value = null;
draggingId.value = deal.id;
overlayDeal.value = deal;
const sid = findStageOf(deal.id);
@@ -241,12 +242,19 @@ function onDragStart(deal: PipelineDeal, event: DragEvent) {
img.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
event.dataTransfer.setDragImage(img, 0, 0);
}
// بستن پیش‌نمایش وسط dragstart گاهی خودِ درگ را لغو می‌کند
if (quickId.value) void nextTick(() => closeQuick());
}
function onDragEnd() {
draggingId.value = null;
dropStageId.value = null;
overlayDeal.value = null;
const endedId = draggingId.value;
// drop معمولاً قبل از dragend است؛ کمی تأخیر تا fallback شناسه از بین نرود
window.setTimeout(() => {
if (draggingId.value !== endedId) return;
draggingId.value = null;
dropStageId.value = null;
overlayDeal.value = null;
}, 0);
}
function onDragOver(stageId: string, event: DragEvent) {
@@ -331,18 +339,24 @@ async function moveCard(activityId: string, toStageId: string, index?: number) {
async function onDrop(stageId: string, event: DragEvent, index?: number) {
event.preventDefault();
const raw = event.dataTransfer?.getData('text/plain') || draggingColumnId.value || draggingId.value || '';
const transfer = event.dataTransfer?.getData('text/plain') || '';
const cardId = draggingId.value;
const columnId = draggingColumnId.value;
dropStageId.value = null;
draggingId.value = null;
overlayDeal.value = null;
if (raw.startsWith('stage:') || draggingColumnId.value) {
const fromId = raw.replace(/^stage:/, '') || draggingColumnId.value;
draggingColumnId.value = null;
draggingColumnId.value = null;
const isStageDrag = transfer.startsWith('stage:');
if (isStageDrag || (!transfer && !cardId && columnId)) {
const fromId = isStageDrag ? transfer.slice('stage:'.length) : columnId;
if (fromId) await reorderColumn(fromId, stageId);
return;
}
if (!raw || moving.value) return;
await moveCard(raw, stageId, index);
const activityId = (!isStageDrag && transfer) || cardId || '';
if (!activityId || moving.value) return;
await moveCard(activityId, stageId, index);
}
async function persistOrder(ids: string[]) {
@@ -500,7 +514,7 @@ function openFullActivity(id: string) {
@rename-stage="onRenameStage"
@delete-stage="onDeleteStage"
@move-stage="onMoveStage"
@column-drag-start="(id: string) => (draggingColumnId = id)"
@column-drag-start="(id: string) => { draggingId = null; overlayDeal = null; draggingColumnId = id; }"
@column-drag-end="draggingColumnId = null; dropStageId = null"
@add-stage="onAddStage"
@load-more="loadMore"