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
{"Sun"}
{"Mon"}
@@ -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 )}>
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 */