Introduces settings service for managing tenant-specific calendar configurations Enables dynamic workweek presets with configurable work days Improves view switching with enhanced UI components Adds flexible calendar rendering based on tenant settings Extends DateService to support workweek date generation
381 lines
7.9 KiB
CSS
381 lines
7.9 KiB
CSS
/* V2 Layout - Calendar structure, grid, navigation */
|
|
|
|
.calendar-wrapper {
|
|
height: 100vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
swp-calendar {
|
|
display: grid;
|
|
grid-template-rows: auto 1fr;
|
|
height: 100%;
|
|
background: var(--color-surface);
|
|
}
|
|
|
|
/* Nav */
|
|
swp-calendar-nav {
|
|
display: flex;
|
|
gap: 12px;
|
|
padding: 8px 16px;
|
|
border-bottom: 1px solid var(--color-border);
|
|
align-items: center;
|
|
font-size: 13px;
|
|
}
|
|
|
|
/* View switcher - small chips */
|
|
swp-view-switcher {
|
|
display: flex;
|
|
gap: 4px;
|
|
background: var(--color-background-alt);
|
|
padding: 3px;
|
|
border-radius: 6px;
|
|
}
|
|
|
|
.view-chip {
|
|
padding: 4px 10px;
|
|
border: none;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
background: transparent;
|
|
color: var(--color-text-secondary);
|
|
font-size: 12px;
|
|
font-weight: 500;
|
|
transition: all 0.15s ease;
|
|
|
|
&:hover {
|
|
background: var(--color-surface);
|
|
color: var(--color-text);
|
|
}
|
|
|
|
&.active {
|
|
background: var(--color-surface);
|
|
color: var(--color-text);
|
|
box-shadow: 0 1px 2px rgba(0,0,0,0.1);
|
|
}
|
|
}
|
|
|
|
/* Workweek dropdown */
|
|
.workweek-dropdown {
|
|
padding: 4px 8px;
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 4px;
|
|
background: var(--color-surface);
|
|
font-size: 12px;
|
|
cursor: pointer;
|
|
|
|
&:hover { border-color: var(--color-text-secondary); }
|
|
&:focus { outline: 2px solid var(--color-primary); outline-offset: 1px; }
|
|
}
|
|
|
|
/* Navigation group */
|
|
swp-nav-group {
|
|
display: flex;
|
|
gap: 2px;
|
|
}
|
|
|
|
swp-nav-button {
|
|
padding: 6px 12px;
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
background: var(--color-surface);
|
|
font-size: 12px;
|
|
|
|
&:hover { background: var(--color-background-hover); }
|
|
|
|
&.btn-small {
|
|
padding: 4px 8px;
|
|
font-size: 11px;
|
|
}
|
|
}
|
|
|
|
swp-week-info {
|
|
margin-left: auto;
|
|
text-align: right;
|
|
|
|
swp-week-number {
|
|
font-weight: 600;
|
|
font-size: 12px;
|
|
display: block;
|
|
}
|
|
|
|
swp-date-range {
|
|
font-size: 11px;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
}
|
|
|
|
/* Container */
|
|
swp-calendar-container {
|
|
display: grid;
|
|
grid-template-columns: var(--time-axis-width) 1fr;
|
|
grid-template-rows: auto 1fr;
|
|
overflow: hidden;
|
|
height: 100%;
|
|
}
|
|
|
|
/* Time axis */
|
|
swp-time-axis {
|
|
grid-column: 1;
|
|
grid-row: 1 / 3;
|
|
display: grid;
|
|
grid-template-rows: auto 1fr;
|
|
border-right: 1px solid var(--color-border);
|
|
background: var(--color-surface);
|
|
overflow: hidden;
|
|
user-select: none;
|
|
}
|
|
|
|
swp-header-spacer {
|
|
border-bottom: 1px solid var(--color-border);
|
|
background: var(--color-surface);
|
|
z-index: 1;
|
|
}
|
|
|
|
swp-header-drawer {
|
|
display: grid;
|
|
grid-template-columns: subgrid;
|
|
grid-column: 1 / -1;
|
|
grid-row: 2;
|
|
overflow: hidden;
|
|
background: var(--color-background-alt);
|
|
border-bottom: 1px solid var(--color-border);
|
|
}
|
|
|
|
swp-time-axis-content {
|
|
display: flex;
|
|
flex-direction: column;
|
|
position: relative;
|
|
}
|
|
|
|
swp-hour-marker {
|
|
height: var(--hour-height);
|
|
padding: 4px 8px;
|
|
font-size: 11px;
|
|
color: var(--color-text-secondary);
|
|
text-align: right;
|
|
position: relative;
|
|
|
|
&::after {
|
|
content: '';
|
|
position: absolute;
|
|
top: -1px;
|
|
right: 0;
|
|
width: 5px;
|
|
height: 1px;
|
|
background: var(--color-hour-line);
|
|
}
|
|
|
|
&:first-child::after {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
/* Grid container */
|
|
swp-grid-container {
|
|
grid-column: 2;
|
|
grid-row: 1 / 3;
|
|
display: grid;
|
|
grid-template-columns: minmax(0, 1fr);
|
|
grid-template-rows: subgrid;
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* Viewport/Track for slide animation */
|
|
swp-header-viewport {
|
|
display: grid;
|
|
grid-template-columns: repeat(var(--grid-columns), minmax(var(--day-column-min-width), 1fr));
|
|
grid-template-rows: auto auto;
|
|
min-width: calc(var(--grid-columns) * var(--day-column-min-width));
|
|
overflow-y: scroll;
|
|
overflow-x: hidden;
|
|
|
|
&::-webkit-scrollbar { background: transparent; }
|
|
&::-webkit-scrollbar-thumb { background: transparent; }
|
|
}
|
|
|
|
swp-content-viewport {
|
|
overflow: hidden;
|
|
min-height: 0;
|
|
width: 100%;
|
|
}
|
|
|
|
swp-header-track {
|
|
display: grid;
|
|
grid-template-columns: subgrid;
|
|
grid-column: 1 / -1;
|
|
grid-row: 1;
|
|
}
|
|
|
|
swp-content-track {
|
|
display: flex;
|
|
height: 100%;
|
|
|
|
> swp-scrollable-content {
|
|
flex: 0 0 100%;
|
|
height: 100%;
|
|
}
|
|
}
|
|
|
|
/* Header */
|
|
swp-calendar-header {
|
|
display: grid;
|
|
grid-template-columns: subgrid;
|
|
grid-column: 1 / -1;
|
|
grid-auto-rows: auto;
|
|
background: var(--color-surface);
|
|
|
|
&[data-levels="date"] > swp-day-header { grid-row: 1; }
|
|
|
|
&[data-levels="resource date"] {
|
|
> swp-resource-header { grid-row: 1; }
|
|
> swp-day-header { grid-row: 2; }
|
|
}
|
|
|
|
&[data-levels="team resource date"] {
|
|
> swp-team-header { grid-row: 1; }
|
|
> swp-resource-header { grid-row: 2; }
|
|
> swp-day-header { grid-row: 3; }
|
|
}
|
|
|
|
&[data-levels="department resource date"] {
|
|
> swp-department-header { grid-row: 1; }
|
|
> swp-resource-header { grid-row: 2; }
|
|
> swp-day-header { grid-row: 3; }
|
|
}
|
|
}
|
|
|
|
swp-day-header,
|
|
swp-resource-header,
|
|
swp-team-header,
|
|
swp-department-header {
|
|
padding: 8px;
|
|
text-align: center;
|
|
border-right: 1px solid var(--color-border);
|
|
border-bottom: 1px solid var(--color-border);
|
|
user-select: none;
|
|
}
|
|
|
|
swp-team-header {
|
|
background: var(--color-team-bg);
|
|
color: var(--color-team-text);
|
|
font-weight: 500;
|
|
grid-column: span var(--team-cols, 1);
|
|
}
|
|
|
|
swp-department-header {
|
|
background: var(--color-team-bg);
|
|
color: var(--color-team-text);
|
|
font-weight: 500;
|
|
grid-column: span var(--department-cols, 1);
|
|
}
|
|
|
|
swp-resource-header {
|
|
background: var(--color-background-alt);
|
|
font-size: 13px;
|
|
}
|
|
|
|
swp-day-header {
|
|
swp-day-name {
|
|
display: block;
|
|
font-size: 11px;
|
|
color: var(--color-text-secondary);
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
swp-day-date {
|
|
display: block;
|
|
font-size: 24px;
|
|
font-weight: 300;
|
|
}
|
|
}
|
|
|
|
/* Scrollable content */
|
|
swp-scrollable-content {
|
|
display: block;
|
|
overflow: auto;
|
|
}
|
|
|
|
swp-time-grid {
|
|
display: block;
|
|
position: relative;
|
|
min-height: calc((var(--day-end-hour) - var(--day-start-hour)) * var(--hour-height));
|
|
min-width: calc(var(--grid-columns) * var(--day-column-min-width));
|
|
|
|
/* Timelinjer */
|
|
&::after {
|
|
content: '';
|
|
position: absolute;
|
|
inset: 0;
|
|
z-index: 2;
|
|
background-image: repeating-linear-gradient(
|
|
to bottom,
|
|
transparent,
|
|
transparent calc(var(--hour-height) - 1px),
|
|
var(--color-hour-line) calc(var(--hour-height) - 1px),
|
|
var(--color-hour-line) var(--hour-height)
|
|
);
|
|
pointer-events: none;
|
|
}
|
|
}
|
|
|
|
/* Kvarterlinjer - 3 linjer per time (15, 30, 45 min) */
|
|
swp-grid-lines {
|
|
display: block;
|
|
position: absolute;
|
|
inset: 0;
|
|
z-index: 1;
|
|
background-image: repeating-linear-gradient(
|
|
to bottom,
|
|
transparent 0,
|
|
transparent calc(var(--hour-height) / 4 - 1px),
|
|
var(--color-grid-line-light) calc(var(--hour-height) / 4 - 1px),
|
|
var(--color-grid-line-light) calc(var(--hour-height) / 4),
|
|
transparent calc(var(--hour-height) / 4),
|
|
transparent calc(var(--hour-height) / 2 - 1px),
|
|
var(--color-grid-line-light) calc(var(--hour-height) / 2 - 1px),
|
|
var(--color-grid-line-light) calc(var(--hour-height) / 2),
|
|
transparent calc(var(--hour-height) / 2),
|
|
transparent calc(var(--hour-height) * 3 / 4 - 1px),
|
|
var(--color-grid-line-light) calc(var(--hour-height) * 3 / 4 - 1px),
|
|
var(--color-grid-line-light) calc(var(--hour-height) * 3 / 4),
|
|
transparent calc(var(--hour-height) * 3 / 4),
|
|
transparent var(--hour-height)
|
|
);
|
|
}
|
|
|
|
swp-day-columns {
|
|
position: absolute;
|
|
inset: 0;
|
|
display: grid;
|
|
grid-template-columns: repeat(var(--grid-columns), minmax(var(--day-column-min-width), 1fr));
|
|
min-width: calc(var(--grid-columns) * var(--day-column-min-width));
|
|
}
|
|
|
|
swp-day-column {
|
|
position: relative;
|
|
border-right: 1px solid var(--color-border);
|
|
}
|
|
|
|
swp-events-layer {
|
|
position: absolute;
|
|
inset: 0;
|
|
z-index: 10;
|
|
}
|
|
|
|
/* Unavailable time zones (outside working hours) */
|
|
swp-unavailable-layer {
|
|
position: absolute;
|
|
inset: 0;
|
|
z-index: 5;
|
|
pointer-events: none;
|
|
}
|
|
|
|
swp-unavailable-zone {
|
|
position: absolute;
|
|
left: 0;
|
|
right: 0;
|
|
background: var(--color-unavailable, rgba(0, 0, 0, 0.05));
|
|
pointer-events: none;
|
|
}
|