diff --git a/frontend/print-preview.css b/frontend/print-preview.css
index 4e68be6..0bdcca0 100644
--- a/frontend/print-preview.css
+++ b/frontend/print-preview.css
@@ -212,6 +212,7 @@
display: none !important;
}
+
/* Remove today highlighting in preview */
.print-preview-paper .calendar-day.today,
.print-preview-paper .week-day-header.today,
diff --git a/frontend/src/app.rs b/frontend/src/app.rs
index 1b04863..12f57ed 100644
--- a/frontend/src/app.rs
+++ b/frontend/src/app.rs
@@ -573,21 +573,6 @@ pub fn App() -> Html {
});
}
- // Reset theme to default when user is logged out
- {
- let auth_token = auth_token.clone();
- use_effect_with((*auth_token).clone(), move |token| {
- if token.is_none() {
- // User is logged out, reset theme to default
- if let Some(document) = web_sys::window().and_then(|w| w.document()) {
- if let Some(root) = document.document_element() {
- let _ = root.set_attribute("data-theme", "default");
- let _ = root.set_attribute("data-style", "default");
- }
- }
- }
- });
- }
// Fetch user info when token is available
{
diff --git a/frontend/src/components/month_view.rs b/frontend/src/components/month_view.rs
index 7736679..0f6d5a2 100644
--- a/frontend/src/components/month_view.rs
+++ b/frontend/src/components/month_view.rs
@@ -114,8 +114,13 @@ pub fn month_view(props: &MonthViewProps) -> Html {
};
+ let weeks_needed = calculate_minimum_weeks_needed(first_weekday, days_in_month);
+
+ // Use calculated weeks with height-based container sizing for proper fit
+ let dynamic_style = format!("grid-template-rows: var(--weekday-header-height, 50px) repeat({}, 1fr);", weeks_needed);
+
html! {
-
+
// Weekday headers
@@ -238,13 +243,27 @@ pub fn month_view(props: &MonthViewProps) -> Html {
}).collect::()
}
- { render_next_month_days(days_from_prev_month.len(), days_in_month) }
+ { render_next_month_days(days_from_prev_month.len(), days_in_month, calculate_minimum_weeks_needed(first_weekday, days_in_month)) }
}
}
-fn render_next_month_days(prev_days_count: usize, current_days_count: u32) -> Html {
- let total_slots = 42; // 6 rows x 7 days
+fn calculate_minimum_weeks_needed(first_weekday: Weekday, days_in_month: u32) -> u32 {
+ let days_before = match first_weekday {
+ Weekday::Sun => 0,
+ Weekday::Mon => 1,
+ Weekday::Tue => 2,
+ Weekday::Wed => 3,
+ Weekday::Thu => 4,
+ Weekday::Fri => 5,
+ Weekday::Sat => 6,
+ };
+ let total_days_needed = days_before + days_in_month;
+ (total_days_needed + 6) / 7 // Round up to get number of weeks
+}
+
+fn render_next_month_days(prev_days_count: usize, current_days_count: u32, weeks_needed: u32) -> Html {
+ let total_slots = (weeks_needed * 7) as usize; // Dynamic based on weeks needed
let used_slots = prev_days_count + current_days_count as usize;
let remaining_slots = if used_slots < total_slots {
total_slots - used_slots
diff --git a/frontend/src/components/print_preview_modal.rs b/frontend/src/components/print_preview_modal.rs
index 2e72988..2562e22 100644
--- a/frontend/src/components/print_preview_modal.rs
+++ b/frontend/src/components/print_preview_modal.rs
@@ -1,9 +1,10 @@
-use crate::components::{ViewMode, WeekView, MonthView};
+use crate::components::{ViewMode, WeekView, MonthView, CalendarHeader};
use crate::models::ical::VEvent;
use crate::services::calendar_service::{UserInfo, ExternalCalendar};
use chrono::NaiveDate;
use std::collections::HashMap;
use wasm_bindgen::{closure::Closure, JsCast};
+use web_sys::MouseEvent;
use yew::prelude::*;
#[derive(Properties, PartialEq)]
@@ -88,10 +89,11 @@ pub fn PrintPreviewModal(props: &PrintPreviewModalProps) -> Html {
let calculate_print_dimensions = |start_hour: u32, end_hour: u32, time_increment: u32| -> (f64, f64, f64) {
let visible_hours = (end_hour - start_hour) as f64;
let slots_per_hour = if time_increment == 15 { 4.0 } else { 2.0 };
- let header_height = 50.0; // Fixed week header height in print preview
+ let calendar_header_height = 80.0; // Calendar header height in print preview
+ let week_header_height = 50.0; // Fixed week header height in print preview
let header_border = 2.0; // Week header bottom border (2px solid)
let container_spacing = 8.0; // Additional container spacing/margins
- let total_overhead = header_height + header_border + container_spacing;
+ let total_overhead = calendar_header_height + week_header_height + header_border + container_spacing;
let available_height = 720.0 - total_overhead; // Available for time content
let base_unit = available_height / (visible_hours * slots_per_hour);
let pixels_per_hour = base_unit * slots_per_hour;
@@ -151,10 +153,11 @@ pub fn PrintPreviewModal(props: &PrintPreviewModalProps) -> Html {
// Recalculate base-unit and pixels-per-hour based on actual height
let visible_hours = (end_hour - start_hour) as f64;
let slots_per_hour = if time_increment == 15 { 4.0 } else { 2.0 };
- let header_height = 50.0;
+ let calendar_header_height = 80.0; // Calendar header height
+ let week_header_height = 50.0; // Week header height
let header_border = 2.0;
let container_spacing = 8.0;
- let total_overhead = header_height + header_border + container_spacing;
+ let total_overhead = calendar_header_height + week_header_height + header_border + container_spacing;
let available_height = actual_height - total_overhead;
let actual_base_unit = available_height / (visible_hours * slots_per_hour);
let actual_pixels_per_hour = actual_base_unit * slots_per_hour;
@@ -320,38 +323,50 @@ pub fn PrintPreviewModal(props: &PrintPreviewModalProps) -> Html {
*start_hour, *end_hour, base_unit, pixels_per_hour, *zoom_level
)}>
- {
- match props.view_mode {
- ViewMode::Week => html! {
-
- },
- ViewMode::Month => html! {
-
>}
- on_event_click={Callback::noop()}
- user_info={props.user_info.clone()}
- external_calendars={props.external_calendars.clone()}
- />
- },
+ Some("week-view"), _ => None })}>
+ >}
+ on_print={None::>}
+ />
+ {
+ match props.view_mode {
+ ViewMode::Week => html! {
+
+ },
+ ViewMode::Month => html! {
+ >}
+ on_event_click={Callback::noop()}
+ user_info={props.user_info.clone()}
+ external_calendars={props.external_calendars.clone()}
+ />
+ },
+ }
}
- }
+
diff --git a/frontend/styles.css b/frontend/styles.css
index 22717b9..3f026aa 100644
--- a/frontend/styles.css
+++ b/frontend/styles.css
@@ -586,6 +586,11 @@ body {
}
@media (max-height: 750px) and (min-height: 600px) {
+ .calendar-grid {
+ --calendar-header-height: 80px;
+ --weekday-header-height: 45px;
+ }
+
.sidebar-header {
padding: 0.8rem 1rem 0.5rem;
}
@@ -695,6 +700,11 @@ body {
font-size: 1.2rem !important;
}
+ /* Adjust weekday header height for responsive row calculation */
+ .calendar-grid {
+ --weekday-header-height: 45px;
+ }
+
.logout-button {
padding: 0.2rem 0.4rem;
@@ -702,7 +712,12 @@ body {
}
}
-@media (max-height: 650px) and (min-height: 600px) {
+@media (max-height: 650px) {
+ .calendar-grid {
+ --calendar-header-height: 75px;
+ --weekday-header-height: 40px;
+ }
+
.sidebar-header {
padding: 0.5rem 0.8rem 0.3rem;
}
@@ -827,6 +842,11 @@ body {
font-size: 1.1rem !important;
}
+ /* Most compact weekday header height for responsive row calculation */
+ .calendar-grid {
+ --weekday-header-height: 40px;
+ }
+
.logout-button {
padding: 0.15rem 0.3rem;
@@ -843,9 +863,9 @@ body {
}
.login-form, .register-form {
- background: white;
+ background: #ffffff !important;
padding: 2rem;
- border-radius: var(--border-radius-medium);
+ border-radius: 12px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
width: 100%;
max-width: 500px;
@@ -854,7 +874,8 @@ body {
.login-form h2, .register-form h2 {
text-align: center;
margin-bottom: 2rem;
- color: #333;
+ color: #333333 !important;
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', sans-serif !important;
}
.form-group {
@@ -868,6 +889,15 @@ body {
color: var(--text-secondary);
}
+.login-form .form-group label,
+.register-form .form-group label,
+.login-form label,
+.register-form label {
+ color: #333333 !important;
+ font-size: 1rem !important;
+ font-weight: 500 !important;
+}
+
.form-group input {
width: 100%;
padding: var(--control-padding);
@@ -877,12 +907,41 @@ body {
transition: border-color 0.2s;
}
+.login-form .form-group input,
+.register-form .form-group input,
+.login-form input[type="text"],
+.login-form input[type="email"],
+.login-form input[type="password"],
+.login-form input[type="url"],
+.register-form input[type="text"],
+.register-form input[type="email"],
+.register-form input[type="password"],
+.register-form input[type="url"] {
+ background: #ffffff !important;
+ color: #333333 !important;
+ border: 1px solid #d1d5db !important;
+}
+
.form-group input:focus {
outline: none;
border-color: var(--input-border-focus);
box-shadow: 0 0 0 2px rgba(102, 126, 234, 0.2);
}
+.login-form .form-group input:focus,
+.register-form .form-group input:focus,
+.login-form input[type="text"]:focus,
+.login-form input[type="email"]:focus,
+.login-form input[type="password"]:focus,
+.login-form input[type="url"]:focus,
+.register-form input[type="text"]:focus,
+.register-form input[type="email"]:focus,
+.register-form input[type="password"]:focus,
+.register-form input[type="url"]:focus {
+ border-color: #667eea !important;
+ box-shadow: 0 0 0 2px rgba(102, 126, 234, 0.2) !important;
+}
+
.form-group input:disabled {
background-color: var(--background-tertiary);
cursor: not-allowed;
@@ -924,7 +983,7 @@ body {
.remember-checkbox label {
margin: 0;
font-size: 0.55rem;
- color: #888;
+ color: #888888;
cursor: pointer;
user-select: none;
font-weight: 400;
@@ -956,15 +1015,51 @@ body {
z-index: 1;
}
+.login-form .password-toggle-btn,
+.register-form .password-toggle-btn {
+ position: absolute !important;
+ right: 0.75rem !important;
+ background: transparent !important;
+ border: none !important;
+ color: #888888 !important;
+ cursor: pointer !important;
+ padding: 0.25rem !important;
+ font-size: 1rem !important;
+ display: flex !important;
+ align-items: center !important;
+ justify-content: center !important;
+ transition: color 0.2s ease !important;
+ z-index: 1 !important;
+ border-radius: 0 !important;
+ box-shadow: none !important;
+}
+
.password-toggle-btn:hover {
color: #555;
}
+.login-form .password-toggle-btn:hover,
+.register-form .password-toggle-btn:hover {
+ color: #555555 !important;
+ background: transparent !important;
+ border: none !important;
+ box-shadow: none !important;
+}
+
.password-toggle-btn:focus {
outline: none;
color: #667eea;
}
+.login-form .password-toggle-btn:focus,
+.register-form .password-toggle-btn:focus {
+ outline: none !important;
+ color: #667eea !important;
+ background: transparent !important;
+ border: none !important;
+ box-shadow: none !important;
+}
+
.login-button, .register-button {
width: 100%;
padding: var(--control-padding);
@@ -998,6 +1093,13 @@ body {
border: 1px solid #f5c6cb;
}
+.login-form .error-message,
+.register-form .error-message {
+ background-color: #ef4444;
+ color: #ffffff;
+ border: 1px solid #f5c6cb;
+}
+
.auth-links {
text-align: center;
margin-top: 2rem;
@@ -1179,10 +1281,13 @@ body {
.calendar-grid {
display: grid;
grid-template-columns: repeat(7, 1fr);
- grid-template-rows: auto repeat(6, 1fr);
- flex: 1;
+ /* grid-template-rows set dynamically in component with calculated weeks */
+ position: relative;
+ height: calc(100% - var(--calendar-header-height, 88px));
background: var(--calendar-bg, white);
gap: 0;
+ --weekday-header-height: 50px; /* Base weekday header height */
+ --calendar-header-height: 88px; /* Base calendar header height */
}
/* Week View Container */