diff --git a/my-app/src/AppRoutes.jsx b/my-app/src/AppRoutes.jsx
index 43694bd..92e41cb 100644
--- a/my-app/src/AppRoutes.jsx
+++ b/my-app/src/AppRoutes.jsx
@@ -9,9 +9,9 @@ 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';
const AppRoutes = () => {
const location = useLocation();
@@ -124,6 +124,7 @@ const AppRoutes = () => {
} />
} />
} />
+ } />
>
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/ThemeToggle.module.css b/my-app/src/components/ThemeToggle.module.css
deleted file mode 100644
index c361983..0000000
--- a/my-app/src/components/ThemeToggle.module.css
+++ /dev/null
@@ -1,107 +0,0 @@
-.toggleButton {
- background: none;
- border: none;
- cursor: pointer;
- padding: var(--spacing-xs);
- border-radius: var(--border-radius-md);
- transition: var(--transition-fast);
- display: flex;
- align-items: center;
- justify-content: center;
- -webkit-tap-highlight-color: transparent;
-}
-
-.toggleButton:hover {
- background-color: var(--bg-muted);
-}
-
-.toggleContainer {
- display: flex;
- align-items: center;
- gap: var(--spacing-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);
- }
-}
\ No newline at end of file
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/common/PlaceholderBanner.jsx b/my-app/src/components/common/PlaceholderBanner.jsx
new file mode 100644
index 0000000..5894309
--- /dev/null
+++ b/my-app/src/components/common/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/common/PlaceholderBanner.module.css b/my-app/src/components/common/PlaceholderBanner.module.css
new file mode 100644
index 0000000..a2d2634
--- /dev/null
+++ b/my-app/src/components/common/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/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 54%
rename from my-app/src/components/Navigation.jsx
rename to my-app/src/components/layout/Navigation.jsx
index dd1787d..989f446 100644
--- a/my-app/src/components/Navigation.jsx
+++ b/my-app/src/components/layout/Navigation.jsx
@@ -1,18 +1,38 @@
-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';
-import { useSettingsContext } from '../context/SettingsContext';
+import { useSettingsContext } from '../../context/SettingsContext';
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 */}
+
+ {/* User Profile Section - Desktop only */}
+
+
+
+ {getInitials(getCurrentUser().name)}
+
+
+
{getCurrentUser().name}
+
+ {/* Theme Toggle - Desktop only */}
+
+
+
+
);
};
diff --git a/my-app/src/components/Navigation.module.css b/my-app/src/components/layout/Navigation.module.css
similarity index 60%
rename from my-app/src/components/Navigation.module.css
rename to my-app/src/components/layout/Navigation.module.css
index 63f1a30..872cb95 100644
--- a/my-app/src/components/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 {
@@ -112,6 +147,124 @@
display: none;
}
+/* Theme Toggle Container - Mobile (hidden) */
+.themeToggleContainer {
+ 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)
========================================== */
@@ -124,39 +277,25 @@
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;
- }
-
- .logo img {
- height: 60px;
- }
-
- .brandText {
- font-size: 1.3rem;
- text-align: center;
+ /* Hide mobile theme toggle on desktop */
+ .right > :first-child {
+ display: none;
}
.menuIcon {
@@ -170,6 +309,8 @@
flex-direction: column;
padding: var(--spacing-xl);
gap: var(--spacing-xs);
+ height: auto;
+ overflow: visible;
}
.navLink {
@@ -208,6 +349,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 +381,7 @@
font-weight: var(--font-weight-semibold);
color: var(--text-primary);
font-size: 1rem;
+ margin: 0;
}
.userLastName {
@@ -290,7 +439,27 @@
.courseLink:hover {
background-color: var(--bg-muted);
- color: var(--color-primary);
+ color: var(--text-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);
+ }
+
+ /* 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/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 52%
rename from my-app/src/components/ThemeToggle.jsx
rename to my-app/src/components/layout/ThemeToggle.jsx
index 3d6ed5a..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 = () => {
@@ -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/layout/ThemeToggle.module.css b/my-app/src/components/layout/ThemeToggle.module.css
new file mode 100644
index 0000000..b6f608c
--- /dev/null
+++ b/my-app/src/components/layout/ThemeToggle.module.css
@@ -0,0 +1,34 @@
+.toggleButton {
+ background-color: var(--bg-secondary);
+ border: 1px solid var(--border-light);
+ cursor: pointer;
+ 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);
+}
+
+.toggleButton:active {
+ transform: translateY(0);
+ box-shadow: var(--shadow-sm);
+}
+
+.toggleButton:focus {
+ outline: 2px solid var(--color-primary);
+ outline-offset: 2px;
+}
\ No newline at end of file
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/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;
}
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
new file mode 100644
index 0000000..a2d087d
--- /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/common/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
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';