refactor(css): delete dead pre-MUI CSS and eliminate plan.css
Phase 1 of the "fully MUI" CSS cleanup. - base.css 429->317: drop dead .admin-sidebar/header/card/modal, .admin-drag-handle/-kbd/-mono/-error-stack/-loading and the unused float/pulse keyframes. Keep reset, typography, scrollbar, ::view-transition cross-fade, the live .admin-spinner (App.tsx pre-React loader) and all utility classes. - attendance.css 456->24: keep only the Leaflet .attendance-location-map rules; the old hand-rolled Attendance page is MUI now. - offers.css 642->417: keep only the Quill (.admin-rich-editor/.ql-*) and .admin-rich-text-view rules; drop the dead offers table / filter / lang-badge / row-state rules. - plan.css deleted: the grid already lives in PlanGrid's styled() wrapper; the last consumer (.plan-cat-color) is now an sx-styled Box input in PlanCategoriesModal. tsc -b --noEmit and npm run build both clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -14,7 +14,6 @@ import Dashboard from "./pages/Dashboard";
|
|||||||
import "./variables.css";
|
import "./variables.css";
|
||||||
import "./base.css";
|
import "./base.css";
|
||||||
import "./attendance.css";
|
import "./attendance.css";
|
||||||
import "./plan.css";
|
|
||||||
import "./offers.css";
|
import "./offers.css";
|
||||||
|
|
||||||
const Users = lazy(() => import("./pages/Users"));
|
const Users = lazy(() => import("./pages/Users"));
|
||||||
|
|||||||
@@ -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 */
|
/* Location Page */
|
||||||
.attendance-location-map {
|
.attendance-location-map {
|
||||||
height: 400px;
|
height: 400px;
|
||||||
@@ -392,49 +12,6 @@
|
|||||||
z-index: 0; /* stacking context - Leaflet z-indexy zustanou uvnitr */
|
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)
|
Mobile (responsive)
|
||||||
============================================================================ */
|
============================================================================ */
|
||||||
@@ -446,10 +23,3 @@
|
|||||||
height: clamp(220px, 45vh, 400px);
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -53,16 +53,6 @@ body {
|
|||||||
color 0.3s ease;
|
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 {
|
#root {
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
touch-action: pan-y pinch-zoom;
|
touch-action: pan-y pinch-zoom;
|
||||||
@@ -230,80 +220,6 @@ img {
|
|||||||
text-align: center;
|
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 */
|
/* Loading & Animations */
|
||||||
.admin-spinner {
|
.admin-spinner {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
@@ -314,39 +230,12 @@ img {
|
|||||||
animation: spin 0.8s linear infinite;
|
animation: spin 0.8s linear infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-loading {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
min-height: 256px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes spin {
|
@keyframes spin {
|
||||||
to {
|
to {
|
||||||
transform: rotate(360deg);
|
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 ─────────────────────────────────────────── */
|
/* ── Additional Utilities ─────────────────────────────────────────── */
|
||||||
|
|
||||||
/* Font sizes */
|
/* Font sizes */
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useState } from "react";
|
import { useState, type ChangeEvent, type FocusEvent } from "react";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
import { Modal, TextField, Button } from "../ui";
|
import { Modal, TextField, Button } from "../ui";
|
||||||
import { useApiMutation } from "../lib/queries/mutations";
|
import { useApiMutation } from "../lib/queries/mutations";
|
||||||
@@ -100,6 +100,19 @@ export default function PlanCategoriesModal({
|
|||||||
py: 1,
|
py: 1,
|
||||||
} as const;
|
} 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 (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
@@ -113,9 +126,10 @@ export default function PlanCategoriesModal({
|
|||||||
<Box>
|
<Box>
|
||||||
{categories.map((c) => (
|
{categories.map((c) => (
|
||||||
<Box key={c.id} sx={{ ...rowSx, opacity: c.is_active ? 1 : 0.55 }}>
|
<Box key={c.id} sx={{ ...rowSx, opacity: c.is_active ? 1 : 0.55 }}>
|
||||||
<input
|
<Box
|
||||||
|
component="input"
|
||||||
type="color"
|
type="color"
|
||||||
className="plan-cat-color"
|
sx={colorInputSx}
|
||||||
// Uncontrolled + patch on blur (like the rename input): the
|
// Uncontrolled + patch on blur (like the rename input): the
|
||||||
// native color picker fires onChange on every drag tick, which
|
// native color picker fires onChange on every drag tick, which
|
||||||
// would spam PATCH requests and the audit log. onBlur commits
|
// would spam PATCH requests and the audit log. onBlur commits
|
||||||
@@ -123,7 +137,7 @@ export default function PlanCategoriesModal({
|
|||||||
defaultValue={c.color}
|
defaultValue={c.color}
|
||||||
key={c.color}
|
key={c.color}
|
||||||
disabled={busy}
|
disabled={busy}
|
||||||
onBlur={(e) => {
|
onBlur={(e: FocusEvent<HTMLInputElement>) => {
|
||||||
if (e.target.value !== c.color) {
|
if (e.target.value !== c.color) {
|
||||||
patch(c.id, { color: e.target.value });
|
patch(c.id, { color: e.target.value });
|
||||||
}
|
}
|
||||||
@@ -190,12 +204,15 @@ export default function PlanCategoriesModal({
|
|||||||
<Box
|
<Box
|
||||||
sx={{ ...rowSx, mt: 1, pt: 2, borderTop: 1, borderColor: "divider" }}
|
sx={{ ...rowSx, mt: 1, pt: 2, borderTop: 1, borderColor: "divider" }}
|
||||||
>
|
>
|
||||||
<input
|
<Box
|
||||||
|
component="input"
|
||||||
type="color"
|
type="color"
|
||||||
className="plan-cat-color"
|
sx={colorInputSx}
|
||||||
value={newColor}
|
value={newColor}
|
||||||
disabled={busy}
|
disabled={busy}
|
||||||
onChange={(e) => setNewColor(e.target.value)}
|
onChange={(e: ChangeEvent<HTMLInputElement>) =>
|
||||||
|
setNewColor(e.target.value)
|
||||||
|
}
|
||||||
aria-label="Barva nové kategorie"
|
aria-label="Barva nové kategorie"
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
|
|||||||
@@ -2,74 +2,6 @@
|
|||||||
Offers Module
|
Offers Module
|
||||||
============================================ */
|
============================================ */
|
||||||
|
|
||||||
/* Items table */
|
|
||||||
.offers-items-table {
|
|
||||||
overflow-x: auto;
|
|
||||||
overflow-y: hidden;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
border: 1px solid var(--border-color);
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.offers-items-table .admin-table {
|
|
||||||
min-width: 700px;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.offers-items-table .admin-table thead th {
|
|
||||||
font-size: 11px;
|
|
||||||
font-weight: 600;
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: 0.04em;
|
|
||||||
color: var(--text-tertiary);
|
|
||||||
padding: 8px 10px;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.offers-items-table .admin-table td {
|
|
||||||
vertical-align: top;
|
|
||||||
padding: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.offers-items-table .admin-table tbody tr {
|
|
||||||
transition: background var(--transition);
|
|
||||||
}
|
|
||||||
|
|
||||||
.offers-items-table .admin-table tbody tr:hover {
|
|
||||||
background: var(--table-row-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
.offers-items-table .admin-table td .admin-form-input {
|
|
||||||
display: block;
|
|
||||||
padding: 6px 8px;
|
|
||||||
font-size: 13px;
|
|
||||||
min-height: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Language badges */
|
|
||||||
.offers-lang-badge {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
min-width: 1.5rem;
|
|
||||||
height: 1.25rem;
|
|
||||||
padding: 0 0.375rem;
|
|
||||||
border-radius: 0.25rem;
|
|
||||||
font-size: 0.625rem;
|
|
||||||
font-weight: 700;
|
|
||||||
letter-spacing: 0.03em;
|
|
||||||
text-transform: uppercase;
|
|
||||||
background: color-mix(in srgb, var(--info) 15%, transparent);
|
|
||||||
color: var(--info);
|
|
||||||
margin-right: 0.375rem;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.offers-lang-badge-cz {
|
|
||||||
background: color-mix(in srgb, var(--danger) 15%, transparent);
|
|
||||||
color: var(--danger);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* RichEditor (Quill) */
|
/* RichEditor (Quill) */
|
||||||
.admin-rich-editor {
|
.admin-rich-editor {
|
||||||
border: 1px solid var(--border-color);
|
border: 1px solid var(--border-color);
|
||||||
@@ -483,159 +415,3 @@
|
|||||||
max-width: calc(100vw - 32px);
|
max-width: calc(100vw - 32px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.offers-items-table .admin-table td .admin-form-input {
|
|
||||||
font-size: 16px;
|
|
||||||
min-height: 44px;
|
|
||||||
padding: 9px 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Give the description column more room by shrinking numeric columns */
|
|
||||||
.offers-col-qty {
|
|
||||||
width: 4rem !important;
|
|
||||||
}
|
|
||||||
.offers-col-unit {
|
|
||||||
width: 4rem !important;
|
|
||||||
}
|
|
||||||
.offers-col-price {
|
|
||||||
width: 5.5rem !important;
|
|
||||||
}
|
|
||||||
.offers-col-included {
|
|
||||||
width: 3.5rem !important;
|
|
||||||
}
|
|
||||||
.offers-col-total {
|
|
||||||
width: 5.5rem !important;
|
|
||||||
}
|
|
||||||
.offers-col-del {
|
|
||||||
width: 2.5rem !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 640px) {
|
|
||||||
.offers-items-table {
|
|
||||||
margin: 0 -1rem;
|
|
||||||
width: calc(100% + 2rem);
|
|
||||||
border-radius: 0;
|
|
||||||
border-left: none;
|
|
||||||
border-right: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.offers-items-table .admin-table {
|
|
||||||
min-width: 700px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.offers-items-table .admin-table td {
|
|
||||||
padding: 6px;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.offers-items-table .admin-table th {
|
|
||||||
font-size: 10px;
|
|
||||||
padding: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Further reduce numeric columns on very small screens */
|
|
||||||
.offers-col-qty {
|
|
||||||
width: 3.5rem !important;
|
|
||||||
}
|
|
||||||
.offers-col-unit {
|
|
||||||
width: 3.5rem !important;
|
|
||||||
}
|
|
||||||
.offers-col-price {
|
|
||||||
width: 5rem !important;
|
|
||||||
}
|
|
||||||
.offers-col-total {
|
|
||||||
width: 5rem !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Offer draft row in table */
|
|
||||||
.offers-draft-row {
|
|
||||||
background: var(--row-draft);
|
|
||||||
}
|
|
||||||
|
|
||||||
.offers-draft-row-label {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.35rem;
|
|
||||||
font-size: 0.75rem;
|
|
||||||
font-weight: 600;
|
|
||||||
letter-spacing: 0.03em;
|
|
||||||
color: var(--warning);
|
|
||||||
background: color-mix(in srgb, var(--warning) 14%, transparent);
|
|
||||||
padding: 0.2rem 0.55rem;
|
|
||||||
border-radius: 99px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Expired offer without order */
|
|
||||||
.offers-expired-row {
|
|
||||||
background: var(--row-expired);
|
|
||||||
}
|
|
||||||
|
|
||||||
.offers-expired-row td {
|
|
||||||
color: var(--danger) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.offers-expired-row a {
|
|
||||||
color: var(--danger) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Invalidated offer */
|
|
||||||
.offers-invalidated-row {
|
|
||||||
opacity: 0.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.offers-invalidated-row td {
|
|
||||||
color: var(--text-muted) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.offers-invalidated-row a {
|
|
||||||
color: var(--text-muted) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Completed offer */
|
|
||||||
.offers-completed-row {
|
|
||||||
background: var(
|
|
||||||
--row-completed,
|
|
||||||
color-mix(in srgb, var(--success) 8%, transparent)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read-only form (invalidated offer detail) */
|
|
||||||
.offers-readonly input[readonly],
|
|
||||||
.offers-readonly select:disabled {
|
|
||||||
background-color: var(--bg-secondary);
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Offer draft indicator */
|
|
||||||
/* Filters */
|
|
||||||
.admin-filters {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 1rem;
|
|
||||||
align-items: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.admin-filter-group {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 0.35rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.admin-filter-label {
|
|
||||||
font-size: 0.75rem;
|
|
||||||
font-weight: 600;
|
|
||||||
color: var(--text-tertiary);
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: 0.03em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.admin-filter-group .admin-tabs {
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.admin-filter-group .admin-form-select {
|
|
||||||
min-width: 10rem;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
/* ============================================================================
|
|
||||||
Plán prací — leftover bespoke styles.
|
|
||||||
|
|
||||||
The planner GRID is now fully MUI/theme-driven (see PlanGrid's styled()
|
|
||||||
wrapper), and the toolbar / range label / banner / day-choice modal were
|
|
||||||
migrated to MUI components. Only the category-manager modal rows remain
|
|
||||||
here; they keep a single paper-rule token for their swatch/divider borders.
|
|
||||||
============================================================================ */
|
|
||||||
|
|
||||||
:root {
|
|
||||||
--plan-paper-rule: rgba(20, 20, 24, 0.08);
|
|
||||||
}
|
|
||||||
[data-theme="dark"] {
|
|
||||||
--plan-paper-rule: rgba(255, 255, 255, 0.06);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Category manager modal rows */
|
|
||||||
.plan-cat-manager {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
.plan-cat-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
.plan-cat-row--inactive {
|
|
||||||
opacity: 0.55;
|
|
||||||
}
|
|
||||||
.plan-cat-row .admin-form-input {
|
|
||||||
flex: 1;
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
.plan-cat-color {
|
|
||||||
width: 34px;
|
|
||||||
height: 34px;
|
|
||||||
padding: 0;
|
|
||||||
border: 1px solid var(--plan-paper-rule);
|
|
||||||
border-radius: 6px;
|
|
||||||
background: none;
|
|
||||||
cursor: pointer;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
}
|
|
||||||
.plan-cat-row--new {
|
|
||||||
margin-top: 6px;
|
|
||||||
padding-top: 10px;
|
|
||||||
border-top: 1px dashed var(--plan-paper-rule);
|
|
||||||
}
|
|
||||||
/* The per-row delete trigger reads quieter than the solid danger confirm
|
|
||||||
button it turns into; keep it an outline until the user commits. */
|
|
||||||
.plan-cat-delete.admin-btn-danger {
|
|
||||||
background: transparent;
|
|
||||||
color: var(--danger);
|
|
||||||
border: 1px solid color-mix(in srgb, var(--danger) 40%, transparent);
|
|
||||||
}
|
|
||||||
.plan-cat-delete.admin-btn-danger:hover:not(:disabled) {
|
|
||||||
background: color-mix(in srgb, var(--danger) 12%, transparent);
|
|
||||||
color: var(--danger);
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user