limpia 2 css con estilos sin usar

main
brobert 1 month ago
parent 138eaa7238
commit 144215a0b5

@ -22,7 +22,9 @@
export let groupName: string | null = null;
export let groupId: string | null = null;
const dispatch = createEventDispatcher<{ changed: { id: number; action: string; patch: any } }>();
const dispatch = createEventDispatcher<{
changed: { id: number; action: string; patch: any };
}>();
const code = display_code ?? id;
const codeStr = String(code).padStart(4, "0");
@ -74,7 +76,7 @@
function toIsoSqlLocal(d: Date = new Date()): string {
const iso = d.toISOString();
return iso.substring(0, 23).replace('T', ' ');
return iso.substring(0, 23).replace("T", " ");
}
async function doComplete() {
@ -85,7 +87,9 @@
const res = await fetch(`/api/tasks/${id}/complete`, { method: "POST" });
if (res.ok) {
const data = await res.json().catch(() => null);
const newCompletedAt: string | null = data?.task?.completed_at ? String(data.task.completed_at) : toIsoSqlLocal(new Date());
const newCompletedAt: string | null = data?.task?.completed_at
? String(data.task.completed_at)
: toIsoSqlLocal(new Date());
// Si no tenía responsables, el backend te auto-asigna: reflejarlo localmente
if (hadNoAssignees && currentUserId) {
const set = new Set<string>(assignees || []);
@ -94,8 +98,16 @@
}
completed = true;
completed_at = newCompletedAt;
success(hadNoAssignees ? "Te has asignado y completado la tarea" : "Tarea completada");
dispatch("changed", { id, action: "complete", patch: { completed: true, completed_at, assignees } });
success(
hadNoAssignees
? "Te has asignado y completado la tarea"
: "Tarea completada",
);
dispatch("changed", {
id,
action: "complete",
patch: { completed: true, completed_at, assignees },
});
} else {
const txt = await res.text();
toastError(txt || "No se pudo completar la tarea");
@ -111,13 +123,19 @@
if (busy || !completed) return;
busy = true;
try {
const res = await fetch(`/api/tasks/${id}/uncomplete`, { method: "POST" });
const res = await fetch(`/api/tasks/${id}/uncomplete`, {
method: "POST",
});
if (res.ok) {
await res.json().catch(() => null);
completed = false;
completed_at = null;
success("Tarea reabierta");
dispatch("changed", { id, action: "uncomplete", patch: { completed: false, completed_at: null } });
dispatch("changed", {
id,
action: "uncomplete",
patch: { completed: false, completed_at: null },
});
} else {
const txt = await res.text();
toastError(txt || "No se pudo deshacer completar");
@ -136,7 +154,10 @@
const res = await fetch(`/api/tasks/${id}/unassign`, { method: "POST" });
if (res.ok) {
if (currentUserId) {
const after = (assignees || []).filter((a) => normalizeDigits(a) !== normalizeDigits(String(currentUserId)));
const after = (assignees || []).filter(
(a) =>
normalizeDigits(a) !== normalizeDigits(String(currentUserId)),
);
assignees = after;
}
success("Asignación eliminada");
@ -198,10 +219,10 @@
}
}
async function saveText(text?: string) {
if (busy) return;
const rawSource = typeof text === "string" ? text : (taskText?.getCurrentText?.() ?? "");
const rawSource =
typeof text === "string" ? text : (taskText?.getCurrentText?.() ?? "");
const raw = String(rawSource).replace(/\s+/g, " ").trim();
if (raw.length < 1 || raw.length > 1000) {
toastError("La descripción debe tener entre 1 y 1000 caracteres.");
@ -221,7 +242,11 @@
if (res.ok) {
description = raw;
success("Descripción actualizada");
dispatch("changed", { id, action: "update_desc", patch: { description } });
dispatch("changed", {
id,
action: "update_desc",
patch: { description },
});
editingText = false;
} else {
const txt = await res.text();
@ -239,16 +264,22 @@
}
</script>
<li class="task" class:completed in:fade={{ duration: 180 }} out:fade={{ duration: 180 }}>
<li
class="task"
class:completed
in:fade={{ duration: 180 }}
out:fade={{ duration: 180 }}
>
<div class="code">{codeStr}</div>
<TaskText
description={description}
{description}
{completed}
editing={editingText}
{busy}
bind:this={taskText}
on:toggleEdit={toggleEditText}
on:saveText={(e) => saveText((e as CustomEvent<{ text: string }>).detail.text)}
on:saveText={(e) =>
saveText((e as CustomEvent<{ text: string }>).detail.text)}
on:cancelText={cancelText}
/>
@ -272,16 +303,17 @@
{canUnassign}
{busy}
{completed}
editingText={editingText}
{editingText}
editingDate={editing}
dateValue={dateValue}
{dateValue}
on:claim={doClaim}
on:unassign={doUnassign}
on:toggleEditText={toggleEditText}
on:saveText={saveText}
on:cancelText={cancelText}
on:toggleEditDate={toggleEdit}
on:saveDate={(e) => saveDate((e as CustomEvent<{ value: string | null }>).detail.value)}
on:saveDate={(e) =>
saveDate((e as CustomEvent<{ value: string | null }>).detail.value)}
on:clearDate={clearDate}
on:cancelDate={() => (editing = false)}
/>
@ -324,9 +356,6 @@
gap: 6px;
align-items: center;
}
.muted {
color: var(--color-text-muted);
}
.assignees-container {
grid-row: 4/5;
grid-column: 1/2;
@ -350,69 +379,21 @@
align-items: center;
justify-content: flex-end;
}
.btn {
padding: 4px 8px;
border: 1px solid var(--color-border);
background: var(--color-surface);
color: var(--color-text);
border-radius: 6px;
font-size: 13px;
cursor: pointer;
font-family: monospace;
box-shadow: 0 0 8px 4px var(--color-border);
margin-bottom: 4px;
}
.btn[disabled] {
opacity: 0.6;
cursor: not-allowed;
}
.btn.primary {
border-color: var(--color-primary);
background: var(--color-primary-muted);
color: var(--color-text);
}
:global(.task .btn.primary svg) {
margin-right: 8px;
}
.btn.ghost {
background: transparent;
}
.btn.danger {
background: var(--color-danger);
color: #fff;
border-color: transparent;
}
.icon-btn {
border: 1px solid var(--color-surface);
border-radius: 6px;
background: var(--color-surface);
font-size: 12px;
line-height: 1;
font-family: monospace;
box-shadow: 0 0 8px 4px var(--color-border);
}
:global(.task .icon-btn svg) {
margin-right: 8px;
}
.date {
padding: 4px 6px;
font-size: 14px;
}
@media (max-width: 768px) {
.actions {
justify-self: stretch;
}
.actions .secondary-action {
flex: 0 0 auto;
}
/* Botón de completar a ancho completo en mobile */
.complete {
grid-column: 1/3;
justify-self: stretch;
}
.complete .btn {
width: 100%;
}
}
@media (max-width: 480px) {
.task {
@ -427,16 +408,7 @@
grid-column: 1/3;
justify-self: flex-end;
}
.icon-btn {
padding: 2px 8px;
}
}
/* Badge de responsables */
.icon-btn-svg {
fill-rule: evenodd;
clip-rule: evenodd;
fill: var(--color-text);
}
</style>

@ -328,8 +328,4 @@
padding: 0;
list-style: none;
}
.footnote {
margin-top: 0.75rem;
color: var(--color-text-muted);
}
</style>

Loading…
Cancel
Save