diff --git a/src/pages/SettingsPage.js b/src/pages/SettingsPage.js new file mode 100644 index 0000000..e69de29 diff --git a/src/styles/base.css b/src/styles/base.css new file mode 100644 index 0000000..7527d02 --- /dev/null +++ b/src/styles/base.css @@ -0,0 +1,257 @@ +/* ====== BASE / VARIABLES ====== */ +:root { + font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + line-height: 1.6; + font-weight: 400; + color-scheme: light; + color: #1e293b; + background-color: #f8fafc; + + --primary: #2563eb; + --primary-hover: #1d4ed8; + --primary-light: rgba(37, 99, 235, 0.06); + --primary-subtle: rgba(37, 99, 235, 0.08); + --success: #16a34a; + --success-hover: #15803d; + --warning: #ca8a04; + --warning-hover: #a16207; + --danger: #dc2626; + --danger-hover: #b91c1c; + --card-bg: #ffffff; + --border-color: #e2e8f0; + --border-subtle: #f1f5f9; + --text-primary: #0f172a; + --text-secondary: #64748b; + --text-tertiary: #94a3b8; + --sidebar-bg: #0f172a; + --sidebar-text: #94a3b8; + --sidebar-active: #3b82f6; + --sidebar-hover: rgba(255, 255, 255, 0.04); + --radius-sm: 6px; + --radius-md: 8px; + --radius-lg: 10px; + --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.04); + --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.04); + --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.06); + --shadow-lg: 0 10px 30px rgba(0, 0, 0, 0.08); + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +*, *::before, *::after { box-sizing: border-box; } + +a { font-weight: 500; color: var(--primary); text-decoration: none; } +a:hover { color: var(--primary-hover); } + +body { margin: 0; min-width: 320px; min-height: 100vh; } + +h1 { font-size: 1.625rem; line-height: 1.25; font-weight: 600; letter-spacing: -0.02em; } + +#app { width: 100%; min-height: 100vh; } + +button { + border-radius: var(--radius-md); + border: 1px solid transparent; + padding: 0.5em 1em; + font-size: 0.8125rem; + font-weight: 500; + font-family: inherit; + background-color: var(--primary); + color: white; + cursor: pointer; + transition: background-color 0.15s ease, box-shadow 0.15s ease; +} +button:hover { background-color: var(--primary-hover); } +button:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; } + +/* Status badges */ +.status-badge { + display: inline-flex; + align-items: center; + padding: 0.175rem 0.55rem; + border-radius: 4px; + font-size: 0.7rem; + font-weight: 600; + letter-spacing: 0.02em; + text-transform: uppercase; +} +.status-pending { background: #fef9c3; color: #854d0e; } +.status-paid { background: #dcfce7; color: #166534; } +.status-overdue { background: #fee2e2; color: #991b1b; } +.status-draft { background: #f1f5f9; color: #475569; } +.status-validated { background: #dbeafe; color: #1e40af; } +.status-unpaid { background: #fef2f2; color: #991b1b; } +.status-canceled { background: #f1f5f9; color: #94a3b8; text-decoration: line-through; } + +/* Form group */ +.form-group { margin-bottom: 1.25rem; } +.form-group label { + display: block; + color: var(--text-primary); + margin-bottom: 0.375rem; + font-weight: 500; + font-size: 0.8125rem; +} +.form-group input { + width: 100%; + padding: 0.5rem 0.75rem; + border: 1px solid var(--border-color); + border-radius: var(--radius-sm); + background: #fff; + color: var(--text-primary); + font-size: 0.875rem; + box-sizing: border-box; + transition: border-color 0.15s ease, box-shadow 0.15s ease; +} +.form-group input:focus { + outline: none; + border-color: var(--primary); + box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.08); +} + +/* View button */ +.btn-view { + background: transparent; + border: none; + padding: 0.35rem; + border-radius: var(--radius-sm); + cursor: pointer; + color: var(--text-tertiary); + transition: color 0.15s ease, background 0.15s ease; + display: inline-flex; + align-items: center; + justify-content: center; +} +.btn-view:hover { color: var(--primary); background: var(--primary-light); } + +/* Loading */ +.loading, .error, .no-invoices, .no-clients { + padding: 3rem; + text-align: center; + color: var(--text-secondary); + font-size: 0.9rem; +} +.error { color: var(--danger); } + +/* Pagination */ +.pagination { + display: flex; + justify-content: center; + align-items: center; + gap: 0.75rem; + margin-top: 1.25rem; + padding: 0.75rem 1rem; + background: var(--card-bg); + border-radius: var(--radius-md); + border: 1px solid var(--border-color); +} +.pagination-info { + font-weight: 500; + color: var(--text-secondary); + font-size: 0.8125rem; + display: flex; + gap: 0.3rem; + align-items: center; +} +.pagination-info .current-page, +.pagination-info .total-pages { + font-weight: 600; + color: var(--text-primary); + min-width: 20px; + text-align: center; +} +.btn-pagination { + padding: 0.4rem 0.9rem; + background: var(--card-bg); + color: var(--text-primary); + border: 1px solid var(--border-color); + border-radius: var(--radius-sm); + cursor: pointer; + font-weight: 500; + font-size: 0.8125rem; + transition: all 0.15s ease; +} +.btn-pagination:hover:not(:disabled) { + background: var(--primary); + color: #fff; + border-color: var(--primary); +} +.btn-pagination:disabled { + background: #f8fafc; + color: #cbd5e1; + cursor: not-allowed; +} + +@media (max-width: 768px) { + .pagination { flex-wrap: wrap; gap: 0.5rem; } + .btn-pagination { flex: 1; min-width: 90px; } + .pagination-info { order: 3; width: 100%; justify-content: center; } +} + +/* Skeleton */ +@keyframes skeleton-shimmer { + 0% { background-position: -200% 0; } + 100% { background-position: 200% 0; } +} +.skeleton { + background: linear-gradient(90deg, #f1f5f9 25%, #e2e8f0 50%, #f1f5f9 75%); + background-size: 200% 100%; + animation: skeleton-shimmer 1.8s ease-in-out infinite; + border-radius: 4px; +} +.skeleton-row { + display: flex; gap: 1rem; + padding: 0.875rem 1.25rem; + border-bottom: 1px solid var(--border-subtle); +} +.skeleton-cell { height: 14px; border-radius: 3px; } +.skeleton-cell.w-sm { width: 60px; } +.skeleton-cell.w-md { width: 120px; } +.skeleton-cell.w-lg { width: 200px; } +.skeleton-cell.w-xl { width: 100%; } + +/* Empty state */ +.empty-state { + display: flex; + flex-direction: column; + align-items: center; + padding: 3.5rem 2rem; + text-align: center; + color: var(--text-secondary); +} +.empty-state-icon { + width: 56px; height: 56px; + border-radius: 14px; + background: var(--primary-light); + display: flex; + align-items: center; justify-content: center; + margin-bottom: 1rem; + color: var(--primary); +} +.empty-state h3 { + margin: 0 0 0.25rem; + color: var(--text-primary); + font-size: 0.95rem; + font-weight: 600; +} +.empty-state p { + margin: 0 0 1rem; + font-size: 0.8125rem; + max-width: 320px; + line-height: 1.5; +} +.empty-state .btn-empty-action { + padding: 0.45rem 1rem; + background: var(--primary); + color: #fff; + border: none; + border-radius: var(--radius-sm); + font-weight: 500; + font-size: 0.8125rem; + cursor: pointer; + transition: background 0.15s ease; +} +.empty-state .btn-empty-action:hover { background: var(--primary-hover); } diff --git a/src/styles/clients.css b/src/styles/clients.css new file mode 100644 index 0000000..e69de29 diff --git a/src/styles/create-invoice.css b/src/styles/create-invoice.css new file mode 100644 index 0000000..d9bb289 --- /dev/null +++ b/src/styles/create-invoice.css @@ -0,0 +1,401 @@ +/* ===================== CREATE INVOICE PAGE ===================== */ +.create-invoice-page { + padding: 2rem; + max-width: 960px; + margin: 0 auto; + min-height: 100vh; +} + +.invoice-header-compact { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1.5rem; + flex-shrink: 0; +} + +.invoice-header-compact h1 { + margin: 0; + font-size: 1.375rem; + color: var(--text-primary); + font-weight: 600; + letter-spacing: -0.02em; +} + +.btn-back { + background: transparent; + color: var(--text-secondary); + border: 1px solid var(--border-color); + padding: 0.45rem 0.875rem; + border-radius: var(--radius-sm); + cursor: pointer; + font-weight: 500; + font-size: 0.8125rem; + transition: all 0.15s ease; +} + +.btn-back:hover { + background: #f8fafc; + color: var(--text-primary); + border-color: #cbd5e1; +} + +.invoice-form-compact { + background: var(--card-bg); + border-radius: var(--radius-md); + border: 1px solid var(--border-color); + padding: 1.75rem; + box-shadow: var(--shadow-xs); +} + +.form-grid-compact { + display: grid; + grid-template-columns: 2fr 1fr 1fr; + gap: 1rem; + margin-bottom: 1.5rem; + flex-shrink: 0; +} + +.notes-grid-compact { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 1rem; + margin-bottom: 1.5rem; +} + +.form-field-compact { + display: flex; + flex-direction: column; +} + +.form-field-compact.full-width { + grid-column: 1 / -1; +} + +.form-field-compact label { + font-weight: 500; + margin-bottom: 0.375rem; + color: var(--text-secondary); + font-size: 0.8125rem; +} + +.form-field-compact input, +.form-field-compact select, +.form-field-compact textarea { + padding: 0.5rem 0.75rem; + border: 1px solid var(--border-color); + border-radius: var(--radius-sm); + font-size: 0.875rem; + color: var(--text-primary); + background: #ffffff; + resize: vertical; + min-height: 36px; + font-family: inherit; + transition: border-color 0.15s ease, box-shadow 0.15s ease; +} + +.form-field-compact input:focus, +.form-field-compact select:focus, +.form-field-compact textarea:focus { + outline: none; + border-color: var(--primary); + box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.08); +} + +/* Date input wrapper */ +.date-input-wrapper { + position: relative; + display: flex; + align-items: stretch; +} + +.date-input-wrapper input[type="date"] { + flex: 1; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + border-right: none; +} + +.date-input-wrapper input[type="date"]:focus { + z-index: 1; +} + +.date-picker-btn { + display: flex; + align-items: center; + justify-content: center; + padding: 0 0.625rem; + background: var(--primary); + color: white; + border: 1px solid var(--primary); + border-top-right-radius: var(--radius-sm); + border-bottom-right-radius: var(--radius-sm); + cursor: pointer; + transition: background 0.15s; +} + +.date-picker-btn:hover { + background: var(--primary-hover); +} + +/* Lines section */ +.lines-section-compact { + flex: 1; + display: flex; + flex-direction: column; + overflow: hidden; + margin-bottom: 1.5rem; +} + +.lines-header-compact { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 0.75rem; + flex-shrink: 0; +} + +.lines-header-compact h3 { + margin: 0; + font-size: 0.875rem; + color: var(--text-primary); + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.03em; +} + +.btn-add-compact { + background: #f8fafc; + color: var(--text-primary); + border: 1px solid var(--border-color); + padding: 0.4rem 0.875rem; + border-radius: var(--radius-sm); + cursor: pointer; + font-weight: 500; + font-size: 0.8125rem; + transition: all 0.15s; +} + +.btn-add-compact:hover { + background: #f1f5f9; + border-color: #cbd5e1; +} + +.lines-table-compact { + flex: 1; + overflow-y: auto; + display: flex; + flex-direction: column; + gap: 0.375rem; +} + +/* Column headers */ +.lines-columns-header { + display: grid; + grid-template-columns: 4fr 0.8fr 1.2fr 0.8fr 1.2fr 40px; + gap: 0.75rem; + padding: 0.5rem 0.75rem; + font-size: 0.7rem; + font-weight: 600; + color: var(--text-secondary); + text-transform: uppercase; + letter-spacing: 0.04em; + border-bottom: 1px solid var(--border-color); + margin-bottom: 0.25rem; +} + +.line-row-compact { + display: grid; + grid-template-columns: 4fr 0.8fr 1.2fr 0.8fr 1.2fr 40px; + gap: 0.75rem; + align-items: center; + background: #f8fafc; + border: 1px solid var(--border-color); + border-radius: var(--radius-sm); + padding: 0.625rem 0.75rem; + transition: border-color 0.15s ease; +} + +.line-row-compact:hover { + border-color: #cbd5e1; +} + +.line-label-mobile { display: none; } +.line-field { display: flex; flex-direction: column; } + +.line-desc-compact, +.line-qty-compact, +.line-price-compact, +.line-tax-compact { + padding: 0.4rem 0.5rem; + border: 1px solid var(--border-color); + border-radius: 4px; + font-size: 0.8125rem; + background: white; + color: var(--text-primary); + transition: border-color 0.15s ease; +} + +.line-desc-compact { width: 100%; } + +.line-desc-compact:focus, +.line-qty-compact:focus, +.line-price-compact:focus, +.line-tax-compact:focus { + outline: none; + border-color: var(--primary); + box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.08); +} + +.line-total-compact { + font-weight: 600; + color: var(--primary); + font-size: 0.875rem; + text-align: right; + padding: 0.4rem 0.25rem; +} + +.btn-delete-compact { + background: transparent; + color: var(--text-tertiary); + border: 1px solid transparent; + width: 32px; + height: 32px; + border-radius: var(--radius-sm); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.15s; + flex-shrink: 0; +} + +.btn-delete-compact:hover { + color: #ef4444; + background: #fee2e2; +} + +/* Grand total */ +.invoice-grand-total { + display: flex; + flex-direction: column; + gap: 0.4rem; + margin-top: 0.75rem; + padding: 0.875rem 1rem; + background: #f8fafc; + border: 1px solid var(--border-color); + border-radius: var(--radius-sm); + max-width: 280px; + margin-left: auto; +} + +.grand-total-row { + display: flex; + justify-content: space-between; + align-items: center; + font-size: 0.8125rem; + color: var(--text-secondary); +} + +.grand-total-row strong { + color: var(--text-primary); + font-weight: 600; +} + +.grand-total-final { + padding-top: 0.4rem; + border-top: 1px solid var(--border-color); + font-size: 0.9375rem; +} + +.grand-total-final strong { + color: var(--primary); + font-size: 1rem; + font-weight: 700; +} + +/* Form actions */ +.form-actions-compact { + display: flex; + justify-content: flex-end; + gap: 0.625rem; + margin-top: 0; + padding-top: 1.25rem; + border-top: 1px solid var(--border-color); + flex-shrink: 0; +} + +.btn-cancel-compact { + background: transparent; + color: var(--text-secondary); + border: 1px solid var(--border-color); + padding: 0.5rem 1rem; + border-radius: var(--radius-sm); + cursor: pointer; + font-weight: 500; + font-size: 0.8125rem; + transition: all 0.15s; +} + +.btn-cancel-compact:hover { + background: #f8fafc; + color: var(--text-primary); +} + +.btn-submit-compact { + background: var(--primary); + color: white; + border: none; + padding: 0.5rem 1.25rem; + border-radius: var(--radius-sm); + cursor: pointer; + font-weight: 500; + font-size: 0.8125rem; + transition: background 0.15s; +} + +.btn-submit-compact:hover { + background: var(--primary-hover); +} + +.btn-submit-compact:disabled { + background: #e2e8f0; + color: #94a3b8; + cursor: not-allowed; +} + +/* Responsive */ +@media (max-width: 768px) { + .create-invoice-page { + padding: 0.5rem; + height: calc(100vh - 1rem); + } + + .form-grid-compact { + grid-template-columns: 1fr; + gap: 0.5rem; + } + + .form-field-compact.full-width { grid-column: 1; } + .lines-columns-header { display: none; } + + .line-row-compact { + grid-template-columns: 1fr 1fr; + gap: 0.5rem; + padding: 0.625rem; + } + + .line-label-mobile { + display: block; + font-size: 0.65rem; + font-weight: 600; + color: var(--text-secondary); + text-transform: uppercase; + letter-spacing: 0.04em; + margin-bottom: 0.15rem; + } + + .line-field-desc { grid-column: 1 / -1; } + .line-field-actions { grid-column: 2; justify-self: end; } + .invoice-grand-total { max-width: 100%; } +} diff --git a/src/styles/dashboard.css b/src/styles/dashboard.css new file mode 100644 index 0000000..8a89196 --- /dev/null +++ b/src/styles/dashboard.css @@ -0,0 +1,195 @@ +/* ===================== DASHBOARD STYLES ===================== */ +.dashboard { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; +} + +.dashboard-header { + display: flex; + justify-content: space-between; + align-items: flex-start; + margin-bottom: 1.75rem; +} + +.dashboard-header h1 { + font-size: 1.5rem; + margin: 0; + color: var(--text-primary); + font-weight: 600; + letter-spacing: -0.02em; +} + +.dashboard-subtitle { + margin: 0.2rem 0 0; + color: var(--text-secondary); + font-size: 0.875rem; +} + +/* Stats */ +.dashboard-stats { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 1rem; + margin-bottom: 1.75rem; +} + +.stat-card { + background: var(--card-bg); + border-radius: var(--radius-md); + padding: 1.25rem; + display: flex; + align-items: center; + gap: 0.875rem; + border: 1px solid var(--border-color); + box-shadow: var(--shadow-xs); + transition: box-shadow 0.15s ease; +} + +.stat-card:hover { + box-shadow: var(--shadow-sm); +} + +.stat-icon { + width: 42px; + height: 42px; + border-radius: var(--radius-md); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; +} + +.stat-icon-invoices { + background: rgba(37, 99, 235, 0.08); + color: #2563eb; +} + +.stat-icon-paid { + background: rgba(22, 163, 74, 0.08); + color: #16a34a; +} + +.stat-icon-unpaid { + background: rgba(202, 138, 4, 0.08); + color: #ca8a04; +} + +.stat-icon-clients { + background: rgba(99, 102, 241, 0.08); + color: #6366f1; +} + +.stat-info { + display: flex; + flex-direction: column; +} + +.stat-value { + font-size: 1.375rem; + font-weight: 700; + color: var(--text-primary); + line-height: 1.2; + letter-spacing: -0.02em; +} + +.stat-label { + font-size: 0.78rem; + color: var(--text-secondary); + margin-top: 0.1rem; +} + +/* Dashboard grid */ +.dashboard-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); + gap: 1rem; +} + +.dashboard-card { + background: var(--card-bg); + border-radius: var(--radius-md); + padding: 1.25rem; + border: 1px solid var(--border-color); + box-shadow: var(--shadow-xs); +} + +.dashboard-card h3 { + margin: 0 0 1rem; + font-size: 0.875rem; + font-weight: 600; + color: var(--text-primary); + text-transform: uppercase; + letter-spacing: 0.03em; +} + +/* Quick actions */ +.quick-actions { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.quick-action-btn { + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0.625rem 1rem; + border-radius: var(--radius-sm); + font-size: 0.8125rem; + font-weight: 500; + text-decoration: none; + transition: background-color 0.15s ease; + cursor: pointer; + background: var(--primary); + color: #fff; +} + +.quick-action-btn:hover { + background: var(--primary-hover); + color: #fff; +} + +.quick-action-btn.secondary { + background: var(--primary-subtle); + color: var(--primary); +} + +.quick-action-btn.secondary:hover { + background: rgba(37, 99, 235, 0.12); + color: var(--primary); +} + +/* Dashboard info */ +.dashboard-info-list { + display: flex; + flex-direction: column; +} + +.dashboard-info-row { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0.55rem 0; + border-bottom: 1px solid var(--border-subtle); + font-size: 0.8125rem; +} + +.dashboard-info-row:last-child { + border-bottom: none; +} + +.dashboard-info-row span:first-child { + color: var(--text-secondary); +} + +.dashboard-info-value { + color: var(--text-primary); + font-weight: 600; +} + +/* Stat skeleton */ +.stat-card .skeleton-value { + width: 50px; + height: 24px; +} diff --git a/src/styles/facturas.css b/src/styles/facturas.css new file mode 100644 index 0000000..e69de29 diff --git a/src/styles/login.css b/src/styles/login.css new file mode 100644 index 0000000..e69de29 diff --git a/src/styles/sidebar.css b/src/styles/sidebar.css new file mode 100644 index 0000000..e69de29