diff --git a/src/components/Scheduled/ScheduledForm.js b/src/components/Scheduled/ScheduledForm.js index d7d97e1..5d641fe 100644 --- a/src/components/Scheduled/ScheduledForm.js +++ b/src/components/Scheduled/ScheduledForm.js @@ -13,7 +13,7 @@ const defaultItem = { enabled: true, }; -const ScheduledForm = ({ editing, onSave, onCancel }) => { +const ScheduledForm = ({ editing, onSave, onCancel, hideHeader = false }) => { const [item, setItem] = useState(defaultItem); const isEditing = useMemo(() => Boolean(editing && editing.id), [editing]); diff --git a/src/components/Scheduled/ScheduledPage.js b/src/components/Scheduled/ScheduledPage.js index 53ab77a..3c221a2 100644 --- a/src/components/Scheduled/ScheduledPage.js +++ b/src/components/Scheduled/ScheduledPage.js @@ -56,6 +56,7 @@ const seeded = [ const ScheduledPage = () => { const [items, setItems] = useState(() => loadFromStorage() || seeded); const [editing, setEditing] = useState(null); + const [showModal, setShowModal] = useState(false); useEffect(() => { saveToStorage(items); @@ -67,6 +68,7 @@ const ScheduledPage = () => { if (payload.id) { setItems((prev) => prev.map((it) => (it.id === payload.id ? { ...it, ...payload } : it))); setEditing(null); + setShowModal(false); } else { const nextId = items.length ? Math.max(...items.map(i => i.id)) + 1 : 1; const next = { @@ -76,6 +78,7 @@ const ScheduledPage = () => { }; setItems((prev) => [next, ...prev]); setEditing(null); + setShowModal(false); } }; @@ -90,10 +93,28 @@ const ScheduledPage = () => { const handleDelete = (item) => { if (window.confirm('¿Eliminar esta programación?')) { setItems((prev) => prev.filter((it) => it.id !== item.id)); - if (editing && editing.id === item.id) setEditing(null); + if (editing && editing.id === item.id) { + setEditing(null); + setShowModal(false); + } } }; + const openCreateModal = () => { + setEditing(null); + setShowModal(true); + }; + + const openEditModal = (item) => { + setEditing(item); + setShowModal(true); + }; + + const closeModal = () => { + setEditing(null); + setShowModal(false); + }; + return (
@@ -113,14 +134,33 @@ const ScheduledPage = () => {

+ {showModal && ( +
+
e.stopPropagation()}> +
+

+ + {editing ? 'Editar programación' : 'Nueva programación'} +

+ +
+
+ +
+
+
+ )} +
- setEditing(null)} />
diff --git a/src/components/Scheduled/ScheduledTable.js b/src/components/Scheduled/ScheduledTable.js index 4aeb514..e221518 100644 --- a/src/components/Scheduled/ScheduledTable.js +++ b/src/components/Scheduled/ScheduledTable.js @@ -1,7 +1,7 @@ import React from 'react'; import '../../styles/components.css'; -const ScheduledTable = ({ items = [], onToggleEnabled, onRunNow, onEdit, onDelete }) => { +const ScheduledTable = ({ items = [], onToggleEnabled, onRunNow, onEdit, onDelete, onCreateNew }) => { const getStatusPill = (item) => { const cls = `status ${item.enabled ? 'completed' : 'pending'}`; const icon = item.enabled ? 'fas fa-check' : 'fas fa-pause'; @@ -20,6 +20,11 @@ const ScheduledTable = ({ items = [], onToggleEnabled, onRunNow, onEdit, onDelet Programaciones +
+ +

No hay solicitudes programadas todavía. Crea una nueva para comenzar.

@@ -34,6 +39,9 @@ const ScheduledTable = ({ items = [], onToggleEnabled, onRunNow, onEdit, onDelet + diff --git a/src/styles/components.css b/src/styles/components.css index 1fa650b..51d8a97 100644 --- a/src/styles/components.css +++ b/src/styles/components.css @@ -743,3 +743,173 @@ textarea { .link:hover { text-decoration: underline; } + +/* Sidebar Styles */ +.sidebar { + width: var(--sidebar-width); + background: linear-gradient(180deg, var(--secondary) 0%, #1e293b 100%); + color: white; + padding: 0; + transition: var(--transition); + box-shadow: var(--shadow-lg); + z-index: 100; + position: fixed; + height: 100vh; + overflow-y: auto; + display: flex; + flex-direction: column; +} + +.logo-container { + padding: 24px 20px; + border-bottom: 1px solid rgba(255,255,255,0.1); + display: flex; + align-items: center; + justify-content: space-between; +} + +.logo { + display: flex; + align-items: center; +} + +.logo-icon { + background: linear-gradient(135deg, var(--primary) 0%, var(--primary-light) 100%); + width: 40px; + height: 40px; + border-radius: 10px; + display: flex; + align-items: center; + justify-content: center; + margin-right: 12px; + box-shadow: 0 4px 6px rgba(99, 102, 241, 0.3); +} + +.logo-text { + font-size: 1.25rem; + font-weight: 700; +} + +.logo-text span { + color: var(--primary-light); +} + +.nav-container { + flex: 1; + padding: 20px 0; +} + +.nav-links { + list-style: none; +} + +.nav-links li { + margin: 4px 16px; + border-radius: 10px; + overflow: hidden; + transition: var(--transition); +} + +.nav-links li.active { + background: rgba(99, 102, 241, 0.15); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.nav-links li:hover:not(.active) { + background: rgba(255, 255, 255, 0.05); +} + +.nav-links a { + color: white; + text-decoration: none; + display: flex; + align-items: center; + padding: 14px 16px; + font-weight: 500; + transition: var(--transition); +} + +.nav-links i { + margin-right: 12px; + font-size: 1.2rem; + width: 24px; + text-align: center; +} + +.nav-links .badge { + margin-left: auto; + background: var(--primary); + color: white; + border-radius: 20px; + padding: 4px 10px; + font-size: 0.75rem; + font-weight: 600; +} + +.sidebar-footer { + padding: 20px; + border-top: 1px solid rgba(255,255,255,0.1); + margin-top: auto; +} + +.user-info { + display: flex; + align-items: center; +} + +/* ... existing styles ... */ + +/* Modal Styles */ +.modal-overlay { + position: fixed; + inset: 0; + background: rgba(15, 23, 42, 0.6); + backdrop-filter: blur(2px); + display: flex; + align-items: center; + justify-content: center; + z-index: 1000; + padding: 20px; +} + +.modal { + background: #ffffff; + color: var(--dark); + width: 100%; + max-width: 820px; + border-radius: 14px; + box-shadow: var(--shadow-lg); + border: 1px solid rgba(148, 163, 184, 0.25); + overflow: hidden; +} + +.modal-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 16px 20px; + border-bottom: 1px solid rgba(148, 163, 184, 0.15); + background: linear-gradient(180deg, rgba(30,41,59,0.6), rgba(2,6,23,0.4)); +} + +.modal-header h3 { + display: flex; + align-items: center; + gap: 10px; + margin: 0; +} + +.modal-body { + padding: 16px 20px 20px; +} + +/* Ensure form inside modal looks nice */ +.modal .form-container { + box-shadow: none; + border: none; + padding: 0; +} + +.modal .form-header { + display: none; /* header handled by modal */ +}