Skip to content

Commit 11cbe47

Browse files
committed
Actualización del componente TodoFloatingPanel y TodoPanelContent para mejorar la gestión de listas de tareas. Se ha añadido un botón para crear nuevas listas y se ha implementado un formulario de creación que se activa mediante un trigger. Además, se han realizado ajustes en el manejo de estados y se ha optimizado la presentación de la interfaz, mejorando la experiencia del usuario al gestionar tareas.
1 parent b4cb437 commit 11cbe47

File tree

2 files changed

+105
-21
lines changed

2 files changed

+105
-21
lines changed

resources/js/components/ui/TodoFloatingPanel.tsx

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import React from 'react';
2-
import { X } from 'lucide-react';
1+
import React, { useState } from 'react';
2+
import { X, Plus } from 'lucide-react';
33
import { TodoPanelContent } from './TodoPanelContent';
44

55
interface TodoFloatingPanelProps {
@@ -9,6 +9,7 @@ interface TodoFloatingPanelProps {
99
}
1010

1111
export const TodoFloatingPanel: React.FC<TodoFloatingPanelProps> = ({ open, onClose, title = 'Lista de Tareas' }) => {
12+
const [createListTrigger, setCreateListTrigger] = useState(0);
1213
if (!open) return null;
1314
return (
1415
<>
@@ -26,16 +27,25 @@ export const TodoFloatingPanel: React.FC<TodoFloatingPanelProps> = ({ open, onCl
2627
>
2728
<div className="flex items-center justify-between p-4 border-b border-gray-200 dark:border-zinc-800">
2829
<h2 className="text-lg font-semibold">{title}</h2>
29-
<button
30-
onClick={onClose}
31-
className="rounded-full p-2 hover:bg-gray-100 dark:hover:bg-zinc-800 focus:outline-none"
32-
aria-label="Cerrar"
33-
>
34-
<X className="h-5 w-5" />
35-
</button>
30+
<div className="flex items-center gap-1">
31+
<button
32+
onClick={() => setCreateListTrigger(t => t + 1)}
33+
className="rounded-full p-2 hover:bg-gray-100 dark:hover:bg-zinc-800 focus:outline-none"
34+
aria-label="Crear nueva lista"
35+
>
36+
<Plus className="h-5 w-5" />
37+
</button>
38+
<button
39+
onClick={onClose}
40+
className="rounded-full p-2 hover:bg-gray-100 dark:hover:bg-zinc-800 focus:outline-none"
41+
aria-label="Cerrar"
42+
>
43+
<X className="h-5 w-5" />
44+
</button>
45+
</div>
3646
</div>
3747
<div className="flex-1 overflow-y-auto p-4">
38-
<TodoPanelContent />
48+
<TodoPanelContent createListTrigger={createListTrigger} panelOpen={false} />
3949
</div>
4050
</aside>
4151
</>

resources/js/components/ui/TodoPanelContent.tsx

Lines changed: 85 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,34 @@ import {
1414
AlertDialogCancel,
1515
} from '@/components/ui/alert-dialog';
1616

17-
export const TodoPanelContent: React.FC = () => {
17+
interface TodoPanelContentProps {
18+
createListTrigger?: number;
19+
panelOpen?: boolean;
20+
}
21+
22+
export const TodoPanelContent: React.FC<TodoPanelContentProps> = ({ createListTrigger, panelOpen }) => {
1823
const [lists, setLists] = useState<TodoList[]>([]);
1924
const [selectedListId, setSelectedListId] = useState<number | null>(null);
2025
const [todos, setTodos] = useState<Todo[]>([]);
2126
const [newListName, setNewListName] = useState('');
27+
const [showCreateList, setShowCreateList] = useState(false);
2228
const [newTodo, setNewTodo] = useState('');
23-
const [editingList, setEditingList] = useState(false);
29+
const [editMode, setEditMode] = useState<null | 'edit'>(null);
2430
const [editListName, setEditListName] = useState('');
2531
const [loading, setLoading] = useState(false);
2632
const [confirmDeleteListId, setConfirmDeleteListId] = useState<number | null>(null);
2733
const [confirmDeleteTodo, setConfirmDeleteTodo] = useState<Todo | null>(null);
2834

35+
// Mostrar formulario de creación de lista cuando se dispare el trigger externo
36+
useEffect(() => {
37+
if (typeof createListTrigger === 'number' && createListTrigger > 0) {
38+
setNewListName('');
39+
setEditListName('');
40+
setShowCreateList(true);
41+
}
42+
// eslint-disable-next-line
43+
}, [createListTrigger]);
44+
2945
// Cargar listas desde el backend al montar
3046
useEffect(() => {
3147
fetchLists();
@@ -81,6 +97,7 @@ export const TodoPanelContent: React.FC = () => {
8197
});
8298
if (res.ok) {
8399
setNewListName('');
100+
setShowCreateList(false);
84101
fetchLists();
85102
}
86103
};
@@ -121,7 +138,8 @@ export const TodoPanelContent: React.FC = () => {
121138
body: JSON.stringify({ name: editListName }),
122139
});
123140
if (res.ok) {
124-
setEditingList(false);
141+
setEditMode(null);
142+
setEditListName('');
125143
fetchLists();
126144
}
127145
};
@@ -178,6 +196,13 @@ export const TodoPanelContent: React.FC = () => {
178196
setConfirmDeleteTodo(null);
179197
};
180198

199+
// Ocultar el formulario de crear lista cuando el panel se cierra
200+
useEffect(() => {
201+
if (panelOpen === false) {
202+
setShowCreateList(false);
203+
}
204+
}, [panelOpen]);
205+
181206
// Render
182207
if (!lists.length) {
183208
return (
@@ -210,10 +235,40 @@ export const TodoPanelContent: React.FC = () => {
210235

211236
return (
212237
<div className="flex flex-col gap-4 h-full">
238+
{/* Formulario de creación de lista */}
239+
{showCreateList && (
240+
<div className="flex gap-2 items-center mt-2">
241+
<input
242+
className="flex-1 rounded border border-gray-300 px-2 py-1 text-sm"
243+
value={newListName}
244+
onChange={e => setNewListName(e.target.value)}
245+
placeholder="Nombre para la nueva lista de tareas"
246+
autoFocus
247+
onKeyDown={e => e.key === 'Enter' && handleCreateList()}
248+
/>
249+
<button
250+
className="p-2 rounded bg-gray-200 hover:bg-gray-300"
251+
onClick={handleCreateList}
252+
title="Crear"
253+
>
254+
<Check className="h-4 w-4 text-green-600" />
255+
</button>
256+
<button
257+
className="p-2 rounded hover:bg-gray-100"
258+
onClick={() => {
259+
setShowCreateList(false);
260+
setNewListName('');
261+
}}
262+
title="Cancelar"
263+
>
264+
<X className="h-4 w-4 text-gray-500" />
265+
</button>
266+
</div>
267+
)}
213268
{/* Selector de lista */}
214269
<div className="flex items-center gap-2">
215270
<select
216-
className="flex-1 rounded border border-gray-300 px-2 py-1 text-sm"
271+
className="flex-1 rounded border border-gray-300 px-2 py-1 text-sm bg-gray-100"
217272
value={selectedListId ?? ''}
218273
onChange={e => setSelectedListId(Number(e.target.value))}
219274
>
@@ -223,7 +278,14 @@ export const TodoPanelContent: React.FC = () => {
223278
</select>
224279
<button
225280
className="rounded p-2 hover:bg-gray-100"
226-
onClick={() => setEditingList(true)}
281+
onClick={() => {
282+
if (selectedListId) {
283+
const list = lists.find(l => l.id === selectedListId);
284+
setEditListName(list ? list.name : '');
285+
setNewListName('');
286+
setEditMode('edit');
287+
}
288+
}}
227289
title="Renombrar lista"
228290
>
229291
<Edit className="h-4 w-4 text-gray-500" />
@@ -236,20 +298,32 @@ export const TodoPanelContent: React.FC = () => {
236298
<Trash2 className="h-4 w-4 text-red-500" />
237299
</button>
238300
</div>
239-
{/* Renombrar lista */}
240-
{editingList && (
241-
<div className="flex gap-2 items-center">
301+
{/* Formulario de edición de lista */}
302+
{editMode === 'edit' && (
303+
<div className="flex gap-2 items-center mt-2">
242304
<input
243305
className="flex-1 rounded border border-gray-300 px-2 py-1 text-sm"
244306
value={editListName}
245307
onChange={e => setEditListName(e.target.value)}
246308
placeholder="Nuevo nombre"
247309
autoFocus
310+
onKeyDown={e => e.key === 'Enter' && handleRenameList()}
248311
/>
249-
<button className="p-2 rounded bg-gray-200 hover:bg-gray-300" onClick={handleRenameList} title="Guardar">
312+
<button
313+
className="p-2 rounded bg-gray-200 hover:bg-gray-300"
314+
onClick={handleRenameList}
315+
title="Guardar"
316+
>
250317
<Check className="h-4 w-4 text-green-600" />
251318
</button>
252-
<button className="p-2 rounded hover:bg-gray-100" onClick={() => setEditingList(false)} title="Cancelar">
319+
<button
320+
className="p-2 rounded hover:bg-gray-100"
321+
onClick={() => {
322+
setEditMode(null);
323+
setEditListName('');
324+
}}
325+
title="Cancelar"
326+
>
253327
<X className="h-4 w-4 text-gray-500" />
254328
</button>
255329
</div>
@@ -313,7 +387,7 @@ export const TodoPanelContent: React.FC = () => {
313387
{/* Agregar nueva tarea */}
314388
<div className="flex gap-2 mt-2">
315389
<input
316-
className="flex-1 rounded border border-gray-300 px-2 py-1 text-sm"
390+
className="flex-1 rounded border border-green-500 px-2 py-1 text-sm"
317391
placeholder="Nueva tarea"
318392
value={newTodo}
319393
onChange={e => setNewTodo(e.target.value)}

0 commit comments

Comments
 (0)