From 18c12cd3e6702c6fde903124175e86456b190f01 Mon Sep 17 00:00:00 2001 From: Janus Knudsen Date: Thu, 21 Aug 2025 22:09:15 +0200 Subject: [PATCH] Adds month view design and styling Introduces basic month view structure and styling with week numbers. Creates expanded month view with event details and duration-based sizing. Moves event color handling to CSS classes for better flexibility and theming. --- month-view-design.html | 537 ++++++++++++++++++ month-view-expanded.html | 848 ++++++++++++++++++++++++++++ src/renderers/EventRenderer.ts | 5 +- src/renderers/HeaderRenderer.ts | 3 +- wwwroot/css/calendar-base-css.css | 20 +- wwwroot/css/calendar-events-css.css | 20 +- wwwroot/css/calendar-month-css.css | 316 +++++++++++ wwwroot/index.html | 1 + 8 files changed, 1735 insertions(+), 15 deletions(-) create mode 100644 month-view-design.html create mode 100644 month-view-expanded.html create mode 100644 wwwroot/css/calendar-month-css.css diff --git a/month-view-design.html b/month-view-design.html new file mode 100644 index 0000000..c71e212 --- /dev/null +++ b/month-view-design.html @@ -0,0 +1,537 @@ + + + + + + Calendar Plantempus - Month View + + + +
+
+ +
Uge
+ + +
Man
+
Tir
+
Ons
+
Tor
+
Fre
+
Lør
+
Søn
+ + +
1
+
+
30
+
+
+
31
+
+
Nytår
+
+
+
+
1
+
+
Nytårsdag
+
+
+
+
2
+
+
Tilbage på arbejde
+
+
+
+
3
+
+
Team møde
+
Review
+
+
+
+
4
+
+
+
5
+
+
Familie
+
+
+ + +
2
+
+
6
+
+
Stand-up
+
+
+
+
7
+
+
Rapport
+
1:1
+
+
+
+
8
+
+
Code review
+
+
+
+
9
+
+
Planning
+
Design
+
+1
+
+
+
+
10
+
+
Sprint review
+
+
+
+
11
+
+
+
12
+
+
Brunch
+
+
+ + +
3
+
+
13
+
+
All hands
+
+
+
+
14
+
+
Deploy
+
+
+
+
15
+
+
Presentation
+
Retro
+
+
+
+
16
+
+
Bug triage
+
+
+
+
17
+
+
Planning
+
+
+
+
18
+
+
Koncert
+
+
+
+
19
+
+ + +
4
+
+
20
+
+
Status møde
+
Refactoring
+
+
+
+
21
+
+
Beta release
+
+
+
+
22
+
+
Architecture
+
Performance
+
Docs
+
+2
+
+
+
+
23
+
+
Cleanup
+
+
+
+
24
+
+
Weekly sync
+
+
+
+
25
+
+
+
26
+
+
Fødselsdag
+
+
+ + +
5
+
+
27
+
+
Q1 planning
+
+
+
+
28
+
+
Tech talks
+
+
+
+
29
+
+
Monthly report
+
+
+
+
30
+
+
Team building
+
+
+
+
31
+
+
End of month
+
+
+
+
1
+
+
+
2
+
+ + +
6
+
+
3
+
+
+
4
+
+
+
5
+
+
+
6
+
+
+
7
+
+
+
8
+
+
+
9
+
+
+
+ + + + \ No newline at end of file diff --git a/month-view-expanded.html b/month-view-expanded.html new file mode 100644 index 0000000..1b36518 --- /dev/null +++ b/month-view-expanded.html @@ -0,0 +1,848 @@ + + + + + + Calendar Plantempus - Month View Expanded + + + +
+
+ +
Uge
+ + +
Man
+
Tir
+
Ons
+
Tor
+
Fre
+
Lør
+
Søn
+ + +
1
+
+
30
+
+
+
+
31
+
+
+
20:00 - 22:00
+
Nytårsaften
+
Fest med familie og venner
+
+
+
+
+
1
+
+
+
Hele dagen
+
Nytårsdag
+
+
+
+
+
2
+
+
+
09:00 - 10:00
+
Tilbage på arbejde
+
Opstart efter ferien
+
+
+
10:00 - 10:30
+
Kick-off møde
+
+
+
+
+
3
+
+
+
09:00 - 10:30
+
Team møde
+
Q1 planning og mål
+
+
+
11:00 - 13:00
+
Projekt review
+
Gennemgang af December projekter og status på Q1 initiativer
+
+
+
15:00 - 15:30
+
Sprint deadline
+
+
+
+
+
4
+
+
+
+
5
+
+
+
18:00 - 20:30
+
Familie middag
+
Hos mormor og morfar
+
+
+
+ + +
2
+
+
6
+
+
+
09:15 - 09:30
+
Stand-up
+
+
+
10:00 - 11:30
+
Code review
+
Frontend refactoring PR
+
+
+
+
+
7
+
+
+
12:00 - 13:00
+
Rapport deadline
+
Månedlig status rapport
+
+
+
14:00 - 15:00
+
1:1 med chef
+
Karriere udvikling
+
+
+
15:30 - 16:00
+
Design review
+
+
+
+
+
8
+
+
+
10:00 - 11:00
+
Feature demo
+
Ny dashboard funktionalitet
+
+
+
+
+
9
+
+
+
09:00 - 11:00
+
Planning møde
+
Sprint 23 planning og estimering
+
+
+
11:00 - 12:30
+
Design session
+
UX workshop for ny feature
+
+
+
14:00 - 14:30
+
Release notes
+
+
+
15:00 - 16:00
+
Tech sync
+
Arkitektur diskussion
+
+
+
17:00 - 17:30
+
Tandlæge
+
+
+
+
+
10
+
+
+
13:00 - 15:00
+
Sprint review
+
Demo af Sprint 22 leverancer til stakeholders
+
+
+
15:00 - 16:00
+
Retrospective
+
Sprint 22 læringer
+
+
+
+
+
11
+
+
+
+
12
+
+
+
11:00 - 13:00
+
Brunch
+
Med gamle venner fra uni
+
+
+
+ + +
3
+
+
13
+
+
+
Hele dagen
+
All hands møde
+
Quarterly business update
+
+
+
14:00 - 16:00
+
Architecture planning
+
Microservices migration strategi
+
+
+
+
+
14
+
+
+
10:00 - 13:00
+
Feature deployment
+
Production release og monitoring af ny payment feature
+
+
+
15:00 - 16:30
+
Client call
+
Requirements gathering
+
+
+
+
+
15
+
+
+
10:00 - 12:00
+
Client presentation
+
Q4 results og Q1 roadmap præsentation
+
+
+
14:00 - 15:00
+
Team retrospective
+
Monthly team health check
+
+
+
16:00 - 17:00
+
Bug triage
+
Priority 1 issues
+
+
+
+
+
16
+
+
+
11:00 - 12:30
+
Performance review
+
Database optimization results
+
+
+
+
+
17
+
+
+
09:00 - 12:00
+
Sprint planning
+
Sprint 24 - omfattende planning session med hele teamet
+
+
+
13:00 - 15:00
+
Code cleanup
+
Technical debt reduction
+
+
+
+
+
18
+
+
+
19:00 - 22:00
+
Koncert
+
Royal Arena - med forband og afterparty
+
+
+
+
+
19
+
+
+ + +
4
+
+
20
+
+
+
09:00 - 09:30
+
Status møde
+
+
+
10:30 - 12:00
+
Refactoring session
+
Legacy code modernization
+
+
+
12:00 - 13:00
+
Documentation due
+
API documentation update
+
+
+
14:00 - 15:30
+
Architecture review
+
System design review med senior architects
+
+
+
15:30 - 16:30
+
Performance testing
+
Load testing results
+
+
+
17:00 - 17:30
+
Gym
+
+
+
+
+
21
+
+
+
14:00 - 18:00
+
Beta release
+
Full release process including deployment, smoke testing, monitoring setup og stakeholder notification
+
+
+
+
+
22
+
+
+
09:00 - 10:30
+
Architecture review
+
Final design approval
+
+
+
11:00 - 13:00
+
Performance testing
+
Full regression test suite execution
+
+
+
14:00 - 15:00
+
Documentation deadline
+
User guide completion
+
+
+
15:00 - 16:30
+
Stakeholder meeting
+
Project status update
+
+
+
16:30 - 17:00
+
Deploy to staging
+
+
+
+
+
23
+
+
+
Hele dagen
+
Code cleanup day
+
Team-wide technical debt reduction
+
+
+
+
+
24
+
+
+
14:00 - 15:00
+
Weekly sync
+
Cross-team alignment
+
+
+
+
+
25
+
+
+
+
26
+
+
+
Hele dagen
+
Fødselsdag
+
+
+
18:00 - 22:00
+
Fødselsdagsfest
+
Stor fest med familie og venner, middag og underholdning
+
+
+
+ + +
5
+
+
27
+
+
+
Hele dagen
+
Q1 planning - Day 1
+
Quarterly planning workshop
+
+
+
+
+
28
+
+
+
Hele dagen
+
Q1 planning - Day 2
+
OKR setting og roadmap
+
+
+
14:00 - 16:00
+
Tech talks
+
Knowledge sharing session om nye teknologier
+
+
+
+
+
29
+
+
+
Hele dagen
+
Q1 planning - Day 3
+
Final alignment og præsentation
+
+
+
16:00 - 18:00
+
Monthly report
+
Januar status rapport og metrics sammensætning
+
+
+
+
+
30
+
+
+
15:00 - 18:00
+
Team building
+
Off-site team building aktivitet med middag
+
+
+
+
+
31
+
+
+
Hele dagen
+
End of month
+
+
+
14:00 - 16:00
+
Month wrap-up
+
Januar review og Februar forberedelse
+
+
+
+
+
1
+
+
+
+
2
+
+
+ + +
6
+
+
3
+
+
+
+
4
+
+
+
+
5
+
+
+
+
6
+
+
+
+
7
+
+
+
+
8
+
+
+
+
9
+
+
+
+
+ + + + \ No newline at end of file diff --git a/src/renderers/EventRenderer.ts b/src/renderers/EventRenderer.ts index 0920b8d..c4afe26 100644 --- a/src/renderers/EventRenderer.ts +++ b/src/renderers/EventRenderer.ts @@ -71,8 +71,7 @@ export abstract class BaseEventRenderer implements EventRendererStrategy { eventElement.style.top = `${position.top + 1}px`; eventElement.style.height = `${position.height - 1}px`; - // Set color - eventElement.style.backgroundColor = event.metadata?.color || '#3498db'; + // Color is now handled by CSS classes based on data-type attribute // Format time for display const startTime = this.dateCalculator.formatTime(new Date(event.start)); @@ -89,7 +88,7 @@ export abstract class BaseEventRenderer implements EventRendererStrategy { console.log(`BaseEventRenderer: Created event element for "${event.title}":`, { top: eventElement.style.top, height: eventElement.style.height, - backgroundColor: eventElement.style.backgroundColor, + dataType: eventElement.dataset.type, position: eventElement.style.position, innerHTML: eventElement.innerHTML }); diff --git a/src/renderers/HeaderRenderer.ts b/src/renderers/HeaderRenderer.ts index 26e16c5..77d8919 100644 --- a/src/renderers/HeaderRenderer.ts +++ b/src/renderers/HeaderRenderer.ts @@ -102,7 +102,8 @@ export class DateHeaderRenderer implements HeaderRenderer { const gridColumnStart = startColumnIndex + 1; const gridColumnEnd = endColumnIndex + 2; allDayEvent.style.gridColumn = `${gridColumnStart} / ${gridColumnEnd}`; - allDayEvent.style.backgroundColor = event.metadata?.color || '#ff9800'; + // Color is now handled by CSS classes based on event type + allDayEvent.dataset.type = event.type || 'work'; calendarHeader.appendChild(allDayEvent); } diff --git a/wwwroot/css/calendar-base-css.css b/wwwroot/css/calendar-base-css.css index 6b8599e..dbeed1d 100644 --- a/wwwroot/css/calendar-base-css.css +++ b/wwwroot/css/calendar-base-css.css @@ -35,18 +35,20 @@ --color-grid-line: #e0e0e0; --color-grid-line-light: rgba(0, 0, 0, 0.05); --color-hour-line: rgba(0, 0, 0, 0.2); - --color-work-hours: rgba(0, 100, 0, 0.06); + --color-work-hours: rgba(242, 242, 242, 1); --color-current-time: #ff0000; - /* Event colors */ - --color-event-meeting: #e3f2fd; - --color-event-meeting-border: #2196f3; - --color-event-meal: #fff3e0; + /* Event colors - Updated with month-view-expanded.html color scheme */ + --color-event-meeting: #e8f5e8; + --color-event-meeting-border: #4caf50; + --color-event-meal: #fff8e1; --color-event-meal-border: #ff9800; - --color-event-work: #f3e5f5; - --color-event-work-border: #9c27b0; - --color-event-milestone: #e8f5e9; - --color-event-milestone-border: #4caf50; + --color-event-work: #fff8e1; + --color-event-work-border: #ff9800; + --color-event-milestone: #ffebee; + --color-event-milestone-border: #f44336; + --color-event-personal: #f3e5f5; + --color-event-personal-border: #9c27b0; /* UI colors */ --color-background: #ffffff; diff --git a/wwwroot/css/calendar-events-css.css b/wwwroot/css/calendar-events-css.css index 9cefb06..6c7c60b 100644 --- a/wwwroot/css/calendar-events-css.css +++ b/wwwroot/css/calendar-events-css.css @@ -10,7 +10,7 @@ swp-event { z-index: 10; left: 2px; right: 2px; - color: white; + color: var(--color-text); font-size: 12px; padding: 2px 4px; @@ -18,28 +18,44 @@ swp-event { &[data-type="meeting"] { background: var(--color-event-meeting); border-left: 4px solid var(--color-event-meeting-border); + color: var(--color-text); } &[data-type="meal"] { background: var(--color-event-meal); border-left: 4px solid var(--color-event-meal-border); + color: var(--color-text); } &[data-type="work"] { background: var(--color-event-work); border-left: 4px solid var(--color-event-work-border); + color: var(--color-text); } &[data-type="milestone"] { background: var(--color-event-milestone); border-left: 4px solid var(--color-event-milestone-border); + color: var(--color-text); + } + + &[data-type="personal"] { + background: var(--color-event-personal); + border-left: 4px solid var(--color-event-personal-border); + color: var(--color-text); + } + + &[data-type="deadline"] { + background: var(--color-event-milestone); + border-left: 4px solid var(--color-event-milestone-border); + color: var(--color-text); } } swp-event:hover { box-shadow: var(--shadow-md); - filter: brightness(0.95); + transform: translateX(2px); z-index: 20; } diff --git a/wwwroot/css/calendar-month-css.css b/wwwroot/css/calendar-month-css.css new file mode 100644 index 0000000..80533fb --- /dev/null +++ b/wwwroot/css/calendar-month-css.css @@ -0,0 +1,316 @@ +/* Calendar Month View Styles */ + +/* Month view specific container - extends swp-calendar-container for month layout */ +swp-calendar[data-view="month"] swp-calendar-container { + overflow: hidden; + background: var(--color-background); +} + +/* Month grid layout with week numbers column */ +.month-grid { + display: grid; + grid-template-columns: 40px repeat(7, 1fr); /* Week numbers + 7 days */ + grid-template-rows: 40px repeat(6, 1fr); + min-height: 600px; + border: 1px solid var(--color-border); + border-radius: var(--border-radius); + overflow: hidden; +} + +/* Week number header cell */ +.month-week-header { + grid-column: 1; + grid-row: 1; + background: var(--color-surface); + border-right: 1px solid var(--color-border); + border-bottom: 1px solid var(--color-border); + display: flex; + align-items: center; + justify-content: center; + font-size: 0.75rem; + font-weight: 600; + color: var(--color-text-secondary); + height: 40px; +} + +/* Month day headers - only day names, right aligned */ +.month-day-header { + background: var(--color-surface); + border-right: 1px solid var(--color-border); + border-bottom: 1px solid var(--color-border); + display: flex; + align-items: center; + justify-content: flex-end; + padding: 8px 12px; + font-weight: 600; + color: var(--color-text-secondary); + font-size: 0.875rem; + height: 40px; +} + +.month-day-header:last-child { + border-right: none; +} + +/* Week number cells */ +.month-week-number { + grid-column: 1; + background: var(--color-surface); + border-right: 1px solid var(--color-border); + border-bottom: 1px solid var(--color-border); + display: flex; + align-items: center; + justify-content: center; + font-size: 0.75rem; + font-weight: 600; + color: var(--color-text-secondary); +} + +/* Month day cells */ +.month-day-cell { + border-right: 1px solid var(--color-border); + border-bottom: 1px solid var(--color-border); + padding: 8px; + background: var(--color-background); + transition: background-color var(--transition-fast); + position: relative; + min-height: 100px; + cursor: pointer; +} + +.month-day-cell:hover { + background: var(--color-hover); +} + +.month-day-cell:last-child { + border-right: none; +} + +/* Other month dates (previous/next month) */ +.month-day-cell.other-month { + background: var(--color-surface); + color: var(--color-text-secondary); +} + +/* Today highlighting - subtle with left border */ +.month-day-cell.today { + background: #f0f8ff; + border-left: 3px solid var(--color-primary); +} + +/* Weekend styling */ +.month-day-cell.weekend { + background: #fafbfc; +} + +/* Day number in each cell */ +.month-day-number { + font-weight: 600; + margin-bottom: 6px; + font-size: 0.875rem; +} + +.month-day-cell.today .month-day-number { + color: var(--color-primary); + font-weight: 700; +} + +/* Events container within each day */ +.month-events { + display: flex; + flex-direction: column; + gap: 2px; + max-height: 70px; + overflow: hidden; +} + +/* Individual month events - compact version */ +.month-event { + background: #e3f2fd; + color: var(--color-primary); + padding: 1px 4px; + border-radius: 2px; + font-size: 10px; + font-weight: 500; + cursor: pointer; + transition: all var(--transition-fast); + border-left: 2px solid var(--color-primary); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + line-height: 1.2; +} + +.month-event:hover { + transform: translateY(-1px); +} + +/* Event categories using existing color scheme */ +.month-event.category-meeting { + background: #e8f5e8; + color: var(--color-success); + border-left-color: var(--color-success); +} + +.month-event.category-deadline { + background: #ffebee; + color: var(--color-error); + border-left-color: var(--color-error); +} + +.month-event.category-work { + background: #fff8e1; + color: var(--color-secondary); + border-left-color: var(--color-secondary); +} + +.month-event.category-personal { + background: #f3e5f5; + color: #7b1fa2; + border-left-color: #9c27b0; +} + +/* "More events" indicator */ +.month-event-more { + background: var(--color-surface); + color: var(--color-text-secondary); + padding: 1px 4px; + border-radius: 2px; + font-size: 9px; + text-align: center; + cursor: pointer; + border: 1px dashed var(--color-border); + margin-top: 1px; +} + +.month-event-more:hover { + background: var(--color-hover); +} + +/* Expanded month view - duration-based events */ +.month-grid.expanded { + min-height: 800px; +} + +.month-grid.expanded .month-day-cell { + min-height: 120px; + padding: 4px; +} + +.month-grid.expanded .month-events { + max-height: none; + overflow: visible; +} + +.month-grid.expanded .month-event { + padding: 2px 6px; + font-size: 11px; + min-height: 16px; + display: flex; + flex-direction: column; + white-space: normal; + text-overflow: clip; + overflow: visible; +} + +/* Duration-based event sizing (30px per hour) */ +.month-event.duration-30min { min-height: 15px; } +.month-event.duration-1h { min-height: 30px; } +.month-event.duration-1h30 { min-height: 45px; } +.month-event.duration-2h { min-height: 60px; } +.month-event.duration-3h { min-height: 90px; } +.month-event.duration-4h { min-height: 120px; } + +/* Event time display for expanded view */ +.month-event-time { + font-size: 9px; + opacity: 0.8; + font-weight: 400; +} + +.month-event-title { + font-weight: 600; + font-size: 10px; +} + +.month-event-subtitle { + font-size: 9px; + opacity: 0.7; + font-weight: 400; +} + +/* All-day events */ +.month-event.all-day { + background: linear-gradient(90deg, var(--color-primary), rgba(33, 150, 243, 0.7)); + color: white; + border-left-color: var(--color-primary); + font-weight: 600; +} + +/* Responsive adjustments */ +@media (max-width: 768px) { + .month-grid { + grid-template-columns: 30px repeat(7, 1fr); + min-height: 400px; + } + + .month-day-cell { + min-height: 60px; + padding: 4px; + } + + .month-day-header { + padding: 8px 4px; + font-size: 0.75rem; + } + + .month-event { + font-size: 9px; + padding: 1px 3px; + } + + .month-events { + max-height: 40px; + } + + .month-week-number { + font-size: 0.6rem; + } +} + +/* Loading state for month view */ +swp-calendar[data-view="month"][data-loading="true"] .month-grid { + opacity: 0.5; + pointer-events: none; +} + +/* Month view navigation animation support */ +.month-grid { + transition: transform var(--transition-normal); +} + +.month-grid.sliding-out-left { + transform: translateX(-100%); +} + +.month-grid.sliding-out-right { + transform: translateX(100%); +} + +.month-grid.sliding-in-left { + transform: translateX(-100%); + animation: slideInFromLeft var(--transition-normal) forwards; +} + +.month-grid.sliding-in-right { + transform: translateX(100%); + animation: slideInFromRight var(--transition-normal) forwards; +} + +@keyframes slideInFromLeft { + to { transform: translateX(0); } +} + +@keyframes slideInFromRight { + to { transform: translateX(0); } +} \ No newline at end of file diff --git a/wwwroot/index.html b/wwwroot/index.html index e72f644..c4f7ffc 100644 --- a/wwwroot/index.html +++ b/wwwroot/index.html @@ -10,6 +10,7 @@ +