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 */
+}