PlanTempusApp/PlanTempus.Application/wwwroot/css/employees.css
Janus C. H. Knudsen eaae745c42 Enhances employee statistics page with rich dashboard
Refactors employee statistics view with comprehensive charts and tables
Adds detailed revenue, utilization, and booking tracking components
Introduces dynamic data loading and chart visualization for employee performance
2026-01-22 23:28:33 +01:00

956 lines
21 KiB
CSS

/**
* Employees Styles - User & Role Management
*
* Employees-specific styling only.
* Reuses: swp-stat-card (stats.css), swp-stats-row (stats.css), swp-tab-bar (tabs.css),
* swp-btn, swp-status-badge, swp-icon-btn, swp-card, swp-section-label,
* swp-add-button, swp-tags-row, swp-tag, swp-status-indicator,
* swp-fact-boxes-inline, swp-fact-inline, swp-edit-section/row/label/value/select,
* swp-detail-grid, swp-back-link (components.css),
* swp-row-toggle (cash.css),
* swp-sticky-header, swp-header-content (page.css),
* swp-toggle-slider, swp-checkbox-list (controls.css)
*
* Creates: swp-employee-table, swp-employee-row, swp-user-info,
* swp-employee-avatar-large, swp-employee-detail-header, swp-employee-status,
* swp-salary-table, swp-document-list/item/info/name/meta/actions,
* swp-subsection/title, swp-simple-list/item/text
*/
/* ===========================================
USERS HEADER
=========================================== */
swp-users-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: var(--section-gap);
}
swp-users-count {
display: flex;
align-items: center;
gap: var(--spacing-4);
font-size: var(--font-size-sm);
color: var(--color-text-secondary);
strong {
color: var(--color-text);
font-weight: var(--font-weight-semibold);
}
}
swp-users-progress {
width: 120px;
height: 6px;
background: var(--color-border);
border-radius: var(--radius-sm);
overflow: hidden;
swp-users-progress-bar {
display: block;
height: 100%;
background: var(--color-teal);
border-radius: var(--radius-sm);
transition: width var(--transition-normal);
}
}
/* ===========================================
EMPLOYEE TABLE (uses swp-data-table + swp-card from components.css)
=========================================== */
swp-card.employees-list {
padding: 0;
overflow: hidden;
}
swp-card.employees-list swp-data-table {
grid-template-columns: minmax(220px, 1fr) 120px 140px 120px 40px;
}
swp-card.employees-list swp-data-table-header,
swp-card.employees-list swp-data-table-row {
padding: 0 var(--spacing-10);
}
swp-card.employees-list swp-data-table-header swp-data-table-cell {
padding-top: var(--spacing-5);
padding-bottom: var(--spacing-5);
}
swp-card.employees-list swp-data-table-row {
cursor: pointer;
}
swp-card.employees-list swp-data-table-cell {
padding: var(--spacing-5) 0;
&:last-child {
display: flex;
align-items: center;
justify-content: center;
}
}
/* ===========================================
USER INFO (Avatar + Details)
=========================================== */
swp-user-info {
display: flex;
align-items: center;
gap: var(--spacing-3);
}
swp-user-avatar {
width: 36px;
height: 36px;
border-radius: 50%;
background: var(--color-teal);
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: var(--font-size-xs);
font-weight: var(--font-weight-semibold);
flex-shrink: 0;
&.purple { background: var(--color-purple); }
&.blue { background: var(--color-blue); }
&.amber { background: var(--color-amber); }
}
swp-user-details {
min-width: 0;
}
swp-user-name {
display: block;
font-size: var(--font-size-base);
font-weight: var(--font-weight-medium);
color: var(--color-text);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
swp-user-email {
display: block;
font-size: var(--font-size-sm);
color: var(--color-text-secondary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* ===========================================
TABLE ACTIONS
=========================================== */
swp-table-actions {
display: flex;
align-items: center;
gap: var(--spacing-2);
justify-content: flex-end;
}
/* ===========================================
PERMISSIONS MATRIX
=========================================== */
swp-permissions-matrix {
display: block;
background: var(--color-surface);
border-radius: var(--radius-lg);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
overflow: hidden;
table {
width: 100%;
border-collapse: collapse;
}
th, td {
padding: var(--spacing-5) var(--spacing-6);
text-align: center;
border-bottom: 1px solid var(--color-border);
font-size: var(--font-size-base);
&:first-child {
text-align: left;
font-weight: var(--font-weight-medium);
}
}
thead th {
background: var(--color-background-alt);
font-size: var(--font-size-xs);
font-weight: var(--font-weight-semibold);
text-transform: uppercase;
letter-spacing: 0.5px;
color: var(--color-text-secondary);
}
tbody tr:last-child td {
border-bottom: none;
}
.permission-name {
display: flex;
align-items: center;
gap: var(--spacing-3);
font-size: var(--font-size-base);
color: var(--color-text);
i {
font-size: 18px;
color: var(--color-text-secondary);
}
}
.check {
color: var(--color-teal);
font-size: 20px;
}
.no-access {
color: var(--color-border);
font-size: 16px;
}
}
/* ===========================================
EMPLOYEE DETAIL VIEW
=========================================== */
swp-employee-avatar-large {
width: 80px;
height: 80px;
border-radius: 50%;
background: var(--color-teal);
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: var(--font-size-2xl);
font-weight: var(--font-weight-semibold);
flex-shrink: 0;
&.purple { background: var(--color-purple); }
&.blue { background: var(--color-blue); }
&.amber { background: var(--color-amber); }
}
swp-employee-detail-header {
display: flex;
gap: var(--spacing-12);
}
swp-employee-info {
flex: 1;
display: flex;
flex-direction: column;
gap: var(--spacing-2);
min-width: 0;
}
swp-employee-name-row {
display: flex;
align-items: center;
gap: var(--spacing-8);
}
swp-employee-name {
font-size: var(--font-size-2xl);
font-weight: var(--font-weight-semibold);
color: var(--color-text);
}
/* ===========================================
EMPLOYEE STATUS (alias for swp-status-indicator)
=========================================== */
swp-employee-status {
display: inline-flex;
align-items: center;
gap: var(--spacing-2);
padding: var(--spacing-2) var(--spacing-4);
font-size: var(--font-size-sm);
font-weight: var(--font-weight-medium);
border-radius: var(--radius-md);
cursor: pointer;
transition: all var(--transition-fast);
margin-left: auto;
&[data-active="true"] {
background: var(--bg-green-strong);
color: var(--color-green);
border: 1px solid var(--bg-green-border);
}
&[data-active="false"] {
background: var(--bg-red-medium);
color: var(--color-red);
border: 1px solid var(--border-red);
}
.icon {
font-size: var(--font-size-base);
}
}
/* ===========================================
VIEW CONTAINERS (Employee-specific)
=========================================== */
swp-employees-list-view,
swp-employee-detail-view {
transition: opacity 100ms ease;
}
swp-employees-list-view {
display: block;
}
swp-employee-detail-view {
display: none;
min-height: calc(100vh - 60px);
}
/* ===========================================
SCHEDULE GRID (Hours tab)
=========================================== */
swp-schedule-grid {
display: flex;
flex-direction: column;
}
swp-schedule-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--spacing-4) 0;
border-bottom: 1px solid var(--color-border);
&:last-child {
border-bottom: none;
}
&.off {
color: var(--color-text-secondary);
swp-schedule-time {
color: var(--color-text-secondary);
}
}
swp-schedule-day {
font-size: var(--font-size-base);
font-weight: var(--font-weight-medium);
}
swp-schedule-time {
font-size: var(--font-size-base);
font-family: var(--font-mono);
color: var(--color-teal);
}
}
/* ===========================================
SERVICE LIST (Services tab)
=========================================== */
swp-service-list {
display: flex;
flex-direction: column;
}
swp-service-item {
display: grid;
grid-template-columns: 1fr auto auto;
gap: var(--spacing-6);
align-items: center;
padding: var(--spacing-4) 0;
border-bottom: 1px solid var(--color-border);
&:last-child {
border-bottom: none;
}
swp-service-name {
font-size: var(--font-size-base);
font-weight: var(--font-weight-medium);
}
swp-service-duration {
font-size: var(--font-size-sm);
color: var(--color-text-secondary);
}
swp-service-price {
font-size: var(--font-size-base);
font-family: var(--font-mono);
color: var(--color-teal);
font-weight: var(--font-weight-medium);
}
}
/* ===========================================
DOCUMENT LIST (HR tab)
=========================================== */
swp-document-list {
display: flex;
flex-direction: column;
gap: var(--spacing-2);
}
swp-document-item {
display: flex;
align-items: center;
gap: var(--spacing-3);
padding: 12px 16px;
background: var(--color-background-alt);
border-radius: var(--radius-md);
border: 1px solid var(--color-border);
i, swp-document-icon {
font-size: 20px;
color: var(--color-text-secondary);
flex-shrink: 0;
}
i.ph-file-pdf {
color: var(--color-red);
}
swp-document-info {
flex: 1;
min-width: 0;
swp-document-name {
display: block;
font-size: var(--font-size-base);
font-weight: var(--font-weight-medium);
color: var(--color-text);
}
swp-document-meta {
display: block;
font-size: var(--font-size-sm);
color: var(--color-text-secondary);
margin-top: 2px;
}
}
swp-document-actions {
display: flex;
align-items: center;
gap: var(--spacing-2);
flex-shrink: 0;
}
}
/* ===========================================
NOTES AREA
=========================================== */
swp-notes-area {
display: block;
min-height: 100px;
padding: var(--spacing-4);
background: var(--color-background-alt);
border-radius: var(--radius-sm);
font-size: var(--font-size-base);
color: var(--color-text-secondary);
line-height: 1.6;
&:focus {
outline: none;
color: var(--color-text);
}
}
/* ===========================================
SALARY TABLE (uses swp-data-table from components.css)
=========================================== */
swp-card.salary-history swp-data-table {
grid-template-columns: 1fr 120px 60px;
}
swp-card.salary-history swp-data-table-header {
background: transparent;
border-bottom: 1px solid var(--color-border);
}
swp-card.salary-history swp-data-table-row {
cursor: pointer;
&:hover swp-data-table-cell i {
color: var(--color-teal);
}
}
swp-card.salary-history swp-data-table-cell {
padding: var(--spacing-4) var(--spacing-2);
&:first-child {
padding-left: 0;
}
&:last-child {
padding-right: 0;
text-align: right;
}
i {
color: var(--color-text-muted);
font-size: 16px;
}
}
/* ===========================================
SUBSECTION TITLE
=========================================== */
swp-subsection {
display: block;
margin-bottom: var(--spacing-6);
&:last-of-type {
margin-bottom: 0;
}
swp-subsection-title {
display: block;
font-size: var(--font-size-sm);
font-weight: var(--font-weight-semibold);
color: var(--color-text-secondary);
margin-bottom: var(--spacing-3);
}
}
/* ===========================================
SIMPLE LIST
=========================================== */
swp-simple-list {
display: flex;
flex-direction: column;
gap: var(--spacing-2);
}
swp-simple-item {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--spacing-3);
padding: 12px 16px;
background: var(--color-background-alt);
border-radius: var(--radius-md);
border: 1px solid var(--color-border);
swp-simple-item-text {
flex: 1;
font-size: var(--font-size-base);
font-family: var(--font-mono);
color: var(--color-text);
}
}
/* ===========================================
FOCUS HIGHLIGHT (double-click to edit)
=========================================== */
@keyframes focus-blink {
0%, 100% { background: transparent; }
25%, 75% { background: var(--bg-teal-medium); }
}
swp-data-row.focus-highlight {
animation: focus-blink 1s ease-out;
& input {
outline: 2px solid var(--color-teal);
outline-offset: 2px;
}
}
/* ===========================================
CHART SUBTITLE (for employee stats)
=========================================== */
swp-chart-subtitle {
display: block;
font-size: var(--font-size-sm);
color: var(--color-text-muted);
margin-top: var(--spacing-1);
}
/* ===========================================
RECENT BOOKINGS TABLE
=========================================== */
swp-card.recent-bookings swp-data-table {
grid-template-columns: minmax(100px, 1fr) minmax(80px, 1fr) 90px 80px;
}
swp-card.recent-bookings swp-data-table-row swp-data-table-cell {
&:first-child {
font-weight: var(--font-weight-medium);
}
&:nth-child(3) {
font-size: var(--font-size-sm);
color: var(--color-text-secondary);
}
&:last-child {
font-family: var(--font-mono);
font-size: var(--font-size-sm);
text-align: right;
}
}
/* ===========================================
STATS BOOKINGS TABLE
=========================================== */
.stats-bookings {
swp-data-table {
grid-template-columns: 90px 60px minmax(120px, 1fr) minmax(150px, 1fr) 80px 100px 100px;
}
swp-data-table-row swp-data-table-cell {
&:nth-child(1),
&:nth-child(2),
&:nth-child(5) {
font-family: var(--font-mono);
font-size: 12px;
color: var(--color-text-secondary);
}
&:nth-child(3) {
font-weight: var(--font-weight-medium);
}
&:nth-child(6) {
font-family: var(--font-mono);
font-size: 12px;
font-weight: var(--font-weight-semibold);
text-align: right;
}
}
swp-data-table-header swp-data-table-cell:nth-child(6) {
text-align: right;
}
}
/* ===========================================
SCHEDULE SCROLL CONTAINER
=========================================== */
swp-schedule-scroll {
display: block;
max-width: var(--page-max-width);
margin: 0 auto;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
cursor: grab;
}
swp-schedule-scroll.dragging {
cursor: grabbing;
user-select: none;
}
swp-schedule-scroll.dragging * {
pointer-events: none;
}
/* Når drawer er åben: page-container styles (padding animeres via JS) */
body.schedule-drawer-open swp-tab-content[data-tab="schedule"] swp-page-container {
max-width: none;
margin: 0;
}
/* ===========================================
WORK SCHEDULE TABLE
=========================================== */
swp-schedule-table {
display: grid;
grid-template-columns: 180px repeat(7, minmax(100px, 1fr));
min-width: max-content;
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-badge {
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-badge {
font-family: var(--font-mono);
font-size: 12px;
font-weight: 500;
padding: 4px 8px;
border-radius: 4px;
background: color-mix(in srgb, var(--color-teal) 10%, white);
color: var(--color-text);
white-space: nowrap;
min-width: 90px;
text-align: center;
display: inline-block;
}
swp-time-badge.off {
background: transparent;
color: var(--color-text-muted);
}
swp-time-badge.off.off-override {
background: color-mix(in srgb, #7c3aed 12%, white);
color: #6d28d9;
}
swp-time-badge.vacation {
background: color-mix(in srgb, #f59e0b 15%, white);
color: #b45309;
}
swp-time-badge.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);
}
}
/* 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);
}
}
/* ===========================================
RESPONSIVE
=========================================== */
@media (max-width: 1024px) {
swp-employee-table {
grid-template-columns: minmax(180px, 1fr) 100px 120px 100px 40px;
}
}
@media (max-width: 768px) {
swp-employee-table {
grid-template-columns: minmax(160px, 1fr) 90px 110px 90px 40px;
}
swp-employee-cell {
padding: var(--spacing-3) 0;
}
swp-employee-table-header,
swp-employee-row {
padding: 0 var(--spacing-4);
}
swp-users-header {
flex-direction: column;
align-items: flex-start;
gap: var(--spacing-4);
swp-btn {
width: 100%;
justify-content: center;
}
}
}