diff --git a/app/api/leantime/tasks/route.ts b/app/api/leantime/tasks/route.ts index da94353..036f3d0 100644 --- a/app/api/leantime/tasks/route.ts +++ b/app/api/leantime/tasks/route.ts @@ -112,70 +112,43 @@ async function getDoneStatusValues(userId: number): Promise> { }), }); - if (!data.result || !Array.isArray(data.result)) { + if (!data.result || typeof data.result !== 'object' || Array.isArray(data.result)) { console.log('[LEANTIME_TASKS] ⚠️ Invalid response format from getAllStatusLabelsByUserId, using fallback'); - console.log('[LEANTIME_TASKS] Response structure:', JSON.stringify(data, null, 2)); + console.log('[LEANTIME_TASKS] Response type:', typeof data.result, 'isArray:', Array.isArray(data.result)); logger.warn('[LEANTIME_TASKS] Invalid response format from getAllStatusLabelsByUserId, using fallback'); // Fallback to default values if API fails return new Set(['0', '3', '5']); } + // data.result is an object where: + // - Keys are project IDs (strings like "4", "5", "6", "457") + // - Values are objects where keys are status numbers (strings like "0", "1", "2", "3", "4", "5", "-1") + // - Each status object has: name, statusType, class, kanbanCol, sortKey + console.log('[LEANTIME_TASKS] 📋 getAllStatusLabelsByUserId response structure:', { resultType: typeof data.result, - isArray: Array.isArray(data.result), - length: data.result.length, - firstItem: data.result[0] ? Object.keys(data.result[0]) : null, + isObject: typeof data.result === 'object', + projectIds: Object.keys(data.result), }); - // data.result is an array of projects, each with labels - // Each label has: id, name, statusType, class, etc. - data.result.forEach((project: any, projectIndex: number) => { - console.log(`[LEANTIME_TASKS] 📁 Project ${projectIndex}:`, { - projectId: project.id, - projectName: project.name, - hasLabels: !!project.labels, - labelsType: typeof project.labels, - labelsIsArray: Array.isArray(project.labels), - labelsCount: project.labels ? (Array.isArray(project.labels) ? project.labels.length : 'not array') : 'no labels', - }); + // Iterate through all projects + Object.keys(data.result).forEach((projectId: string) => { + const projectStatuses = data.result[projectId]; - if (project.labels && Array.isArray(project.labels)) { - project.labels.forEach((label: any, labelIndex: number) => { - console.log(`[LEANTIME_TASKS] 🏷️ Label ${labelIndex} in project ${projectIndex}:`, { - labelId: label.id, - labelName: label.name, - labelStatusType: label.statusType, - labelClass: label.class, - allKeys: Object.keys(label), - }); + if (projectStatuses && typeof projectStatuses === 'object') { + // Iterate through all statuses in this project + Object.keys(projectStatuses).forEach((statusKey: string) => { + const statusInfo = projectStatuses[statusKey]; - // Check if the label name (case-insensitive) contains "done" - const labelName = String(label.name || '').toLowerCase().trim(); - const statusType = String(label.statusType || '').toLowerCase().trim(); - - if (labelName === 'done' || labelName.includes('done') || statusType === 'done') { - // The status value might be in different places depending on Leantime version - // Try label.id, label.name, or extract from label structure - let statusValue = ''; + if (statusInfo && typeof statusInfo === 'object') { + const statusType = String(statusInfo.statusType || '').toUpperCase(); + const statusName = String(statusInfo.name || '').toLowerCase().trim(); - // If label.id is a number, use it directly - if (typeof label.id === 'number') { - statusValue = String(label.id); - } else if (label.id) { - // If it's a string like "projectId-status", extract the status part - const idStr = String(label.id); - const parts = idStr.split('-'); - statusValue = parts.length > 1 ? parts[parts.length - 1] : idStr; - } else if (label.name) { - // Try to extract numeric value from name - const nameStr = String(label.name); - const numMatch = nameStr.match(/\d+/); - statusValue = numMatch ? numMatch[0] : nameStr; - } - - if (statusValue) { - doneStatusValues.add(statusValue); - console.log(`[LEANTIME_TASKS] ✅ Found done status: ${statusValue} from label:`, label); + // Check if statusType is "DONE" or name contains "done" + if (statusType === 'DONE' || statusName === 'done' || statusName.includes('done')) { + // The statusKey IS the status number (e.g., "0", "3", "5", "-1") + doneStatusValues.add(statusKey); + console.log(`[LEANTIME_TASKS] ✅ Found done status: ${statusKey} in project ${projectId} (name: "${statusInfo.name}", statusType: "${statusType}")`); } } }); @@ -184,11 +157,11 @@ async function getDoneStatusValues(userId: number): Promise> { console.log('[LEANTIME_TASKS] ✅ Identified done status values:', { doneStatusValues: Array.from(doneStatusValues), - projectsCount: data.result.length, + projectsCount: Object.keys(data.result).length, }); logger.debug('[LEANTIME_TASKS] Identified done status values', { doneStatusValues: Array.from(doneStatusValues), - projectsCount: data.result.length, + projectsCount: Object.keys(data.result).length, }); // If no done statuses found, use fallback