Adds employee work schedule component
Introduces a new work schedule feature for managing employee shifts and schedules Implements interactive schedule view with: - Week-based schedule grid - Shift status tracking (work, vacation, sick, off) - Editable time ranges - Repeat shift functionality Enhances employee management with dynamic scheduling capabilities
This commit is contained in:
parent
d5a803ba80
commit
3214cbdc16
11 changed files with 1669 additions and 0 deletions
|
|
@ -879,6 +879,531 @@ swp-data-row.focus-highlight {
|
|||
}
|
||||
}
|
||||
|
||||
/* ===========================================
|
||||
WORK SCHEDULE TABLE
|
||||
=========================================== */
|
||||
swp-schedule-table {
|
||||
display: grid;
|
||||
grid-template-columns: 180px repeat(7, minmax(100px, 1fr));
|
||||
border-radius: var(--radius-md);
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--color-border);
|
||||
background: var(--color-surface);
|
||||
}
|
||||
|
||||
swp-schedule-cell {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: 12px 16px;
|
||||
min-height: 60px;
|
||||
background: var(--color-surface);
|
||||
border-right: 1px solid var(--color-border);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* Last column: no right border */
|
||||
swp-schedule-cell:nth-child(8n) {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
/* Last row: no bottom border */
|
||||
swp-schedule-cell:nth-last-child(-n+8) {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
swp-schedule-cell.header {
|
||||
background: var(--color-background-alt);
|
||||
font-weight: var(--font-weight-medium);
|
||||
font-size: 13px;
|
||||
color: var(--color-text-secondary);
|
||||
min-height: 48px;
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
swp-schedule-cell.header.week-number {
|
||||
font-size: 15px;
|
||||
font-weight: var(--font-weight-semibold);
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
swp-schedule-cell.header.closed {
|
||||
background: color-mix(in srgb, #f59e0b 10%, var(--color-background-alt));
|
||||
border-top: 2px solid #f59e0b;
|
||||
border-left: 2px solid #f59e0b;
|
||||
border-right: 2px solid #f59e0b;
|
||||
border-bottom: none;
|
||||
|
||||
swp-day-name {
|
||||
color: #d97706;
|
||||
}
|
||||
}
|
||||
|
||||
swp-schedule-cell.employee {
|
||||
align-items: flex-start;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
swp-schedule-cell.day {
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
swp-schedule-cell.day.closed-day {
|
||||
background: color-mix(in srgb, #f59e0b 6%, var(--color-surface));
|
||||
border-left: 2px solid #f59e0b;
|
||||
border-right: 2px solid #f59e0b;
|
||||
|
||||
swp-time-display {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
/* Last cell in closed column gets bottom border */
|
||||
swp-schedule-cell.day.closed-day:nth-last-child(-n+8) {
|
||||
border-bottom: 2px solid #f59e0b;
|
||||
}
|
||||
|
||||
/* Schedule employee info */
|
||||
swp-schedule-cell swp-employee-name {
|
||||
font-size: var(--font-size-sm);
|
||||
font-weight: var(--font-weight-medium);
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
swp-schedule-cell swp-employee-hours {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 12px;
|
||||
color: var(--color-text-muted);
|
||||
}
|
||||
|
||||
/* Day header */
|
||||
swp-day-name {
|
||||
font-weight: var(--font-weight-medium);
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
swp-day-date {
|
||||
font-size: 12px;
|
||||
color: var(--color-text-muted);
|
||||
font-weight: var(--font-weight-normal);
|
||||
}
|
||||
|
||||
/* Time display variants */
|
||||
swp-time-display {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 12px;
|
||||
font-weight: var(--font-weight-medium);
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
background: var(--bg-teal-light);
|
||||
color: var(--color-text);
|
||||
white-space: nowrap;
|
||||
min-width: 90px;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
swp-time-display.off {
|
||||
background: transparent;
|
||||
color: var(--color-text-muted);
|
||||
}
|
||||
|
||||
swp-time-display.off.off-override {
|
||||
background: color-mix(in srgb, #7c3aed 12%, white);
|
||||
color: #6d28d9;
|
||||
}
|
||||
|
||||
swp-time-display.vacation {
|
||||
background: color-mix(in srgb, #f59e0b 15%, white);
|
||||
color: #b45309;
|
||||
}
|
||||
|
||||
swp-time-display.sick {
|
||||
background: color-mix(in srgb, #ef4444 15%, white);
|
||||
color: #dc2626;
|
||||
}
|
||||
|
||||
/* Edit mode */
|
||||
body.schedule-edit-mode swp-schedule-cell.day {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
body.schedule-edit-mode swp-schedule-cell.day:hover {
|
||||
background: var(--color-background-alt);
|
||||
}
|
||||
|
||||
body.schedule-edit-mode swp-schedule-cell.day.selected {
|
||||
background: color-mix(in srgb, var(--color-teal) 12%, white);
|
||||
border: 2px solid var(--color-teal);
|
||||
margin: -1px;
|
||||
padding: 11px 15px;
|
||||
}
|
||||
|
||||
body.schedule-edit-mode swp-schedule-cell.header:not(.week-number) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
body.schedule-edit-mode swp-schedule-cell.header:not(.week-number):hover {
|
||||
background: var(--color-border);
|
||||
}
|
||||
|
||||
/* Status options in drawer */
|
||||
swp-status-options {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
swp-status-option {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 4px 10px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: all var(--transition-fast);
|
||||
font-size: 13px;
|
||||
font-weight: var(--font-weight-medium);
|
||||
background: var(--color-background-alt);
|
||||
color: var(--color-text-secondary);
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
&[data-status="work"] {
|
||||
--status-color: var(--color-teal);
|
||||
}
|
||||
&[data-status="off"] {
|
||||
--status-color: #7c3aed;
|
||||
}
|
||||
&[data-status="vacation"] {
|
||||
--status-color: #f59e0b;
|
||||
}
|
||||
&[data-status="sick"] {
|
||||
--status-color: #e53935;
|
||||
}
|
||||
|
||||
&::before {
|
||||
background: var(--status-color);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--color-border);
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background: color-mix(in srgb, var(--status-color) 15%, white);
|
||||
color: var(--status-color);
|
||||
}
|
||||
}
|
||||
|
||||
/* Time range slider */
|
||||
swp-time-range {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
swp-time-range-slider {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
height: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
swp-time-range-track {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
background: var(--color-border);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
swp-time-range-fill {
|
||||
position: absolute;
|
||||
height: 4px;
|
||||
background: var(--color-teal);
|
||||
border-radius: 2px;
|
||||
cursor: grab;
|
||||
|
||||
&:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
}
|
||||
|
||||
swp-time-range-slider input[type="range"] {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
background: transparent;
|
||||
pointer-events: none;
|
||||
margin: 0;
|
||||
|
||||
&::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
background: var(--color-teal);
|
||||
border: 2px solid white;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
pointer-events: auto;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
&::-moz-range-thumb {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
background: var(--color-teal);
|
||||
border: 2px solid white;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
pointer-events: auto;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.2);
|
||||
}
|
||||
}
|
||||
|
||||
swp-time-range-label {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
min-width: 100px;
|
||||
text-align: center;
|
||||
background: var(--color-background-alt);
|
||||
padding: 6px 12px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
swp-time-range-times {
|
||||
font-size: 13px;
|
||||
font-family: var(--font-mono);
|
||||
font-weight: var(--font-weight-medium);
|
||||
color: var(--color-text);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
swp-time-range-duration {
|
||||
font-size: 11px;
|
||||
font-family: var(--font-mono);
|
||||
color: var(--color-text-secondary);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Toggle options (Enkelt/Gentagelse) */
|
||||
swp-toggle-options {
|
||||
display: flex;
|
||||
gap: 0;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-sm);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
swp-toggle-option {
|
||||
flex: 1;
|
||||
padding: 10px 16px;
|
||||
text-align: center;
|
||||
font-size: var(--font-size-sm);
|
||||
cursor: pointer;
|
||||
background: var(--color-surface);
|
||||
border-right: 1px solid var(--color-border);
|
||||
transition: all var(--transition-fast);
|
||||
|
||||
&:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--color-background-alt);
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background: var(--color-teal);
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
/* Schedule drawer employee display */
|
||||
swp-employee-display {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
|
||||
swp-employee-avatar {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, var(--color-teal) 0%, #00695c 100%);
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: var(--font-weight-semibold);
|
||||
font-size: 12px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
&.empty swp-employee-avatar {
|
||||
background: var(--color-border);
|
||||
color: var(--color-text-muted);
|
||||
}
|
||||
|
||||
&.multi swp-employee-avatar {
|
||||
background: var(--color-text-muted);
|
||||
}
|
||||
}
|
||||
|
||||
/* ===========================================
|
||||
SCHEDULE DRAWER (matches POC exactly)
|
||||
=========================================== */
|
||||
|
||||
/* Drawer header with background */
|
||||
#schedule-drawer swp-drawer-header {
|
||||
background: var(--color-background-alt);
|
||||
padding: 20px 24px;
|
||||
}
|
||||
|
||||
#schedule-drawer swp-drawer-title {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
/* Drawer body/content */
|
||||
#schedule-drawer swp-drawer-body {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
/* Form row layout */
|
||||
#schedule-drawer swp-form-row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
/* Form labels - uppercase style from POC */
|
||||
#schedule-drawer swp-form-label {
|
||||
font-size: 11px;
|
||||
font-weight: 400;
|
||||
color: var(--color-text-secondary);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
|
||||
.optional,
|
||||
.auto {
|
||||
font-weight: 400;
|
||||
text-transform: none;
|
||||
color: var(--color-text-muted);
|
||||
}
|
||||
}
|
||||
|
||||
/* Form value (read-only display) */
|
||||
#schedule-drawer swp-form-value {
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
/* Form divider */
|
||||
#schedule-drawer swp-form-divider {
|
||||
display: block;
|
||||
height: 1px;
|
||||
background: var(--color-border);
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
/* Form hint text */
|
||||
#schedule-drawer swp-form-hint {
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
color: var(--color-text-muted);
|
||||
margin: -8px 0 16px 0;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
/* Form group - gray card background from POC */
|
||||
#schedule-drawer swp-form-group {
|
||||
display: block;
|
||||
padding: 16px;
|
||||
background: var(--color-background-alt);
|
||||
border-radius: 8px;
|
||||
margin-top: 16px;
|
||||
|
||||
swp-form-row:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Form select wrapper */
|
||||
#schedule-drawer swp-form-select {
|
||||
display: block;
|
||||
|
||||
select {
|
||||
width: 100%;
|
||||
padding: 10px 12px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
font-family: var(--font-family);
|
||||
color: var(--color-text);
|
||||
background: var(--color-surface);
|
||||
cursor: pointer;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: var(--color-teal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Text inputs in drawer */
|
||||
#schedule-drawer input[type="text"],
|
||||
#schedule-drawer input[type="date"] {
|
||||
width: 100%;
|
||||
padding: 10px 12px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
font-family: var(--font-family);
|
||||
color: var(--color-text);
|
||||
background: var(--color-surface);
|
||||
|
||||
&::placeholder {
|
||||
color: var(--color-text-muted);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: var(--color-teal);
|
||||
}
|
||||
}
|
||||
|
||||
/* Drawer footer with background */
|
||||
#schedule-drawer swp-drawer-footer {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
padding: 20px 24px;
|
||||
border-top: 1px solid var(--color-border);
|
||||
background: var(--color-background-alt);
|
||||
|
||||
swp-btn {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* ===========================================
|
||||
RESPONSIVE
|
||||
=========================================== */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue