|
|
import { TaskService } from '../../../tasks/service';
|
|
|
import { ICONS } from '../../../utils/icons';
|
|
|
import { codeId } from '../../../utils/formatting';
|
|
|
import {
|
|
|
parseMultipleIds, resolveAndValidate,
|
|
|
formatDue, handleBatch
|
|
|
} from '../shared';
|
|
|
import type { BatchOutcome } from '../shared';
|
|
|
|
|
|
type Ctx = {
|
|
|
sender: string;
|
|
|
groupId: string;
|
|
|
message: string;
|
|
|
};
|
|
|
|
|
|
type Msg = {
|
|
|
recipient: string;
|
|
|
message: string;
|
|
|
mentions?: string[];
|
|
|
};
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
// Single completion outcome
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
function completeOne(idInput: number, sender: string): BatchOutcome {
|
|
|
const rv = resolveAndValidate(idInput, sender);
|
|
|
|
|
|
if ('error' in rv) {
|
|
|
const isNotFound = rv.error.includes('no encontrada');
|
|
|
return {
|
|
|
status: isNotFound ? 'notFound' : 'blocked',
|
|
|
line: rv.error,
|
|
|
};
|
|
|
}
|
|
|
|
|
|
const { resolvedId } = rv;
|
|
|
const res = TaskService.completeTask(resolvedId, sender);
|
|
|
const due = formatDue(res.task);
|
|
|
const desc = res.task?.description || '(sin descripción)';
|
|
|
const dc = res.task?.display_code;
|
|
|
|
|
|
switch (res.status) {
|
|
|
case 'already':
|
|
|
return {
|
|
|
status: 'already',
|
|
|
line: `ℹ️ ${codeId(resolvedId, dc)} ya estaba completada — ${desc}${due}`,
|
|
|
};
|
|
|
case 'updated':
|
|
|
return {
|
|
|
status: 'updated',
|
|
|
line: `${ICONS.complete} ${codeId(resolvedId, dc)} completada — ${desc}${due}`,
|
|
|
};
|
|
|
default:
|
|
|
return {
|
|
|
status: 'notFound',
|
|
|
line: `⚠️ ${codeId(resolvedId)} no encontrada.`,
|
|
|
};
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
// Single-ID mode
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
function handleSingleComplete(idInput: number, sender: string): Msg[] {
|
|
|
const rv = resolveAndValidate(idInput, sender);
|
|
|
if ('error' in rv) {
|
|
|
return [{ recipient: sender, message: rv.error }];
|
|
|
}
|
|
|
|
|
|
const { resolvedId } = rv;
|
|
|
const res = TaskService.completeTask(resolvedId, sender);
|
|
|
const due = formatDue(res.task);
|
|
|
|
|
|
if (res.status === 'not_found') {
|
|
|
return [{ recipient: sender, message: `⚠️ Tarea ${codeId(resolvedId)} no encontrada.` }];
|
|
|
}
|
|
|
if (res.status === 'already') {
|
|
|
return [{
|
|
|
recipient: sender,
|
|
|
message: `ℹ️ ${codeId(resolvedId, res.task?.display_code)} _Ya estaba completada_ — ${res.task?.description || '(sin descripción)'}${due}`,
|
|
|
}];
|
|
|
}
|
|
|
|
|
|
return [{
|
|
|
recipient: sender,
|
|
|
message: `${ICONS.complete} ${codeId(resolvedId, res.task?.display_code)} _completada_ — ${res.task?.description || '(sin descripción)'}${due}`,
|
|
|
}];
|
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
// Main handler
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
export async function handleCompletar(context: Ctx): Promise<Msg[]> {
|
|
|
const tokens = (context.message || '').trim().split(/\s+/);
|
|
|
const { ids, truncated } = parseMultipleIds(tokens.slice(2), 10);
|
|
|
|
|
|
if (ids.length === 0) {
|
|
|
return [{
|
|
|
recipient: context.sender,
|
|
|
message: 'ℹ️ Uso: `t x 26` o múltiples: `t x 14 19 24` o `t x 14,19,24` (máx. 10)',
|
|
|
}];
|
|
|
}
|
|
|
|
|
|
if (ids.length === 1 && ids[0] != null) {
|
|
|
return handleSingleComplete(ids[0], context.sender);
|
|
|
}
|
|
|
|
|
|
return handleBatch(
|
|
|
context.sender,
|
|
|
ids,
|
|
|
truncated,
|
|
|
completeOne,
|
|
|
{ updated: 'completadas', already: 'ya estaban', notFound: 'no encontradas', blocked: 'bloqueadas' },
|
|
|
'',
|
|
|
) as Msg[];
|
|
|
}
|