diff --git a/src/admin/AdminApp.tsx b/src/admin/AdminApp.tsx index d1dc9ec..cb4c629 100644 --- a/src/admin/AdminApp.tsx +++ b/src/admin/AdminApp.tsx @@ -14,7 +14,6 @@ import Dashboard from "./pages/Dashboard"; import "./variables.css"; import "./base.css"; import "./attendance.css"; -import "./plan.css"; import "./offers.css"; const Users = lazy(() => import("./pages/Users")); diff --git a/src/admin/attendance.css b/src/admin/attendance.css index a60a5e4..b04edd4 100644 --- a/src/admin/attendance.css +++ b/src/admin/attendance.css @@ -1,387 +1,7 @@ /* ============================================================================ - Attendance Module + Attendance Module — Leaflet map (Location page) ============================================================================ */ -/* Layout */ -.attendance-layout { - display: flex; - flex-direction: column; - gap: 1.5rem; -} - -@media (min-width: 1024px) { - .attendance-layout { - flex-direction: row; - align-items: flex-start; - } -} - -.attendance-main { - flex: 1; - min-width: 0; -} - -.attendance-sidebar { - display: flex; - flex-direction: column; - gap: 1rem; -} - -@media (min-width: 1024px) { - .attendance-sidebar { - width: 320px; - flex-shrink: 0; - } -} - -/* Clock Card */ -.attendance-clock-card { - background: var(--glass-bg); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); - border: 1px solid var(--glass-border); - box-shadow: var(--glass-shadow); - border-radius: var(--border-radius); - padding: 2rem; -} - -.attendance-clock-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 2rem; - padding-bottom: 1.5rem; - border-bottom: 1px solid var(--border-color); -} - -.attendance-clock-status { - display: flex; - align-items: center; - gap: 0.5rem; - font-size: 1rem; - font-weight: 500; - color: var(--text-secondary); -} - -.attendance-status-dot { - width: 10px; - height: 10px; - border-radius: 50%; - background: var(--text-muted); -} - -.attendance-status-dot.active { - background: var(--success); - box-shadow: 0 0 8px color-mix(in srgb, var(--success) 50%, transparent); - animation: pulse 2s ease-in-out infinite; -} - -.attendance-clock-time { - font-size: 2.5rem; - font-weight: 700; - color: var(--text-primary); - font-family: var(--font-heading); -} - -/* Shift Info */ -.attendance-shift-info { - margin-bottom: 2rem; -} - -.attendance-shift-row { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 1rem; -} - -@media (max-width: 640px) { - .attendance-shift-row { - grid-template-columns: 1fr; - gap: 0.75rem; - } -} - -.attendance-shift-item { - text-align: center; - padding: 1rem; - background: var(--bg-tertiary); - border-radius: var(--border-radius-sm); -} - -.attendance-shift-label { - display: block; - font-size: 0.75rem; - text-transform: uppercase; - letter-spacing: 0.05em; - color: var(--text-muted); - margin-bottom: 0.5rem; -} - -.attendance-shift-value { - display: block; - font-size: 1.25rem; - font-weight: 600; - color: var(--text-secondary); -} - -.attendance-shift-value.success { - color: var(--success); -} - -/* Clock Actions */ -.attendance-clock-actions { - display: flex; - flex-direction: column; - gap: 0.75rem; -} - -/* Notes */ -.attendance-notes { - margin-top: 1.5rem; - padding-top: 1rem; - border-top: 1px solid var(--border-color); -} - -.attendance-notes-label { - display: block; - font-size: 0.875rem; - font-weight: 500; - color: var(--text-secondary); - margin-bottom: 0.5rem; -} - -/* Project Section */ -.attendance-project-section { - margin-bottom: 1.5rem; - padding: 1rem; - background: var(--bg-tertiary); - border-radius: var(--border-radius-sm); -} - -.attendance-project-header { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: 0.75rem; -} - -.attendance-project-header .attendance-shift-label { - margin-bottom: 0; -} - -.attendance-project-section .admin-form-select { - margin-bottom: 0; -} - -.attendance-project-logs { - margin-top: 0.75rem; - padding-top: 0.75rem; - border-top: 1px solid var(--border-color); - display: flex; - flex-direction: column; - gap: 0.375rem; -} - -.attendance-project-log-item { - display: flex; - align-items: center; - gap: 0.5rem; - font-size: 0.8125rem; - padding: 0.375rem 0.5rem; - background: var(--bg-secondary); - border-radius: var(--border-radius-sm); -} - -.attendance-project-log-name { - font-weight: 500; - color: var(--text-primary); - flex: 1; - min-width: 0; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.attendance-project-log-time { - color: var(--text-muted); - white-space: nowrap; - font-size: 0.75rem; -} - -.attendance-project-log-duration { - color: var(--text-secondary); - font-weight: 600; - white-space: nowrap; - font-variant-numeric: tabular-nums; -} - -/* Balance Card */ -.attendance-balance-card { - background: var(--gradient); - border-radius: var(--border-radius); - padding: 1.5rem; - color: #fff; -} - -.attendance-balance-title { - font-size: 0.875rem; - font-weight: 500; - opacity: 0.9; - margin-bottom: 0.75rem; - color: inherit; -} - -.attendance-balance-value { - display: flex; - align-items: baseline; - gap: 0.5rem; - margin-bottom: 1rem; -} - -.attendance-balance-number { - font-size: 3rem; - font-weight: 700; - line-height: 1; - color: inherit; -} - -.attendance-balance-unit { - font-size: 1rem; - opacity: 0.9; -} - -.attendance-balance-detail { - display: flex; - justify-content: space-between; - font-size: 0.8125rem; - opacity: 0.8; - margin-bottom: 0.75rem; -} - -.attendance-balance-bar { - height: 6px; - background: rgba(255, 255, 255, 0.2); - border-radius: 3px; - overflow: hidden; -} - -.attendance-balance-progress { - height: 100%; - background: rgba(255, 255, 255, 0.9); - border-radius: 3px; - transition: width 0.3s ease; -} - -/* Quick Links */ -.attendance-quick-links { - background: var(--glass-bg); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); - border: 1px solid var(--glass-border); - box-shadow: var(--glass-shadow); - border-radius: var(--border-radius); - padding: 1rem; -} - -.attendance-quick-title { - font-size: 0.75rem; - text-transform: uppercase; - letter-spacing: 0.05em; - color: var(--text-muted); - margin-bottom: 0.75rem; -} - -.attendance-quick-link { - display: flex; - align-items: center; - gap: 0.75rem; - padding: 0.75rem; - margin: -0.25rem -0.5rem; - border-radius: var(--border-radius-sm); - color: var(--text-secondary); - text-decoration: none; - transition: var(--transition); -} - -.attendance-quick-link:hover { - background: var(--bg-tertiary); - color: var(--text-primary); -} - -.attendance-quick-link span { - flex: 1; -} - -.attendance-quick-link svg:last-child { - opacity: 0.5; -} - -/* Leave Type Badges */ -.attendance-leave-badge { - display: inline-flex; - align-items: center; - justify-content: center; - padding: 0.25rem 0.55rem; - border-radius: var(--border-radius-sm); - font-size: 0.75rem; - font-weight: 500; - line-height: 1.2; - background: var(--bg-tertiary); - color: var(--text-secondary); -} - -.attendance-leave-badge.badge-vacation { - background: color-mix(in srgb, var(--info) 15%, transparent); - color: var(--info); -} - -.attendance-leave-badge.badge-sick { - background: color-mix(in srgb, var(--danger) 15%, transparent); - color: var(--danger); -} - -.attendance-leave-badge.badge-holiday { - background: color-mix(in srgb, var(--success) 15%, transparent); - color: var(--success); -} - -.attendance-leave-badge.badge-unpaid { - background: var(--muted-light); - color: var(--muted); -} - -/* Working Status Badge */ -.attendance-working-badge { - display: inline-flex; - align-items: center; - justify-content: center; - width: 20px; - height: 20px; - border-radius: 50%; - font-size: 0.75rem; - font-weight: 600; -} - -.attendance-working-badge.working { - background: color-mix(in srgb, var(--success) 15%, transparent); - color: var(--success); -} - -.attendance-working-badge.finished { - background: color-mix(in srgb, var(--danger) 15%, transparent); - color: var(--danger); -} - -/* GPS Link */ -.attendance-gps-link { - text-decoration: none; - font-size: 1rem; -} - -.attendance-gps-link:hover { - transform: scale(1.1); -} - /* Location Page */ .attendance-location-map { height: 400px; @@ -392,49 +12,6 @@ z-index: 0; /* stacking context - Leaflet z-indexy zustanou uvnitr */ } -.attendance-location-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); - gap: 1rem; -} - -.attendance-location-card { - background: var(--bg-tertiary); - border: 1px solid var(--border-color); - border-radius: var(--border-radius-sm); - padding: 1rem; -} - -.attendance-location-card.empty { - opacity: 0.6; -} - -.attendance-location-title { - font-size: 1rem; - margin-bottom: 0.5rem; - color: var(--accent-color); - font-weight: 600; -} - -.attendance-location-time { - font-weight: 600; - margin-bottom: 0.5rem; - color: var(--text-primary); -} - -.attendance-location-address { - color: var(--text-secondary); - font-size: 0.9rem; - margin-bottom: 0.5rem; - line-height: 1.4; -} - -.attendance-location-coords { - font-size: 0.8rem; - color: var(--text-muted); - font-family: monospace; -} - /* ============================================================================ Mobile (responsive) ============================================================================ */ @@ -446,10 +23,3 @@ height: clamp(220px, 45vh, 400px); } } - -/* The clock card's 2rem padding crushes content at ~360px — tighten it. */ -@media (max-width: 480px) { - .attendance-clock-card { - padding: 1rem; - } -} diff --git a/src/admin/base.css b/src/admin/base.css index f8d37ab..3fe47b1 100644 --- a/src/admin/base.css +++ b/src/admin/base.css @@ -53,16 +53,6 @@ body { color 0.3s ease; } -.admin-sidebar, -.admin-header, -.admin-card, -.admin-modal { - transition: - background-color 0.3s ease, - color 0.3s ease, - border-color 0.3s ease; -} - #root { overflow-x: hidden; touch-action: pan-y pinch-zoom; @@ -230,80 +220,6 @@ img { text-align: center; } -/* Spinner variant */ -.admin-spinner-sm { - width: 16px; - height: 16px; - border-width: 2px; -} - -/* Monospace for data values (times, dates, numbers, IDs) */ -.admin-mono { - font-family: var(--font-mono); - font-size: 0.875em; - letter-spacing: -0.01em; -} - -/* Drag handle */ -.admin-drag-handle { - display: flex; - align-items: center; - justify-content: center; - width: 24px; - height: 24px; - border: none; - background: none; - color: var(--text-muted); - cursor: grab; - border-radius: 4px; - padding: 0; - transition: - color 0.15s, - background 0.15s; - touch-action: none; -} - -.admin-drag-handle:hover { - color: var(--text-primary); - background: var(--bg-secondary); -} - -.admin-drag-handle:active { - cursor: grabbing; -} - -/* Error stack (DEV only) */ -.admin-error-stack { - max-width: 600px; - max-height: 200px; - overflow: auto; - padding: 0.75rem 1rem; - margin: 0; - border-radius: var(--border-radius-sm); - background: var(--bg-tertiary); - border: 1px solid var(--border-color); - color: var(--danger); - font-family: var(--font-mono); - font-size: 11px; - line-height: 1.5; - text-align: left; - white-space: pre-wrap; - word-break: break-word; -} - -/* Keyboard shortcut badge */ -.admin-kbd { - display: inline-block; - padding: 2px 7px; - font-family: var(--font-mono); - font-size: 12px; - line-height: 1.4; - border-radius: 4px; - background: var(--bg-secondary); - border: 1px solid var(--border-color); - white-space: nowrap; -} - /* Loading & Animations */ .admin-spinner { width: 32px; @@ -314,39 +230,12 @@ img { animation: spin 0.8s linear infinite; } -.admin-loading { - display: flex; - align-items: center; - justify-content: center; - min-height: 256px; -} - @keyframes spin { to { transform: rotate(360deg); } } -@keyframes float { - 0%, - 100% { - transform: translate(0, 0); - } - 50% { - transform: translate(30px, -30px); - } -} - -@keyframes pulse { - 0%, - 100% { - opacity: 1; - } - 50% { - opacity: 0.5; - } -} - /* ── Additional Utilities ─────────────────────────────────────────── */ /* Font sizes */ diff --git a/src/admin/components/PlanCategoriesModal.tsx b/src/admin/components/PlanCategoriesModal.tsx index c0110b1..6691dab 100644 --- a/src/admin/components/PlanCategoriesModal.tsx +++ b/src/admin/components/PlanCategoriesModal.tsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useState, type ChangeEvent, type FocusEvent } from "react"; import Box from "@mui/material/Box"; import { Modal, TextField, Button } from "../ui"; import { useApiMutation } from "../lib/queries/mutations"; @@ -100,6 +100,19 @@ export default function PlanCategoriesModal({ py: 1, } as const; + // Native color picker, styled to match the row (was the .plan-cat-color rule). + const colorInputSx = { + width: 34, + height: 34, + p: 0, + border: 1, + borderColor: "divider", + borderRadius: "6px", + background: "none", + cursor: "pointer", + flex: "0 0 auto", + } as const; + return ( {categories.map((c) => ( - { + onBlur={(e: FocusEvent) => { if (e.target.value !== c.color) { patch(c.id, { color: e.target.value }); } @@ -190,12 +204,15 @@ export default function PlanCategoriesModal({ - setNewColor(e.target.value)} + onChange={(e: ChangeEvent) => + setNewColor(e.target.value) + } aria-label="Barva nové kategorie" />