From cae3a6e6c29f7e923a3c2f54d5088950c5606112 Mon Sep 17 00:00:00 2001 From: Jacob Reinikainen <80760206+jazzjacob@users.noreply.github.com> Date: Fri, 5 Sep 2025 15:08:57 +0200 Subject: [PATCH 1/3] profilepage and new darkmode button --- my-app/src/AppRoutes.jsx | 2 + my-app/src/components/Navigation.jsx | 10 +- my-app/src/components/Navigation.module.css | 26 ++ my-app/src/components/PlaceholderBanner.jsx | 30 +++ .../components/PlaceholderBanner.module.css | 94 +++++++ my-app/src/components/ThemeToggle.jsx | 9 +- my-app/src/components/ThemeToggle.module.css | 109 ++------ my-app/src/pages/Profile.jsx | 102 ++++++++ my-app/src/pages/Profile.module.css | 232 ++++++++++++++++++ 9 files changed, 512 insertions(+), 102 deletions(-) create mode 100644 my-app/src/components/PlaceholderBanner.jsx create mode 100644 my-app/src/components/PlaceholderBanner.module.css create mode 100644 my-app/src/pages/Profile.jsx create mode 100644 my-app/src/pages/Profile.module.css diff --git a/my-app/src/AppRoutes.jsx b/my-app/src/AppRoutes.jsx index 43694bd..cc94ee4 100644 --- a/my-app/src/AppRoutes.jsx +++ b/my-app/src/AppRoutes.jsx @@ -12,6 +12,7 @@ import { TestSession } from './pages/TestSession'; import FullScreenLoader from './components/FullScreenLoader'; import Home from './pages/Home'; import CoursePage from './pages/CoursePage'; +import Profile from './pages/Profile'; const AppRoutes = () => { const location = useLocation(); @@ -124,6 +125,7 @@ const AppRoutes = () => { } /> } /> } /> + } /> diff --git a/my-app/src/components/Navigation.jsx b/my-app/src/components/Navigation.jsx index dd1787d..87538fd 100644 --- a/my-app/src/components/Navigation.jsx +++ b/my-app/src/components/Navigation.jsx @@ -53,14 +53,14 @@ const Navigation = () => { {/* User Profile Section - Desktop only */} -
+
{getInitials(getCurrentUser().name)}
-

{getCurrentUser().name}

-
+ {getCurrentUser().name} + {/* Navigation - always visible in sidebar mode, toggleable in mobile */} + {/* Theme Toggle - Desktop only */} +
+ +
); }; diff --git a/my-app/src/components/Navigation.module.css b/my-app/src/components/Navigation.module.css index 63f1a30..c76a629 100644 --- a/my-app/src/components/Navigation.module.css +++ b/my-app/src/components/Navigation.module.css @@ -112,6 +112,11 @@ display: none; } +/* Theme Toggle Container - Mobile (hidden) */ +.themeToggleContainer { + display: none; +} + /* =========================================== DESKTOP SIDEBAR STYLES (≥ 1024px) ========================================== */ @@ -150,6 +155,11 @@ justify-content: center; } + /* Hide mobile theme toggle on desktop */ + .right > :first-child { + display: none; + } + .logo img { height: 60px; } @@ -208,6 +218,13 @@ gap: var(--spacing-md); padding: var(--spacing-lg) var(--spacing-xl); height: fit-content; + text-decoration: none; + transition: var(--transition-fast); + border-radius: 0; + } + + .userSection:hover { + background-color: var(--bg-muted); } .userAvatar { @@ -233,6 +250,7 @@ font-weight: var(--font-weight-semibold); color: var(--text-primary); font-size: 1rem; + margin: 0; } .userLastName { @@ -292,6 +310,14 @@ background-color: var(--bg-muted); color: var(--color-primary); } + + /* Theme Toggle Container - Desktop */ + .themeToggleContainer { + padding: var(--spacing-lg) var(--spacing-xl); + display: flex; + justify-content: center; + border-bottom: 1px solid var(--border-light); + } } /* =========================================== diff --git a/my-app/src/components/PlaceholderBanner.jsx b/my-app/src/components/PlaceholderBanner.jsx new file mode 100644 index 0000000..5894309 --- /dev/null +++ b/my-app/src/components/PlaceholderBanner.jsx @@ -0,0 +1,30 @@ +import React, { useState } from 'react'; +import styles from './PlaceholderBanner.module.css'; + +const PlaceholderBanner = ({ message = "Detta är en platshållare för utveckling. Funktionaliteten är inte färdigimplementerad än." }) => { + const [isDismissed, setIsDismissed] = useState(false); + + if (isDismissed) return null; + + return ( +
+
+
+ +
+
+ {message} +
+ +
+
+ ); +}; + +export default PlaceholderBanner; \ No newline at end of file diff --git a/my-app/src/components/PlaceholderBanner.module.css b/my-app/src/components/PlaceholderBanner.module.css new file mode 100644 index 0000000..a2d2634 --- /dev/null +++ b/my-app/src/components/PlaceholderBanner.module.css @@ -0,0 +1,94 @@ +.banner { + position: sticky; + top: 0; + z-index: var(--z-sticky); + background-color: #fef3c7; + border-bottom: 1px solid #f59e0b; + padding: var(--spacing-md) 0; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.content { + max-width: 1200px; + margin: 0 auto; + display: flex; + align-items: center; + gap: var(--spacing-md); + padding: 0 var(--spacing-xl); +} + +.iconContainer { + flex-shrink: 0; + color: #b45309; + font-size: 1.2rem; +} + +.message { + flex: 1; + color: #b45309; + font-size: 0.9rem; + font-weight: var(--font-weight-medium); + line-height: 1.4; +} + +.dismissButton { + flex-shrink: 0; + background: none; + border: none; + color: #b45309; + cursor: pointer; + padding: var(--spacing-xs); + border-radius: var(--border-radius-sm); + transition: var(--transition-fast); + display: flex; + align-items: center; + justify-content: center; + font-size: 1rem; + width: fit-content; +} + +.dismissButton:hover { + background-color: rgba(180, 83, 9, 0.1); + color: #92400e; +} + +.dismissButton:focus { + outline: 2px solid #f59e0b; + outline-offset: 2px; +} + +/* Dark mode adjustments */ +:global([data-theme="dark"]) .banner { + background-color: #92400e; + border-bottom-color: #fbbf24; +} + +:global([data-theme="dark"]) .iconContainer, +:global([data-theme="dark"]) .message, +:global([data-theme="dark"]) .dismissButton { + color: #fcd34d; +} + +:global([data-theme="dark"]) .dismissButton:hover { + background-color: rgba(252, 211, 77, 0.15); + color: #fbbf24; +} + +:global([data-theme="dark"]) .dismissButton:focus { + outline-color: #fbbf24; +} + +/* Mobile responsiveness */ +@media (max-width: 768px) { + .content { + padding: 0 var(--spacing-lg); + } + + .message { + font-size: 0.85rem; + } + + .iconContainer { + font-size: 1.1rem; + } +} \ No newline at end of file diff --git a/my-app/src/components/ThemeToggle.jsx b/my-app/src/components/ThemeToggle.jsx index 3d6ed5a..fcfde11 100644 --- a/my-app/src/components/ThemeToggle.jsx +++ b/my-app/src/components/ThemeToggle.jsx @@ -12,14 +12,7 @@ export const ThemeToggle = () => { aria-label={`Switch to ${isDarkMode ? 'light' : 'dark'} mode`} title={`Switch to ${isDarkMode ? 'light' : 'dark'} mode`} > -
-
-
-
- - {isDarkMode ? '🌙' : '☀️'} - -
+ ); }; \ No newline at end of file diff --git a/my-app/src/components/ThemeToggle.module.css b/my-app/src/components/ThemeToggle.module.css index c361983..b6f608c 100644 --- a/my-app/src/components/ThemeToggle.module.css +++ b/my-app/src/components/ThemeToggle.module.css @@ -1,107 +1,34 @@ .toggleButton { - background: none; - border: none; + background-color: var(--bg-secondary); + border: 1px solid var(--border-light); cursor: pointer; - padding: var(--spacing-xs); - border-radius: var(--border-radius-md); + padding: 0; + border-radius: 50%; transition: var(--transition-fast); + color: var(--text-primary); + font-size: 1rem; display: flex; align-items: center; justify-content: center; + width: 36px; + height: 36px; + box-shadow: var(--shadow-sm); -webkit-tap-highlight-color: transparent; } .toggleButton:hover { background-color: var(--bg-muted); + border-color: var(--border-medium); + box-shadow: var(--shadow-md); + transform: translateY(-1px); } -.toggleContainer { - display: flex; - align-items: center; - gap: var(--spacing-sm); +.toggleButton:active { + transform: translateY(0); + box-shadow: var(--shadow-sm); } -.toggle { - width: 44px; - height: 24px; - border-radius: 12px; - position: relative; - transition: var(--transition-medium); - border: 1px solid var(--border-medium); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -} - -.toggle.light { - background: linear-gradient(to bottom, #ffffff, #f0f0f0); -} - -.toggle.dark { - background: linear-gradient(to bottom, #4a4a4a, #2a2a2a); -} - -.toggleHandle { - width: 18px; - height: 18px; - border-radius: 50%; - background: linear-gradient(to bottom, #ffffff, #e0e0e0); - border: 1px solid rgba(0, 0, 0, 0.1); - position: absolute; - top: 50%; - transform: translateY(-50%); - transition: var(--transition-medium); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); -} - -.toggle.light .toggleHandle { - left: 2px; - background: linear-gradient(to bottom, #ffd700, #ffed4a); - border-color: rgba(255, 165, 0, 0.3); -} - -.toggle.dark .toggleHandle { - left: calc(100% - 20px); - background: linear-gradient(to bottom, #e6e6e6, #cccccc); - border-color: rgba(0, 0, 0, 0.2); -} - -.toggleLabel { - font-size: var(--font-size-lg); - line-height: 1; - user-select: none; - min-width: 20px; - text-align: center; -} - -/* iPhone-style pressed state */ -.toggleButton:active .toggle { - transform: scale(0.95); -} - -.toggleButton:active .toggleHandle { - width: 20px; -} - -/* Responsive adjustments */ -@media (max-width: 768px) { - .toggleContainer { - gap: var(--spacing-xs); - } - - .toggle { - width: 40px; - height: 22px; - } - - .toggleHandle { - width: 16px; - height: 16px; - } - - .toggle.dark .toggleHandle { - left: calc(100% - 18px); - } - - .toggleLabel { - font-size: var(--font-size-md); - } +.toggleButton:focus { + outline: 2px solid var(--color-primary); + outline-offset: 2px; } \ No newline at end of file diff --git a/my-app/src/pages/Profile.jsx b/my-app/src/pages/Profile.jsx new file mode 100644 index 0000000..45eaff2 --- /dev/null +++ b/my-app/src/pages/Profile.jsx @@ -0,0 +1,102 @@ +import React from 'react'; +import { useSettingsContext } from '../context/SettingsContext'; +import PlaceholderBanner from '../components/PlaceholderBanner'; +import styles from './Profile.module.css'; + +const Profile = () => { + const { getCurrentUser } = useSettingsContext(); + const user = getCurrentUser(); + + // Helper function to get user's initials + const getInitials = (name) => { + return name.split(' ').map(word => word[0]).join('').toUpperCase(); + }; + + return ( + <> + +
+
+
+
+ {getInitials(user.name)} +
+
+
+

{user.name}

+

{user.email}

+

@{user.username}

+
+
+ +
+
+

Personlig information

+
+
+ + {user.name} +
+
+ + {user.email} +
+
+ + {user.username} +
+
+ + {user.id} +
+
+
+ +
+

Inställningar

+
+
+
+

Notifikationer

+

Hantera dina notifikationsinställningar

+
+ +
+
+
+

Integritet

+

Kontrollera dina sekretessinställningar

+
+ +
+
+
+ +
+

Aktivitet

+
+
+
📅
+
+

Senaste bokning

+

Team standup - G5:7

+ 3 sep 2025 +
+
+
+
📚
+
+

Senaste kursaktivitet

+

Prototyper inom interaktionsdesign

+ 2 sep 2025 +
+
+
+
+
+
+ + ); +}; + +export default Profile; \ No newline at end of file diff --git a/my-app/src/pages/Profile.module.css b/my-app/src/pages/Profile.module.css new file mode 100644 index 0000000..319e09b --- /dev/null +++ b/my-app/src/pages/Profile.module.css @@ -0,0 +1,232 @@ +.container { + max-width: 1200px; + margin: 0 auto; + padding: var(--spacing-2xl); + min-height: 100vh; + background-color: var(--bg-primary); +} + +.header { + display: flex; + align-items: center; + gap: var(--spacing-2xl); + margin-bottom: var(--spacing-3xl); + padding-bottom: var(--spacing-2xl); + border-bottom: 1px solid var(--border-light); +} + +.avatarLarge { + width: 100px; + height: 100px; + flex-shrink: 0; +} + +.avatarInitials { + width: 100%; + height: 100%; + border-radius: 50%; + background-color: var(--color-primary); + color: var(--color-white); + display: flex; + align-items: center; + justify-content: center; + font-size: 2rem; + font-weight: var(--font-weight-bold); +} + +.userInfo { + flex: 1; +} + +.name { + margin: 0 0 var(--spacing-sm) 0; + font-size: 2.5rem; + font-weight: var(--font-weight-bold); + color: var(--text-primary); +} + +.email { + margin: 0 0 var(--spacing-xs) 0; + font-size: 1.1rem; + color: var(--text-secondary); +} + +.username { + margin: 0; + font-size: 1rem; + color: var(--text-muted); + font-weight: var(--font-weight-medium); +} + +.content { + display: grid; + gap: var(--spacing-3xl); +} + +.section { + background-color: var(--bg-secondary); + border: 1px solid var(--border-light); + border-radius: var(--border-radius-lg); + padding: var(--spacing-2xl); +} + +.section h2 { + margin: 0 0 var(--spacing-xl) 0; + font-size: 1.5rem; + font-weight: var(--font-weight-semibold); + color: var(--text-primary); +} + +.infoGrid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: var(--spacing-lg); +} + +.infoItem { + display: flex; + flex-direction: column; + gap: var(--spacing-xs); +} + +.infoItem label { + font-size: 0.875rem; + font-weight: var(--font-weight-semibold); + color: var(--text-secondary); + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.infoItem span { + font-size: 1rem; + color: var(--text-primary); + padding: var(--spacing-sm) var(--spacing-md); + background-color: var(--bg-tertiary); + border-radius: var(--border-radius-md); + border: 1px solid var(--border-light); +} + +.settingsGrid { + display: grid; + gap: var(--spacing-lg); +} + +.settingItem { + display: flex; + align-items: center; + justify-content: space-between; + padding: var(--spacing-lg); + background-color: var(--bg-tertiary); + border-radius: var(--border-radius-md); + border: 1px solid var(--border-light); +} + +.settingInfo h3 { + margin: 0 0 var(--spacing-xs) 0; + font-size: 1.1rem; + font-weight: var(--font-weight-semibold); + color: var(--text-primary); +} + +.settingInfo p { + margin: 0; + font-size: 0.9rem; + color: var(--text-secondary); +} + +.settingButton { + padding: var(--spacing-sm) var(--spacing-lg); + background-color: var(--color-primary); + color: var(--color-white); + border: none; + border-radius: var(--border-radius-md); + font-size: 0.9rem; + font-weight: var(--font-weight-medium); + cursor: pointer; + transition: var(--transition-fast); + flex-shrink: 0; + width: fit-content; + height: fit-content; +} + +.settingButton:hover { + background-color: var(--color-primary-hover, var(--color-primary)); + transform: translateY(-1px); +} + +.activityList { + display: grid; + gap: var(--spacing-lg); +} + +.activityItem { + display: flex; + align-items: flex-start; + gap: var(--spacing-lg); + padding: var(--spacing-lg); + background-color: var(--bg-tertiary); + border-radius: var(--border-radius-md); + border: 1px solid var(--border-light); +} + +.activityIcon { + font-size: 1.5rem; + flex-shrink: 0; + margin-top: var(--spacing-xs); +} + +.activityInfo { + flex: 1; +} + +.activityInfo h4 { + margin: 0 0 var(--spacing-xs) 0; + font-size: 1rem; + font-weight: var(--font-weight-semibold); + color: var(--text-primary); +} + +.activityInfo p { + margin: 0 0 var(--spacing-xs) 0; + color: var(--text-secondary); +} + +.activityDate { + font-size: 0.875rem; + color: var(--text-muted); +} + +/* Mobile responsiveness */ +@media (max-width: 768px) { + .container { + padding: var(--spacing-lg); + } + + .header { + flex-direction: column; + text-align: center; + gap: var(--spacing-lg); + } + + .name { + font-size: 2rem; + } + + .infoGrid { + grid-template-columns: 1fr; + } + + .settingItem { + flex-direction: column; + align-items: flex-start; + gap: var(--spacing-md); + } + + .settingButton { + align-self: stretch; + } + + .section { + padding: var(--spacing-lg); + } +} \ No newline at end of file -- 2.39.5 From 78b213890fe9d44238ef8e8129cbab9e4b18f119 Mon Sep 17 00:00:00 2001 From: Jacob Reinikainen <80760206+jazzjacob@users.noreply.github.com> Date: Fri, 5 Sep 2025 15:24:52 +0200 Subject: [PATCH 2/3] change directory structure --- my-app/src/AppRoutes.jsx | 1 - my-app/src/Layout.jsx | 2 +- my-app/src/components/{ => booking}/BookingCard.jsx | 12 ++++++------ .../components/{ => booking}/BookingCard.module.css | 0 .../components/{ => booking}/BookingDetailsModal.jsx | 0 .../{ => booking}/BookingDetailsModal.module.css | 0 my-app/src/components/{ => booking}/BookingModal.jsx | 8 ++++---- .../components/{ => booking}/BookingModal.module.css | 0 my-app/src/components/{ => booking}/BookingsList.jsx | 2 +- .../components/{ => booking}/BookingsList.module.css | 0 .../components/{ => booking}/InlineBookingForm.jsx | 12 ++++++------ .../{ => booking}/InlineBookingForm.module.css | 0 my-app/src/components/{ => common}/ContentLoader.jsx | 0 .../components/{ => common}/ContentLoader.module.css | 0 .../src/components/{ => common}/FullScreenLoader.jsx | 0 .../{ => common}/FullScreenLoader.module.css | 0 .../components/{ => common}/NotificationBanner.jsx | 2 +- .../{ => common}/NotificationBanner.module.css | 0 .../components/{ => common}/PlaceholderBanner.jsx | 0 .../{ => common}/PlaceholderBanner.module.css | 0 .../src/components/{ => forms}/BookingDatePicker.jsx | 8 ++++---- .../components/{ => forms}/BookingLengthField.jsx | 6 +++--- .../{ => forms}/BookingLengthField.module.css | 0 .../src/components/{ => forms}/BookingTitleField.jsx | 4 ++-- .../{ => forms}/BookingTitleField.module.css | 0 .../src/components/{ => forms}/ParticipantsField.jsx | 0 .../{ => forms}/ParticipantsField.module.css | 0 .../components/{ => forms}/ParticipantsSelector.jsx | 6 +++--- .../{ => forms}/ParticipantsSelector.module.css | 0 .../components/{ => forms}/RoomSelectionField.jsx | 7 +++---- .../{ => forms}/RoomSelectionField.module.css | 0 my-app/src/components/{ => layout}/Navigation.jsx | 2 +- .../components/{ => layout}/Navigation.module.css | 0 my-app/src/components/{ => layout}/PageWrapper.jsx | 0 my-app/src/components/{ => layout}/ThemeToggle.jsx | 2 +- .../components/{ => layout}/ThemeToggle.module.css | 0 my-app/src/components/{ => ui}/Card.jsx | 0 my-app/src/components/{ => ui}/Card.module.css | 0 my-app/src/components/{ => ui}/ComboBox.jsx | 0 my-app/src/components/{ => ui}/ComboBox.module.css | 0 my-app/src/components/{ => ui}/Dropdown.jsx | 0 my-app/src/components/{ => ui}/Dropdown.module.css | 0 my-app/src/components/{ => ui}/TimeCard.jsx | 2 +- my-app/src/components/{ => ui}/TimeCard.module.css | 0 my-app/src/components/{ => ui}/TimeCardContainer.jsx | 10 +++++----- .../components/{ => ui}/TimeCardContainer.module.css | 0 my-app/src/pages/NewBooking.jsx | 12 ++++++------ my-app/src/pages/Profile.jsx | 2 +- my-app/src/pages/RoomBooking.jsx | 4 ++-- 49 files changed, 51 insertions(+), 53 deletions(-) rename my-app/src/components/{ => booking}/BookingCard.jsx (95%) rename my-app/src/components/{ => booking}/BookingCard.module.css (100%) rename my-app/src/components/{ => booking}/BookingDetailsModal.jsx (100%) rename my-app/src/components/{ => booking}/BookingDetailsModal.module.css (100%) rename my-app/src/components/{ => booking}/BookingModal.jsx (96%) rename my-app/src/components/{ => booking}/BookingModal.module.css (100%) rename my-app/src/components/{ => booking}/BookingsList.jsx (97%) rename my-app/src/components/{ => booking}/BookingsList.module.css (100%) rename my-app/src/components/{ => booking}/InlineBookingForm.jsx (93%) rename my-app/src/components/{ => booking}/InlineBookingForm.module.css (100%) rename my-app/src/components/{ => common}/ContentLoader.jsx (100%) rename my-app/src/components/{ => common}/ContentLoader.module.css (100%) rename my-app/src/components/{ => common}/FullScreenLoader.jsx (100%) rename my-app/src/components/{ => common}/FullScreenLoader.module.css (100%) rename my-app/src/components/{ => common}/NotificationBanner.jsx (97%) rename my-app/src/components/{ => common}/NotificationBanner.module.css (100%) rename my-app/src/components/{ => common}/PlaceholderBanner.jsx (100%) rename my-app/src/components/{ => common}/PlaceholderBanner.module.css (100%) rename my-app/src/components/{ => forms}/BookingDatePicker.jsx (81%) rename my-app/src/components/{ => forms}/BookingLengthField.jsx (74%) rename my-app/src/components/{ => forms}/BookingLengthField.module.css (100%) rename my-app/src/components/{ => forms}/BookingTitleField.jsx (81%) rename my-app/src/components/{ => forms}/BookingTitleField.module.css (100%) rename my-app/src/components/{ => forms}/ParticipantsField.jsx (100%) rename my-app/src/components/{ => forms}/ParticipantsField.module.css (100%) rename my-app/src/components/{ => forms}/ParticipantsSelector.jsx (97%) rename my-app/src/components/{ => forms}/ParticipantsSelector.module.css (100%) rename my-app/src/components/{ => forms}/RoomSelectionField.jsx (76%) rename my-app/src/components/{ => forms}/RoomSelectionField.module.css (100%) rename my-app/src/components/{ => layout}/Navigation.jsx (98%) rename my-app/src/components/{ => layout}/Navigation.module.css (100%) rename my-app/src/components/{ => layout}/PageWrapper.jsx (100%) rename my-app/src/components/{ => layout}/ThemeToggle.jsx (89%) rename my-app/src/components/{ => layout}/ThemeToggle.module.css (100%) rename my-app/src/components/{ => ui}/Card.jsx (100%) rename my-app/src/components/{ => ui}/Card.module.css (100%) rename my-app/src/components/{ => ui}/ComboBox.jsx (100%) rename my-app/src/components/{ => ui}/ComboBox.module.css (100%) rename my-app/src/components/{ => ui}/Dropdown.jsx (100%) rename my-app/src/components/{ => ui}/Dropdown.module.css (100%) rename my-app/src/components/{ => ui}/TimeCard.jsx (97%) rename my-app/src/components/{ => ui}/TimeCard.module.css (100%) rename my-app/src/components/{ => ui}/TimeCardContainer.jsx (94%) rename my-app/src/components/{ => ui}/TimeCardContainer.module.css (100%) diff --git a/my-app/src/AppRoutes.jsx b/my-app/src/AppRoutes.jsx index cc94ee4..92e41cb 100644 --- a/my-app/src/AppRoutes.jsx +++ b/my-app/src/AppRoutes.jsx @@ -9,7 +9,6 @@ import { BookingSettings } from './pages/BookingSettings'; import { CourseSchedule } from './pages/CourseSchedule'; import { CourseScheduleView } from './pages/CourseScheduleView'; import { TestSession } from './pages/TestSession'; -import FullScreenLoader from './components/FullScreenLoader'; import Home from './pages/Home'; import CoursePage from './pages/CoursePage'; import Profile from './pages/Profile'; diff --git a/my-app/src/Layout.jsx b/my-app/src/Layout.jsx index 3197c44..05383dd 100644 --- a/my-app/src/Layout.jsx +++ b/my-app/src/Layout.jsx @@ -1,7 +1,7 @@ // components/Layout.jsx import React from 'react'; import { Outlet, Link } from 'react-router-dom'; -import Navigation from './components/Navigation'; +import Navigation from './components/layout/Navigation'; export default function Layout() { return ( diff --git a/my-app/src/components/BookingCard.jsx b/my-app/src/components/booking/BookingCard.jsx similarity index 95% rename from my-app/src/components/BookingCard.jsx rename to my-app/src/components/booking/BookingCard.jsx index f9ffca4..2dadc87 100644 --- a/my-app/src/components/BookingCard.jsx +++ b/my-app/src/components/booking/BookingCard.jsx @@ -1,12 +1,12 @@ import React, { useState, useEffect, useRef } from 'react'; import { Button } from 'react-aria-components'; import styles from './BookingCard.module.css'; -import { convertDateObjectToString } from '../helpers'; -import Dropdown from './Dropdown'; -import { BookingTitleField } from './BookingTitleField'; -import { ParticipantsSelector } from './ParticipantsSelector'; -import { BookingProvider } from '../context/BookingContext'; -import { PEOPLE } from '../constants/bookingConstants'; +import { convertDateObjectToString } from '../../helpers'; +import Dropdown from '../ui/Dropdown'; +import { BookingTitleField } from '../forms/BookingTitleField'; +import { ParticipantsSelector } from '../forms/ParticipantsSelector'; +import { BookingProvider } from '../../context/BookingContext'; +import { PEOPLE } from '../../constants/bookingConstants'; function BookingCard({ booking, onClick, isExpanded, onBookingUpdate, onBookingDelete }) { const [selectedLength, setSelectedLength] = useState(null); diff --git a/my-app/src/components/BookingCard.module.css b/my-app/src/components/booking/BookingCard.module.css similarity index 100% rename from my-app/src/components/BookingCard.module.css rename to my-app/src/components/booking/BookingCard.module.css diff --git a/my-app/src/components/BookingDetailsModal.jsx b/my-app/src/components/booking/BookingDetailsModal.jsx similarity index 100% rename from my-app/src/components/BookingDetailsModal.jsx rename to my-app/src/components/booking/BookingDetailsModal.jsx diff --git a/my-app/src/components/BookingDetailsModal.module.css b/my-app/src/components/booking/BookingDetailsModal.module.css similarity index 100% rename from my-app/src/components/BookingDetailsModal.module.css rename to my-app/src/components/booking/BookingDetailsModal.module.css diff --git a/my-app/src/components/BookingModal.jsx b/my-app/src/components/booking/BookingModal.jsx similarity index 96% rename from my-app/src/components/BookingModal.jsx rename to my-app/src/components/booking/BookingModal.jsx index 0a4945f..30f87fd 100644 --- a/my-app/src/components/BookingModal.jsx +++ b/my-app/src/components/booking/BookingModal.jsx @@ -1,9 +1,9 @@ import React, { useState, useEffect, useRef } from 'react'; import { Button, Dialog, Heading, Modal } from 'react-aria-components'; -import { convertDateObjectToString, getTimeFromIndex } from '../helpers'; -import Dropdown from './Dropdown'; -import { useBookingContext } from '../context/BookingContext'; -import { useSettingsContext } from '../context/SettingsContext'; +import { convertDateObjectToString, getTimeFromIndex } from '../../helpers'; +import Dropdown from '../ui/Dropdown'; +import { useBookingContext } from '../../context/BookingContext'; +import { useSettingsContext } from '../../context/SettingsContext'; import styles from './BookingModal.module.css'; export function BookingModal({ diff --git a/my-app/src/components/BookingModal.module.css b/my-app/src/components/booking/BookingModal.module.css similarity index 100% rename from my-app/src/components/BookingModal.module.css rename to my-app/src/components/booking/BookingModal.module.css diff --git a/my-app/src/components/BookingsList.jsx b/my-app/src/components/booking/BookingsList.jsx similarity index 97% rename from my-app/src/components/BookingsList.jsx rename to my-app/src/components/booking/BookingsList.jsx index 91cc60e..91a2b99 100644 --- a/my-app/src/components/BookingsList.jsx +++ b/my-app/src/components/booking/BookingsList.jsx @@ -2,7 +2,7 @@ import React, { useState } from 'react'; import { CalendarDate } from '@internationalized/date'; import styles from './BookingsList.module.css'; import BookingCard from './BookingCard'; -import NotificationBanner from './NotificationBanner'; +import NotificationBanner from '../common/NotificationBanner'; function BookingsList({ bookings, handleEditBooking, onBookingUpdate, onBookingDelete, showSuccessBanner, lastCreatedBooking, onDismissBanner, showDeleteBanner, lastDeletedBooking, onDismissDeleteBanner, showDevelopmentBanner, showBookingConfirmationBanner, showBookingDeleteBanner }) { const [showAll, setShowAll] = useState(false); diff --git a/my-app/src/components/BookingsList.module.css b/my-app/src/components/booking/BookingsList.module.css similarity index 100% rename from my-app/src/components/BookingsList.module.css rename to my-app/src/components/booking/BookingsList.module.css diff --git a/my-app/src/components/InlineBookingForm.jsx b/my-app/src/components/booking/InlineBookingForm.jsx similarity index 93% rename from my-app/src/components/InlineBookingForm.jsx rename to my-app/src/components/booking/InlineBookingForm.jsx index 7a3396a..711f4de 100644 --- a/my-app/src/components/InlineBookingForm.jsx +++ b/my-app/src/components/booking/InlineBookingForm.jsx @@ -1,11 +1,11 @@ import React, { useState, useEffect, useRef } from 'react'; import { Button } from 'react-aria-components'; -import { convertDateObjectToString, getTimeFromIndex } from '../helpers'; -import Dropdown from './Dropdown'; -import { BookingTitleField } from './BookingTitleField'; -import { ParticipantsSelector } from './ParticipantsSelector'; -import { useBookingContext } from '../context/BookingContext'; -import { useSettingsContext } from '../context/SettingsContext'; +import { convertDateObjectToString, getTimeFromIndex } from '../../helpers'; +import Dropdown from '../ui/Dropdown'; +import { BookingTitleField } from '../forms/BookingTitleField'; +import { ParticipantsSelector } from '../forms/ParticipantsSelector'; +import { useBookingContext } from '../../context/BookingContext'; +import { useSettingsContext } from '../../context/SettingsContext'; import styles from './InlineBookingForm.module.css'; export function InlineBookingForm({ diff --git a/my-app/src/components/InlineBookingForm.module.css b/my-app/src/components/booking/InlineBookingForm.module.css similarity index 100% rename from my-app/src/components/InlineBookingForm.module.css rename to my-app/src/components/booking/InlineBookingForm.module.css diff --git a/my-app/src/components/ContentLoader.jsx b/my-app/src/components/common/ContentLoader.jsx similarity index 100% rename from my-app/src/components/ContentLoader.jsx rename to my-app/src/components/common/ContentLoader.jsx diff --git a/my-app/src/components/ContentLoader.module.css b/my-app/src/components/common/ContentLoader.module.css similarity index 100% rename from my-app/src/components/ContentLoader.module.css rename to my-app/src/components/common/ContentLoader.module.css diff --git a/my-app/src/components/FullScreenLoader.jsx b/my-app/src/components/common/FullScreenLoader.jsx similarity index 100% rename from my-app/src/components/FullScreenLoader.jsx rename to my-app/src/components/common/FullScreenLoader.jsx diff --git a/my-app/src/components/FullScreenLoader.module.css b/my-app/src/components/common/FullScreenLoader.module.css similarity index 100% rename from my-app/src/components/FullScreenLoader.module.css rename to my-app/src/components/common/FullScreenLoader.module.css diff --git a/my-app/src/components/NotificationBanner.jsx b/my-app/src/components/common/NotificationBanner.jsx similarity index 97% rename from my-app/src/components/NotificationBanner.jsx rename to my-app/src/components/common/NotificationBanner.jsx index 37e4108..55b809c 100644 --- a/my-app/src/components/NotificationBanner.jsx +++ b/my-app/src/components/common/NotificationBanner.jsx @@ -1,6 +1,6 @@ import React, { useState } from 'react'; import styles from './NotificationBanner.module.css'; -import { convertDateObjectToString } from '../helpers'; +import { convertDateObjectToString } from '../../helpers'; const BANNER_VARIANTS = { success: { diff --git a/my-app/src/components/NotificationBanner.module.css b/my-app/src/components/common/NotificationBanner.module.css similarity index 100% rename from my-app/src/components/NotificationBanner.module.css rename to my-app/src/components/common/NotificationBanner.module.css diff --git a/my-app/src/components/PlaceholderBanner.jsx b/my-app/src/components/common/PlaceholderBanner.jsx similarity index 100% rename from my-app/src/components/PlaceholderBanner.jsx rename to my-app/src/components/common/PlaceholderBanner.jsx diff --git a/my-app/src/components/PlaceholderBanner.module.css b/my-app/src/components/common/PlaceholderBanner.module.css similarity index 100% rename from my-app/src/components/PlaceholderBanner.module.css rename to my-app/src/components/common/PlaceholderBanner.module.css diff --git a/my-app/src/components/BookingDatePicker.jsx b/my-app/src/components/forms/BookingDatePicker.jsx similarity index 81% rename from my-app/src/components/BookingDatePicker.jsx rename to my-app/src/components/forms/BookingDatePicker.jsx index 6bf5e0e..91ee437 100644 --- a/my-app/src/components/BookingDatePicker.jsx +++ b/my-app/src/components/forms/BookingDatePicker.jsx @@ -1,8 +1,8 @@ import React from 'react'; -import { DatePicker } from '../react-aria-starter/src/DatePicker'; -import { getFutureDate, isDateUnavailable } from '../utils/bookingUtils'; -import { useBookingContext } from '../context/BookingContext'; -import { useSettingsContext } from '../context/SettingsContext'; +import { DatePicker } from '../../react-aria-starter/src/DatePicker'; +import { getFutureDate, isDateUnavailable } from '../../utils/bookingUtils'; +import { useBookingContext } from '../../context/BookingContext'; +import { useSettingsContext } from '../../context/SettingsContext'; export function BookingDatePicker() { const booking = useBookingContext(); diff --git a/my-app/src/components/BookingLengthField.jsx b/my-app/src/components/forms/BookingLengthField.jsx similarity index 74% rename from my-app/src/components/BookingLengthField.jsx rename to my-app/src/components/forms/BookingLengthField.jsx index 5af8eac..faf19d4 100644 --- a/my-app/src/components/BookingLengthField.jsx +++ b/my-app/src/components/forms/BookingLengthField.jsx @@ -1,7 +1,7 @@ import React from 'react'; -import Dropdown from './Dropdown'; -import { BOOKING_LENGTHS } from '../constants/bookingConstants'; -import { useBookingContext } from '../context/BookingContext'; +import Dropdown from '../ui/Dropdown'; +import { BOOKING_LENGTHS } from '../../constants/bookingConstants'; +import { useBookingContext } from '../../context/BookingContext'; import styles from './BookingLengthField.module.css'; export function BookingLengthField() { diff --git a/my-app/src/components/BookingLengthField.module.css b/my-app/src/components/forms/BookingLengthField.module.css similarity index 100% rename from my-app/src/components/BookingLengthField.module.css rename to my-app/src/components/forms/BookingLengthField.module.css diff --git a/my-app/src/components/BookingTitleField.jsx b/my-app/src/components/forms/BookingTitleField.jsx similarity index 81% rename from my-app/src/components/BookingTitleField.jsx rename to my-app/src/components/forms/BookingTitleField.jsx index 71eca53..2c517bf 100644 --- a/my-app/src/components/BookingTitleField.jsx +++ b/my-app/src/components/forms/BookingTitleField.jsx @@ -1,6 +1,6 @@ import React from 'react'; -import { useBookingContext } from '../context/BookingContext'; -import { useSettingsContext } from '../context/SettingsContext'; +import { useBookingContext } from '../../context/BookingContext'; +import { useSettingsContext } from '../../context/SettingsContext'; import styles from './BookingTitleField.module.css'; export function BookingTitleField({ compact = false }) { diff --git a/my-app/src/components/BookingTitleField.module.css b/my-app/src/components/forms/BookingTitleField.module.css similarity index 100% rename from my-app/src/components/BookingTitleField.module.css rename to my-app/src/components/forms/BookingTitleField.module.css diff --git a/my-app/src/components/ParticipantsField.jsx b/my-app/src/components/forms/ParticipantsField.jsx similarity index 100% rename from my-app/src/components/ParticipantsField.jsx rename to my-app/src/components/forms/ParticipantsField.jsx diff --git a/my-app/src/components/ParticipantsField.module.css b/my-app/src/components/forms/ParticipantsField.module.css similarity index 100% rename from my-app/src/components/ParticipantsField.module.css rename to my-app/src/components/forms/ParticipantsField.module.css diff --git a/my-app/src/components/ParticipantsSelector.jsx b/my-app/src/components/forms/ParticipantsSelector.jsx similarity index 97% rename from my-app/src/components/ParticipantsSelector.jsx rename to my-app/src/components/forms/ParticipantsSelector.jsx index d3f1d9d..4a7a621 100644 --- a/my-app/src/components/ParticipantsSelector.jsx +++ b/my-app/src/components/forms/ParticipantsSelector.jsx @@ -1,7 +1,7 @@ import React, { useState, useRef, useEffect } from 'react'; -import { PEOPLE, USER } from '../constants/bookingConstants'; -import { useBookingContext } from '../context/BookingContext'; -import { useSettingsContext } from '../context/SettingsContext'; +import { PEOPLE, USER } from '../../constants/bookingConstants'; +import { useBookingContext } from '../../context/BookingContext'; +import { useSettingsContext } from '../../context/SettingsContext'; import styles from './ParticipantsSelector.module.css'; export function ParticipantsSelector({ compact = false }) { diff --git a/my-app/src/components/ParticipantsSelector.module.css b/my-app/src/components/forms/ParticipantsSelector.module.css similarity index 100% rename from my-app/src/components/ParticipantsSelector.module.css rename to my-app/src/components/forms/ParticipantsSelector.module.css diff --git a/my-app/src/components/RoomSelectionField.jsx b/my-app/src/components/forms/RoomSelectionField.jsx similarity index 76% rename from my-app/src/components/RoomSelectionField.jsx rename to my-app/src/components/forms/RoomSelectionField.jsx index 7174dc4..30923b9 100644 --- a/my-app/src/components/RoomSelectionField.jsx +++ b/my-app/src/components/forms/RoomSelectionField.jsx @@ -1,8 +1,7 @@ import React, { useMemo } from 'react'; -import Dropdown from './Dropdown'; -import { SMALL_GROUP_ROOMS } from '../constants/bookingConstants'; -import { useBookingContext } from '../context/BookingContext'; -import { useSettingsContext } from '../context/SettingsContext'; +import Dropdown from '../ui/Dropdown'; +import { useBookingContext } from '../../context/BookingContext'; +import { useSettingsContext } from '../../context/SettingsContext'; import styles from './RoomSelectionField.module.css'; export function RoomSelectionField() { diff --git a/my-app/src/components/RoomSelectionField.module.css b/my-app/src/components/forms/RoomSelectionField.module.css similarity index 100% rename from my-app/src/components/RoomSelectionField.module.css rename to my-app/src/components/forms/RoomSelectionField.module.css diff --git a/my-app/src/components/Navigation.jsx b/my-app/src/components/layout/Navigation.jsx similarity index 98% rename from my-app/src/components/Navigation.jsx rename to my-app/src/components/layout/Navigation.jsx index 87538fd..c8207d0 100644 --- a/my-app/src/components/Navigation.jsx +++ b/my-app/src/components/layout/Navigation.jsx @@ -2,7 +2,7 @@ import React, { useState } from 'react'; import styles from './Navigation.module.css'; // Import the CSS Module import { Link, useLocation } from 'react-router-dom'; import { ThemeToggle } from './ThemeToggle'; -import { useSettingsContext } from '../context/SettingsContext'; +import { useSettingsContext } from '../../context/SettingsContext'; import 'bootstrap-icons/font/bootstrap-icons.css'; diff --git a/my-app/src/components/Navigation.module.css b/my-app/src/components/layout/Navigation.module.css similarity index 100% rename from my-app/src/components/Navigation.module.css rename to my-app/src/components/layout/Navigation.module.css diff --git a/my-app/src/components/PageWrapper.jsx b/my-app/src/components/layout/PageWrapper.jsx similarity index 100% rename from my-app/src/components/PageWrapper.jsx rename to my-app/src/components/layout/PageWrapper.jsx diff --git a/my-app/src/components/ThemeToggle.jsx b/my-app/src/components/layout/ThemeToggle.jsx similarity index 89% rename from my-app/src/components/ThemeToggle.jsx rename to my-app/src/components/layout/ThemeToggle.jsx index fcfde11..c22ca1a 100644 --- a/my-app/src/components/ThemeToggle.jsx +++ b/my-app/src/components/layout/ThemeToggle.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import { useTheme } from '../context/ThemeContext'; +import { useTheme } from '../../context/ThemeContext'; import styles from './ThemeToggle.module.css'; export const ThemeToggle = () => { diff --git a/my-app/src/components/ThemeToggle.module.css b/my-app/src/components/layout/ThemeToggle.module.css similarity index 100% rename from my-app/src/components/ThemeToggle.module.css rename to my-app/src/components/layout/ThemeToggle.module.css diff --git a/my-app/src/components/Card.jsx b/my-app/src/components/ui/Card.jsx similarity index 100% rename from my-app/src/components/Card.jsx rename to my-app/src/components/ui/Card.jsx diff --git a/my-app/src/components/Card.module.css b/my-app/src/components/ui/Card.module.css similarity index 100% rename from my-app/src/components/Card.module.css rename to my-app/src/components/ui/Card.module.css diff --git a/my-app/src/components/ComboBox.jsx b/my-app/src/components/ui/ComboBox.jsx similarity index 100% rename from my-app/src/components/ComboBox.jsx rename to my-app/src/components/ui/ComboBox.jsx diff --git a/my-app/src/components/ComboBox.module.css b/my-app/src/components/ui/ComboBox.module.css similarity index 100% rename from my-app/src/components/ComboBox.module.css rename to my-app/src/components/ui/ComboBox.module.css diff --git a/my-app/src/components/Dropdown.jsx b/my-app/src/components/ui/Dropdown.jsx similarity index 100% rename from my-app/src/components/Dropdown.jsx rename to my-app/src/components/ui/Dropdown.jsx diff --git a/my-app/src/components/Dropdown.module.css b/my-app/src/components/ui/Dropdown.module.css similarity index 100% rename from my-app/src/components/Dropdown.module.css rename to my-app/src/components/ui/Dropdown.module.css diff --git a/my-app/src/components/TimeCard.jsx b/my-app/src/components/ui/TimeCard.jsx similarity index 97% rename from my-app/src/components/TimeCard.jsx rename to my-app/src/components/ui/TimeCard.jsx index 0111367..6054129 100644 --- a/my-app/src/components/TimeCard.jsx +++ b/my-app/src/components/ui/TimeCard.jsx @@ -1,7 +1,7 @@ import { Button } from 'react-aria-components'; import React from 'react'; import styles from './TimeCard.module.css'; -import { useBookingContext } from '../context/BookingContext'; +import { useBookingContext } from '../../context/BookingContext'; export default function TimeCard({ startTimeIndex, diff --git a/my-app/src/components/TimeCard.module.css b/my-app/src/components/ui/TimeCard.module.css similarity index 100% rename from my-app/src/components/TimeCard.module.css rename to my-app/src/components/ui/TimeCard.module.css diff --git a/my-app/src/components/TimeCardContainer.jsx b/my-app/src/components/ui/TimeCardContainer.jsx similarity index 94% rename from my-app/src/components/TimeCardContainer.jsx rename to my-app/src/components/ui/TimeCardContainer.jsx index 80844ca..2c897a4 100644 --- a/my-app/src/components/TimeCardContainer.jsx +++ b/my-app/src/components/ui/TimeCardContainer.jsx @@ -1,11 +1,11 @@ import React from 'react'; import TimeCard from './TimeCard'; -import { InlineBookingForm } from './InlineBookingForm'; -import { BookingModal } from './BookingModal'; +import { InlineBookingForm } from '../booking/InlineBookingForm'; +import { BookingModal } from '../booking/BookingModal'; import styles from './TimeCardContainer.module.css'; -import modalStyles from './BookingModal.module.css'; -import { useBookingContext } from '../context/BookingContext'; -import { useSettingsContext } from '../context/SettingsContext'; +import modalStyles from '../booking/BookingModal.module.css'; +import { useBookingContext } from '../../context/BookingContext'; +import { useSettingsContext } from '../../context/SettingsContext'; const SLOT_GROUPING_SIZE = 8; diff --git a/my-app/src/components/TimeCardContainer.module.css b/my-app/src/components/ui/TimeCardContainer.module.css similarity index 100% rename from my-app/src/components/TimeCardContainer.module.css rename to my-app/src/components/ui/TimeCardContainer.module.css diff --git a/my-app/src/pages/NewBooking.jsx b/my-app/src/pages/NewBooking.jsx index af1ba53..80c79b0 100644 --- a/my-app/src/pages/NewBooking.jsx +++ b/my-app/src/pages/NewBooking.jsx @@ -1,11 +1,11 @@ import React, { useState, useEffect } from 'react'; import styles from './NewBooking.module.css'; -import { TimeCardContainer } from '../components/TimeCardContainer'; -import { BookingDatePicker } from '../components/BookingDatePicker'; -import { BookingTitleField } from '../components/BookingTitleField'; -import { ParticipantsSelector } from '../components/ParticipantsSelector'; -import { RoomSelectionField } from '../components/RoomSelectionField'; -import { BookingLengthField } from '../components/BookingLengthField'; +import { TimeCardContainer } from '../components/ui/TimeCardContainer'; +import { BookingDatePicker } from '../components/forms/BookingDatePicker'; +import { BookingTitleField } from '../components/forms/BookingTitleField'; +import { ParticipantsSelector } from '../components/forms/ParticipantsSelector'; +import { RoomSelectionField } from '../components/forms/RoomSelectionField'; +import { BookingLengthField } from '../components/forms/BookingLengthField'; import { useBookingState } from '../hooks/useBookingState'; import { BookingProvider } from '../context/BookingContext'; import { useSettingsContext } from '../context/SettingsContext'; diff --git a/my-app/src/pages/Profile.jsx b/my-app/src/pages/Profile.jsx index 45eaff2..a2d087d 100644 --- a/my-app/src/pages/Profile.jsx +++ b/my-app/src/pages/Profile.jsx @@ -1,6 +1,6 @@ import React from 'react'; import { useSettingsContext } from '../context/SettingsContext'; -import PlaceholderBanner from '../components/PlaceholderBanner'; +import PlaceholderBanner from '../components/common/PlaceholderBanner'; import styles from './Profile.module.css'; const Profile = () => { diff --git a/my-app/src/pages/RoomBooking.jsx b/my-app/src/pages/RoomBooking.jsx index c20b2c1..6769ddf 100644 --- a/my-app/src/pages/RoomBooking.jsx +++ b/my-app/src/pages/RoomBooking.jsx @@ -1,8 +1,8 @@ import React, { useEffect } from 'react'; import styles from './RoomBooking.module.css'; import { Link } from 'react-router-dom'; -import BookingsList from '../components/BookingsList'; -import Card from '../components/Card'; +import BookingsList from '../components/booking/BookingsList'; +import Card from '../components/ui/Card'; import { useSettingsContext } from '../context/SettingsContext'; import { USER } from '../constants/bookingConstants'; -- 2.39.5 From e5d7cca9cb7d7f46807c9beb757e32ac96159ac6 Mon Sep 17 00:00:00 2001 From: Jacob Reinikainen <80760206+jazzjacob@users.noreply.github.com> Date: Fri, 5 Sep 2025 17:06:52 +0200 Subject: [PATCH 3/3] navigation menu improvments --- my-app/src/components/layout/Navigation.jsx | 95 +++++++-- .../components/layout/Navigation.module.css | 189 +++++++++++++++--- my-app/src/pages/BookingSettings.module.css | 135 +++++++------ 3 files changed, 318 insertions(+), 101 deletions(-) diff --git a/my-app/src/components/layout/Navigation.jsx b/my-app/src/components/layout/Navigation.jsx index c8207d0..989f446 100644 --- a/my-app/src/components/layout/Navigation.jsx +++ b/my-app/src/components/layout/Navigation.jsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import styles from './Navigation.module.css'; // Import the CSS Module import { Link, useLocation } from 'react-router-dom'; import { ThemeToggle } from './ThemeToggle'; @@ -8,11 +8,31 @@ import 'bootstrap-icons/font/bootstrap-icons.css'; const Navigation = () => { const [menuOpen, setMenuOpen] = useState(false); + const [coursesOpen, setCoursesOpen] = useState(false); const location = useLocation(); const { getCurrentUser } = useSettingsContext(); const toggleMenu = () => { setMenuOpen(!menuOpen); + setCoursesOpen(false); + }; + + // Prevent body scroll when mobile menu is open + useEffect(() => { + if (menuOpen) { + document.body.style.overflow = 'hidden'; + } else { + document.body.style.overflow = 'unset'; + } + + // Cleanup on unmount + return () => { + document.body.style.overflow = 'unset'; + }; + }, [menuOpen]); + + const toggleCourses = () => { + setCoursesOpen(!coursesOpen); }; // Helper function to get user's initials @@ -52,18 +72,17 @@ const Navigation = () => { - {/* User Profile Section - Desktop only */} - -
-
- {getInitials(getCurrentUser().name)} -
-
- {getCurrentUser().name} - - {/* Navigation - always visible in sidebar mode, toggleable in mobile */} - {/* Theme Toggle - Desktop only */} +
+ {/* User Profile Section - Desktop only */} + +
+
+ {getInitials(getCurrentUser().name)} +
+
+ {getCurrentUser().name} + + {/* Theme Toggle - Desktop only */}
+
); }; diff --git a/my-app/src/components/layout/Navigation.module.css b/my-app/src/components/layout/Navigation.module.css index c76a629..872cb95 100644 --- a/my-app/src/components/layout/Navigation.module.css +++ b/my-app/src/components/layout/Navigation.module.css @@ -66,6 +66,40 @@ flex-direction: column; background-color: var(--bg-primary); border-top: 1px solid var(--border-light); + width: 100%; + overflow: hidden; +} + +/* Mobile-specific height adjustments */ +@media (max-width: 1023px) { + .nav { + height: calc(100vh - 60px); + min-height: calc(100vh - 60px); + } +} + +/* iOS Safari mobile specific - more precise detection */ +@media (max-width: 1023px) and (max-device-width: 768px) { + @supports (-webkit-touch-callout: none) { + .nav { + height: calc(100svh - 60px); + min-height: calc(100svh - 120px); + } + } +} + +.navScrollContainer { + display: contents; +} + +/* Mobile-specific scroll container */ +@media (max-width: 1023px) { + .navScrollContainer { + display: block; + height: 100%; + overflow-y: auto; + -webkit-overflow-scrolling: touch; + } } .navOpen { @@ -89,6 +123,7 @@ .navLink:hover { background-color: var(--bg-muted); + color: var(--text-primary); } .navIcon { @@ -117,6 +152,119 @@ display: none; } +/* Mobile-only profile link */ +.mobileOnly { + display: flex; +} + +.mobileProfileLink { + background-color: var(--bg-muted); + margin-bottom: var(--spacing-sm); + border-radius: var(--border-radius-md); + border-bottom: none !important; +} + +.mobileUserAvatar { + width: 32px; + height: 32px; + flex-shrink: 0; +} + +.mobileUserAvatar .avatarInitials { + width: 100%; + height: 100%; + border-radius: 50%; + background-color: var(--color-primary); + color: var(--color-white); + display: flex; + align-items: center; + justify-content: center; + font-size: 0.9rem; + font-weight: var(--font-weight-semibold); +} + +/* Mobile Courses Accordion */ +.mobileCoursesSection { + flex-direction: column; +} + +.accordionToggle { + background: none; + border: none; + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + cursor: pointer; + box-sizing: border-box; + padding: var(--spacing-lg) var(--spacing-xl); + min-height: auto; + height: auto; +} + +.accordionToggle:hover { + background-color: var(--bg-muted); +} + +.chevron { + transition: var(--transition-fast); + color: var(--text-secondary); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; +} + +.accordionContent { + max-height: 0; + overflow: hidden; + transition: max-height 0.3s ease; + background-color: var(--bg-tertiary); + display: flex; + flex-direction: column; +} + +.accordionOpen { + max-height: none; +} + +.mobileTermGroup { + padding: var(--spacing-md) var(--spacing-xl); + display: flex; + flex-direction: column; +} + +.mobileTermGroup:first-child { + border-top: 1px solid var(--border-light); +} + +.mobileTermTitle { + font-size: 0.8rem; + font-weight: var(--font-weight-semibold); + color: var(--text-secondary); + margin: 0 0 var(--spacing-sm) 0; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.mobileCourseLink { + display: block; + padding: var(--spacing-md) var(--spacing-lg); + margin-bottom: var(--spacing-sm); + font-size: 1rem; + color: var(--text-primary); + text-decoration: none; + border-radius: var(--border-radius-md); + transition: var(--transition-fast); + line-height: 1.4; + width: 100%; +} + +.mobileCourseLink:hover { + background-color: var(--bg-muted); + color: var(--text-primary); +} + /* =========================================== DESKTOP SIDEBAR STYLES (≥ 1024px) ========================================== */ @@ -129,46 +277,27 @@ left: 0; width: 280px; height: 100vh; + min-height: 100vh; flex-direction: column; /*box-shadow: var(--shadow-xl);*/ border-right: 1px solid var(--border-light); overflow-y: auto; + z-index: var(--z-header); } .top { - flex-direction: column; + flex-direction: row; padding: var(--spacing-2xl); gap: var(--spacing-lg); border-bottom: 1px solid var(--border-light); min-height: fit-content; } - .left { - flex-direction: column; - align-items: center; - gap: var(--spacing-md); - width: 100%; - } - - .right { - width: 100%; - justify-content: center; - } - /* Hide mobile theme toggle on desktop */ .right > :first-child { display: none; } - .logo img { - height: 60px; - } - - .brandText { - font-size: 1.3rem; - text-align: center; - } - .menuIcon { display: none; } @@ -180,6 +309,8 @@ flex-direction: column; padding: var(--spacing-xl); gap: var(--spacing-xs); + height: auto; + overflow: visible; } .navLink { @@ -308,7 +439,7 @@ .courseLink:hover { background-color: var(--bg-muted); - color: var(--color-primary); + color: var(--text-primary); } /* Theme Toggle Container - Desktop */ @@ -318,6 +449,18 @@ justify-content: center; border-bottom: 1px solid var(--border-light); } + + /* Hide mobile-only profile link on desktop */ + .mobileOnly { + display: none; + } + + .sidebarBottom { + background-color: var(--bg-primary); + border-top: 1px solid var(--border-light); + position: sticky; + bottom: 0; + } } /* =========================================== diff --git a/my-app/src/pages/BookingSettings.module.css b/my-app/src/pages/BookingSettings.module.css index 9e70107..5a332fd 100644 --- a/my-app/src/pages/BookingSettings.module.css +++ b/my-app/src/pages/BookingSettings.module.css @@ -2,7 +2,9 @@ max-width: 800px; margin: 0 auto; padding: 2rem; - font-family: system-ui, -apple-system, sans-serif; + font-family: var(--font-secondary); + background-color: var(--bg-primary); + color: var(--text-primary); } .header { @@ -12,13 +14,13 @@ .header h1 { font-size: 2.5rem; - font-weight: 600; - color: #1f2937; + font-weight: var(--font-weight-semibold); + color: var(--text-primary); margin-bottom: 0.5rem; } .header p { - color: #6b7280; + color: var(--text-secondary); font-size: 1.1rem; } @@ -29,19 +31,19 @@ } .section { - background: white; - border: 1px solid #e5e7eb; - border-radius: 12px; + background: var(--bg-secondary); + border: 1px solid var(--border-light); + border-radius: var(--border-radius-2xl); padding: 1.5rem; - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + box-shadow: var(--shadow-sm); } .section h2 { font-size: 1.5rem; - font-weight: 600; - color: #1f2937; + font-weight: var(--font-weight-semibold); + color: var(--text-primary); margin-bottom: 1.5rem; - border-bottom: 2px solid #f3f4f6; + border-bottom: 2px solid var(--border-light); padding-bottom: 0.5rem; } @@ -60,14 +62,14 @@ .setting label strong { font-size: 1rem; - font-weight: 600; - color: #374151; + font-weight: var(--font-weight-semibold); + color: var(--text-primary); display: block; } .description { font-size: 0.875rem; - color: #6b7280; + color: var(--text-secondary); margin-top: 0.25rem; display: block; } @@ -80,17 +82,18 @@ .dateInput, .numberInput, .select, .textInput { padding: 0.75rem; - border: 1px solid #d1d5db; - border-radius: 6px; + border: 1px solid var(--input-border); + border-radius: var(--border-radius-md); font-size: 1rem; - transition: border-color 0.2s, box-shadow 0.2s; - background: white; + transition: var(--transition-medium); + background: var(--input-bg); + color: var(--input-text); } .dateInput:focus, .numberInput:focus, .select:focus, .textInput:focus { outline: none; - border-color: #2563eb; - box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1); + border-color: var(--color-primary); + box-shadow: 0 0 0 3px var(--color-primary-light); } .dateInput { @@ -111,34 +114,34 @@ .clearButton { padding: 0.5rem 1rem; - background: #f3f4f6; - border: 1px solid #d1d5db; - border-radius: 6px; + background: var(--button-secondary-bg); + border: 1px solid var(--border-light); + border-radius: var(--border-radius-md); font-size: 0.875rem; - color: #374151; + color: var(--button-secondary-text); cursor: pointer; - transition: all 0.2s; + transition: var(--transition-medium); width: fit-content; } .clearButton:hover { - background: #e5e7eb; - border-color: #9ca3af; + background: var(--button-secondary-hover-bg); + border-color: var(--border-medium); } .currentStatus { margin-top: 0.5rem; font-size: 0.875rem; - color: #4b5563; + color: var(--text-secondary); } .mockLabel { - background: #fbbf24; - color: #92400e; + background: var(--notification-warning-border); + color: var(--notification-warning-bg); padding: 0.125rem 0.375rem; - border-radius: 4px; + border-radius: var(--border-radius-sm); font-size: 0.75rem; - font-weight: 600; + font-weight: var(--font-weight-semibold); text-transform: uppercase; letter-spacing: 0.05em; } @@ -153,7 +156,7 @@ flex: 1; height: 6px; border-radius: 3px; - background: #e5e7eb; + background: var(--border-light); outline: none; cursor: pointer; -webkit-appearance: none; @@ -164,25 +167,25 @@ width: 20px; height: 20px; border-radius: 50%; - background: #2563eb; + background: var(--color-primary); cursor: pointer; - border: 2px solid white; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + border: 2px solid var(--bg-primary); + box-shadow: var(--shadow-sm); } .slider::-moz-range-thumb { width: 20px; height: 20px; border-radius: 50%; - background: #2563eb; + background: var(--color-primary); cursor: pointer; - border: 2px solid white; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + border: 2px solid var(--bg-primary); + box-shadow: var(--shadow-sm); } .sliderValue { - font-weight: 600; - color: #2563eb; + font-weight: var(--font-weight-semibold); + color: var(--color-primary); min-width: 40px; text-align: center; } @@ -196,18 +199,18 @@ .toggle { width: 50px; height: 24px; - background: #d1d5db; + background: var(--border-light); border-radius: 12px; border: none; position: relative; cursor: pointer; - transition: background-color 0.3s ease; + transition: var(--transition-slow); -webkit-appearance: none; appearance: none; } .toggle:checked { - background: #10b981; + background: var(--notification-success-icon-bg); } .toggle:before { @@ -216,11 +219,11 @@ width: 20px; height: 20px; border-radius: 50%; - background: white; + background: var(--bg-primary); top: 2px; left: 2px; - transition: transform 0.3s ease; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + transition: var(--transition-slow); + box-shadow: var(--shadow-sm); } .toggle:checked:before { @@ -228,60 +231,60 @@ } .toggleStatus { - font-weight: 500; - color: #374151; + font-weight: var(--font-weight-medium); + color: var(--text-primary); } .actions { display: flex; flex-direction: column; align-items: center; - justify-content: center;; + justify-content: center; gap: 1rem; padding: 2rem; - background: #f9fafb; - border-radius: 12px; - border: 1px solid #e5e7eb; + background: var(--bg-tertiary); + border-radius: var(--border-radius-2xl); + border: 1px solid var(--border-light); width: 100%; } .resetButton { padding: 0.75rem 2rem; - background: #dc2626; - color: white; + background: var(--reset-button-border); + color: var(--color-white); border: none; - border-radius: 6px; + border-radius: var(--border-radius-md); font-size: 1rem; - font-weight: 600; + font-weight: var(--font-weight-semibold); cursor: pointer; - transition: background-color 0.2s; + transition: var(--transition-medium); width: fit-content; } .resetButton:hover { - background: #b91c1c; + background: var(--reset-button-hover-border); } .testSessionButton { padding: 0.75rem 2rem; - background: #2563eb; - color: white; + background: var(--color-primary); + color: var(--color-white); border: none; - border-radius: 6px; + border-radius: var(--border-radius-md); font-size: 1rem; - font-weight: 600; + font-weight: var(--font-weight-semibold); cursor: pointer; - transition: background-color 0.2s; + transition: var(--transition-medium); width: fit-content; } .testSessionButton:hover { - background: #1d4ed8; + background: var(--color-primary-hover); } .info { font-size: 0.875rem; - color: #6b7280; + color: var(--text-secondary); text-align: center; } -- 2.39.5