diff --git a/app/src/components/DecisionModal.tsx b/app/src/components/DecisionModal.tsx
index adf4f89..b40a958 100644
--- a/app/src/components/DecisionModal.tsx
+++ b/app/src/components/DecisionModal.tsx
@@ -88,6 +88,8 @@ function AttachmentRow({
e.preventDefault()}
className="w-7 h-7 rounded-lg text-muted hover:bg-surface2 flex items-center justify-center shrink-0"
aria-label={t('decisions.attachment.download', { name: att.filename })}
>
@@ -97,6 +99,7 @@ function AttachmentRow({
e.preventDefault()}
onClick={() => {
setDeleting(true);
void Promise.resolve(onDelete(att)).finally(() => setDeleting(false));
@@ -131,6 +134,9 @@ export function DecisionModal({
const [solutionText, setSolutionText] = useState('');
const [proposing, setProposing] = useState(false);
const [chooseTarget, setChooseTarget] = useState(undefined);
+ // Cerrar sin solución: doble confirmación armada (patrón borrado de tarea)
+ const [closeArmed, setCloseArmed] = useState(false);
+ const closeTimer = useRef | null>(null);
const [error, setError] = useState(null);
const [commentBody, setCommentBody] = useState('');
const [commentSending, setCommentSending] = useState(false);
@@ -176,8 +182,13 @@ export function DecisionModal({
setEditError(null);
setSolAttError(null);
setAttError(null);
+ setCloseArmed(false);
}, [decisionId]);
+ useEffect(() => () => {
+ if (closeTimer.current) clearTimeout(closeTimer.current);
+ }, []);
+
useEffect(() => {
setDescEditing(false);
}, [decisionId]);
@@ -501,7 +512,9 @@ export function DecisionModal({
)}
- {/* Adjuntos de la decisión: añade cualquier miembro; borra quien subió o admin */}
+ {/* Adjuntos de la decisión: solo visibles mientras se edita la descripción.
+ Añade cualquier miembro; borra quien subió o admin. */}
+ {descEditing && (
{decisionAttachments.length > 0 && (
@@ -527,6 +540,8 @@ export function DecisionModal({
e.preventDefault()}
onClick={() => decAttInputRef.current?.click()}
className={`w-full flex items-center justify-center gap-2 rounded-xl border border-dashed border-app px-4 py-3 text-[13px] font-medium text-muted hover:bg-surface2 disabled:opacity-60 ${
decisionAttachments.length > 0 ? 'mt-2' : ''
@@ -546,6 +561,7 @@ export function DecisionModal({
)}
+ )}
{/* Soluciones */}
@@ -604,49 +620,37 @@ export function DecisionModal({
{editError}
)}
-
- ) : (
- <>
-
-
- {s.title}
-
- {chosen && (
-
-
- {t('decisions.modal.chosen')}
-
- )}
-
- {s.description && (
-
- {s.description}
-
- )}
-
- {t('decisions.by', { name: s.proposer_username })}
-
+ {/* Adjuntos de la solución: solo visibles mientras se edita */}
{detail.attachments.some((a) => a.solution_id === s.id) && (
-
+
{detail.attachments
.filter((a) => a.solution_id === s.id)
.map((a) => (
))}
)}
+ e.preventDefault()}
+ onClick={() => {
+ setSolAttTarget(s.id);
+ solAttInputRef.current?.click();
+ }}
+ className={`w-full flex items-center justify-center gap-2 rounded-xl border border-dashed border-app px-4 py-2.5 text-[13px] font-medium text-muted hover:bg-surface2 disabled:opacity-60 mt-2`}
+ >
+
+ {attUploading && solAttTarget === s.id
+ ? t('decisions.attachment.uploading')
+ : t('decisions.attachment.add')}
+
{solAttError?.solutionId === s.id && (
)}
- >
- )}
-
-
- {editingSolutionId !== s.id && (
+
+ ) : (
<>
- {(s.proposer_id === user?.id || user?.role === 'admin') && (
- <>
+ {/* Fila superior: titulo + like + editar */}
+
+
+
+ {s.title}
+
+ {chosen && (
+
+
+ {t('decisions.modal.chosen')}
+
+ )}
+
+ {decision.status === 'open' ? (
{
- setSolAttTarget(s.id);
- solAttInputRef.current?.click();
- }}
- className="w-8 h-8 rounded-lg text-faint hover:text-muted hover:bg-surface flex items-center justify-center disabled:opacity-60"
- aria-label={t('decisions.attachment.add')}
- title={t('decisions.attachment.add')}
+ onClick={() => void handleVote(s.id, s.my_vote)}
+ className={`inline-flex items-center gap-1 shrink-0 rounded-full px-3 py-1.5 text-[13px] font-semibold transition-colors ${
+ s.my_vote
+ ? 'bg-brand text-brandfg'
+ : 'bg-surface border border-app text-muted hover:bg-surface2'
+ }`}
+ aria-label={t('decisions.votes', { count: s.votes })}
>
-
+
+ {s.votes}
+ ) : (
+
+
+ {s.votes}
+
+ )}
+ {(s.proposer_id === user?.id || user?.role === 'admin') && (
startEditSolution(s.id, s.title, s.description)}
- className="w-8 h-8 rounded-lg text-faint hover:text-muted hover:bg-surface flex items-center justify-center"
+ className="w-8 h-8 rounded-lg text-faint hover:text-muted hover:bg-surface flex items-center justify-center shrink-0"
aria-label={t('decisions.modal.editSolution')}
title={t('decisions.modal.editSolution')}
>
- >
+ )}
+
+ {s.description && (
+
+ {s.description}
+
)}
- {decision.status === 'open' && (
- void handleVote(s.id, s.my_vote)}
- className={`inline-flex items-center gap-1 rounded-full px-3 py-1.5 text-[13px] font-semibold transition-colors ${
- s.my_vote
- ? 'bg-brand text-brandfg'
- : 'bg-surface border border-app text-muted hover:bg-surface2'
- }`}
- aria-label={t('decisions.votes', { count: s.votes })}
+ {solAttError?.solutionId === s.id && (
+
-
- {s.votes}
-
+ {solAttError.message}
+
)}
- {decision.status !== 'open' && (
-
-
- {s.votes}
+ {/* Autor + Elegir flotando a la derecha: sin separador,
+ encaja en el hueco que deja el texto */}
+
+
+ {t('decisions.by', { name: s.proposer_username })}
- )}
- {decision.status === 'open' && canDecide && (
- setChooseTarget(s.id)}
- className="px-2.5 py-1.5 rounded-lg text-[12px] font-medium bg-surface border border-app text-muted hover:text-brand"
- >
- {t('decisions.modal.choose')}
-
- )}
+ {decision.status === 'open' && canDecide && (
+ setChooseTarget(s.id)}
+ className="float-right px-3 py-1 rounded-full text-[12px] font-semibold border border-brand/60 text-brand hover:bg-brand-soft transition-colors"
+ >
+ {t('decisions.modal.choose')}
+
+ )}
+
>
)}
@@ -729,7 +754,7 @@ export function DecisionModal({
{/* Proponer solución */}
{decision.status === 'open' && (
-
+ )}
+ {/* Fila de acciones: proponer + acciones del creador, todas juntas */}
+
+ {decision.status === 'open' && (
{t('decisions.modal.propose')}
-
- )}
+ )}
+ {canDecide &&
+ (decision.status === 'decided' ? (
+
void handleReopen()}
+ className="inline-flex items-center gap-1.5 px-3 py-2 rounded-xl text-[13px] font-medium bg-surface border border-app text-muted hover:bg-surface2"
+ >
+
+ {t('decisions.modal.reopen')}
+
+ ) : (
+ <>
+
{
+ if (closeArmed) {
+ if (closeTimer.current) clearTimeout(closeTimer.current);
+ setCloseArmed(false);
+ setChooseTarget(null);
+ } else {
+ setCloseArmed(true);
+ closeTimer.current = setTimeout(() => setCloseArmed(false), 4000);
+ }
+ }}
+ className={
+ closeArmed
+ ? 'inline-flex items-center gap-1.5 px-3 py-2 rounded-xl text-[13px] font-semibold text-rose-600 dark:text-rose-400 bg-rose-50 dark:bg-rose-500/10 border border-rose-300 dark:border-rose-500/40'
+ : 'inline-flex items-center gap-1.5 px-3 py-2 rounded-xl text-[13px] font-medium bg-surface border border-app text-muted hover:bg-surface2'
+ }
+ >
+ {closeArmed
+ ? t('decisions.modal.closeArm')
+ : t('decisions.modal.closeWithoutSolution')}
+
+
void handleDelete()}
+ className="inline-flex items-center gap-1.5 px-3 py-2 rounded-xl text-[13px] font-medium text-rose-600 dark:text-rose-400 hover:bg-rose-50 dark:hover:bg-rose-500/10"
+ >
+ {t('common.delete')}
+
+ >
+ ))}
+
{error && (
- {/* Acciones del creador */}
- {canDecide && (
-
- {decision.status === 'decided' ? (
- void handleReopen()}
- className="inline-flex items-center gap-1.5 px-3 py-2 rounded-xl text-[13px] font-medium bg-surface border border-app text-muted hover:bg-surface2"
- >
-
- {t('decisions.modal.reopen')}
-
- ) : (
- <>
- setChooseTarget(null)}
- className="inline-flex items-center gap-1.5 px-3 py-2 rounded-xl text-[13px] font-medium bg-surface border border-app text-muted hover:bg-surface2"
- >
- {t('decisions.modal.closeWithoutSolution')}
-
- void handleDelete()}
- className="inline-flex items-center gap-1.5 px-3 py-2 rounded-xl text-[13px] font-medium text-rose-600 dark:text-rose-400 hover:bg-rose-50 dark:hover:bg-rose-500/10"
- >
- {t('common.delete')}
-
- >
- )}
-
- )}
-
{/* Comentarios */}
-
- {t('decisions.modal.comments')}
-
- {comments.length > 0 ? (
-
-
-
-
setCommentBody(e.target.value)}
- placeholder={t('comments.placeholder')}
- className="flex-1 bg-transparent text-[14px] outline-none placeholder:text-faint"
- />
+ {/* Input y boton en dos filas: en movil la fila unica sobrepasa el ancho */}
+
+
+
+
+ setCommentBody(e.target.value)}
+ placeholder={t('comments.placeholder')}
+ className="flex-1 bg-transparent text-[14px] outline-none placeholder:text-faint"
+ />
+
+
+
- {t('decisions.modal.chooseConfirm')}
+
+ {chooseTarget === null
+ ? t('decisions.modal.closeConfirm')
+ : t('decisions.modal.chooseConfirm')}
+
{t('comments.empty')}
)}
-
-
-
-
- {t('comments.placeholder')}
-
- setBody(e.target.value)}
- placeholder={t('comments.placeholder')}
- className="flex-1 bg-transparent text-[14px] outline-none placeholder:text-faint"
- />
+ {/* Input y boton en dos filas: en movil la fila unica sobrepasa el ancho */}
+
+
+
+
+
+ {t('comments.placeholder')}
+
+ setBody(e.target.value)}
+ placeholder={t('comments.placeholder')}
+ className="flex-1 bg-transparent text-[14px] outline-none placeholder:text-faint"
+ />
+
+
+