booking-flow-finalized-design kindaaaa #7
@@ -3,6 +3,7 @@ import { BrowserRouter as Router } from 'react-router-dom';
|
||||
import AppRoutes from './AppRoutes'; // move the routing and loading logic here
|
||||
import { SettingsProvider, useSettingsContext } from './context/SettingsContext';
|
||||
import { ThemeProvider } from './context/ThemeContext';
|
||||
import { BookingsListProvider } from './context/BookingContext';
|
||||
import { NamePrompt } from './components/ui/NamePrompt';
|
||||
|
||||
function AppContent() {
|
||||
@@ -34,7 +35,9 @@ function App() {
|
||||
return (
|
||||
<ThemeProvider>
|
||||
<SettingsProvider>
|
||||
<AppContent />
|
||||
<BookingsListProvider>
|
||||
<AppContent />
|
||||
</BookingsListProvider>
|
||||
</SettingsProvider>
|
||||
</ThemeProvider>
|
||||
);
|
||||
|
||||
@@ -16,128 +16,31 @@ import CoursePage from './pages/CoursePage';
|
||||
import Profile from './pages/Profile';
|
||||
import RoomSchedules from './pages/RoomSchedules';
|
||||
import { useSettingsContext } from './context/SettingsContext';
|
||||
import { useBookingsListContext } from './context/BookingContext';
|
||||
|
||||
const AppRoutes = () => {
|
||||
const location = useLocation();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [showSuccessBanner, setShowSuccessBanner] = useState(false);
|
||||
const [lastCreatedBooking, setLastCreatedBooking] = useState(null);
|
||||
const [showDeleteBanner, setShowDeleteBanner] = useState(false);
|
||||
const [lastDeletedBooking, setLastDeletedBooking] = useState(null);
|
||||
const [showLeaveBanner, setShowLeaveBanner] = useState(false);
|
||||
const [lastLeftBooking, setLastLeftBooking] = useState(null);
|
||||
const [showUpdateBanner, setShowUpdateBanner] = useState(false);
|
||||
const [lastUpdatedBooking, setLastUpdatedBooking] = useState(null);
|
||||
const { getCurrentUser } = useSettingsContext();
|
||||
const currentUser = getCurrentUser();
|
||||
|
||||
// Mock bookings data
|
||||
// In a real app, this would come from an API or global state
|
||||
const [bookings, setBookings] = useState([
|
||||
{
|
||||
id: 1,
|
||||
date: new CalendarDate(2025, 9, 3),
|
||||
startTime: 4,
|
||||
endTime: 6,
|
||||
room: 'G5:7',
|
||||
roomCategory: 'green',
|
||||
title: 'Team standup',
|
||||
participants: [
|
||||
currentUser,
|
||||
{ id: 2, name: 'Filip Norgren', username: 'fino2341', email: 'filip.norgren@dsv.su.se' },
|
||||
{ id: 3, name: 'Hedvig Engelmark', username: 'heen9876', email: 'hedvig.engelmark@dsv.su.se' },
|
||||
{ id: 4, name: 'Elin Rudling', username: 'elru4521', email: 'elin.rudling@dsv.su.se' }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
date: new CalendarDate(2025, 9, 5),
|
||||
startTime: 8,
|
||||
endTime: 12,
|
||||
room: 'G5:12',
|
||||
roomCategory: 'red',
|
||||
title: 'Project planning workshop',
|
||||
participants: [
|
||||
currentUser,
|
||||
{ id: 5, name: 'Victor Magnusson', username: 'vima8734', email: 'victor.magnusson@dsv.su.se' },
|
||||
{ id: 6, name: 'Ellen Britschgi', username: 'elbr5623', email: 'ellen.britschgi@dsv.su.se' },
|
||||
{ id: 7, name: 'Anna Andersson', username: 'anan3457', email: 'anna.andersson@dsv.su.se' },
|
||||
{ id: 8, name: 'Erik Larsson', username: 'erla7892', email: 'erik.larsson@dsv.su.se' },
|
||||
{ id: 9, name: 'Sofia Karlsson', username: 'soka1245', email: 'sofia.karlsson@dsv.su.se' },
|
||||
{ id: 10, name: 'Magnus Nilsson', username: 'mani6789', email: 'magnus.nilsson@dsv.su.se' }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
date: new CalendarDate(2025, 9, 4),
|
||||
startTime: 2,
|
||||
endTime: 3,
|
||||
room: 'G5:3',
|
||||
roomCategory: 'blue',
|
||||
title: '1:1 with supervisor',
|
||||
participants: [
|
||||
currentUser,
|
||||
{ id: 251, name: 'Arjohn Emilsson', username: 'arem1532', email: 'arjohn.emilsson@dsv.su.se' }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
date: new CalendarDate(2025, 9, 6),
|
||||
startTime: 6,
|
||||
endTime: 8,
|
||||
room: 'G5:15',
|
||||
roomCategory: 'yellow',
|
||||
title: 'Study group session',
|
||||
participants: [
|
||||
currentUser,
|
||||
{ id: 11, name: 'Emma Johansson', username: 'emjo4512', email: 'emma.johansson@dsv.su.se' },
|
||||
{ id: 12, name: 'Oskar Pettersson', username: 'ospe3698', email: 'oskar.pettersson@dsv.su.se' }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
date: new CalendarDate(2025, 9, 7),
|
||||
startTime: 10,
|
||||
endTime: 12,
|
||||
room: 'G5:9',
|
||||
roomCategory: 'blue',
|
||||
title: 'Design review meeting',
|
||||
createdBy: { id: 3, name: 'Hedvig Engelmark', username: 'heen9876', email: 'hedvig.engelmark@dsv.su.se' },
|
||||
participants: [
|
||||
{ id: 3, name: 'Hedvig Engelmark', username: 'heen9876', email: 'hedvig.engelmark@dsv.su.se' },
|
||||
currentUser,
|
||||
{ id: 5, name: 'Victor Magnusson', username: 'vima8734', email: 'victor.magnusson@dsv.su.se' },
|
||||
{ id: 8, name: 'Erik Larsson', username: 'erla7892', email: 'erik.larsson@dsv.su.se' }
|
||||
],
|
||||
isParticipantBooking: true
|
||||
}
|
||||
]);
|
||||
|
||||
function addBooking(newBooking) {
|
||||
setBookings([...bookings, newBooking]);
|
||||
setLastCreatedBooking(newBooking);
|
||||
setShowSuccessBanner(true);
|
||||
}
|
||||
|
||||
function updateBooking(updatedBooking) {
|
||||
setBookings(bookings.map(booking =>
|
||||
booking.id === updatedBooking.id ? updatedBooking : booking
|
||||
));
|
||||
setLastUpdatedBooking(updatedBooking);
|
||||
setShowUpdateBanner(true);
|
||||
}
|
||||
|
||||
function deleteBooking(bookingToDelete, actionType = 'delete') {
|
||||
setBookings(bookings.filter(booking => booking.id !== bookingToDelete.id));
|
||||
|
||||
if (actionType === 'leave') {
|
||||
setLastLeftBooking(bookingToDelete);
|
||||
setShowLeaveBanner(true);
|
||||
} else {
|
||||
setLastDeletedBooking(bookingToDelete);
|
||||
setShowDeleteBanner(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Get bookings data and functions from context
|
||||
const {
|
||||
bookings,
|
||||
addBooking,
|
||||
updateBooking,
|
||||
deleteBooking,
|
||||
showSuccessBanner,
|
||||
setShowSuccessBanner,
|
||||
lastCreatedBooking,
|
||||
showDeleteBanner,
|
||||
setShowDeleteBanner,
|
||||
lastDeletedBooking,
|
||||
showLeaveBanner,
|
||||
setShowLeaveBanner,
|
||||
lastLeftBooking,
|
||||
showUpdateBanner,
|
||||
setShowUpdateBanner,
|
||||
lastUpdatedBooking
|
||||
} = useBookingsListContext();
|
||||
|
||||
useEffect(() => {
|
||||
// Reset scroll position on route change
|
||||
@@ -161,6 +64,7 @@ const AppRoutes = () => {
|
||||
<Route path="/" element={<Layout />}>
|
||||
<Route index element={<RoomBooking bookings={bookings} showSuccessBanner={showSuccessBanner} lastCreatedBooking={lastCreatedBooking} onDismissBanner={() => setShowSuccessBanner(false)} onBookingUpdate={updateBooking} onBookingDelete={deleteBooking} showDeleteBanner={showDeleteBanner} lastDeletedBooking={lastDeletedBooking} onDismissDeleteBanner={() => setShowDeleteBanner(false)} showLeaveBanner={showLeaveBanner} lastLeftBooking={lastLeftBooking} onDismissLeaveBanner={() => setShowLeaveBanner(false)} showUpdateBanner={showUpdateBanner} lastUpdatedBooking={lastUpdatedBooking} onDismissUpdateBanner={() => setShowUpdateBanner(false)} />} />
|
||||
<Route path="new-booking" element={<NewBooking addBooking={addBooking} />} />
|
||||
<Route path="new-booking/:roomType" element={<NewBooking addBooking={addBooking} />} />
|
||||
<Route path="booking-details" element={<BookingDetails addBooking={addBooking} />} />
|
||||
<Route path="booking-confirmation" element={<BookingConfirmation addBooking={addBooking} />} />
|
||||
<Route path="course-schedule" element={<CourseSchedule />} />
|
||||
|
||||
@@ -4,17 +4,36 @@ import { useBookingContext } from '../../context/BookingContext';
|
||||
import { useSettingsContext } from '../../context/SettingsContext';
|
||||
import styles from './RoomSelectionField.module.css';
|
||||
|
||||
export function RoomSelectionField({ clean = false }) {
|
||||
export function RoomSelectionField({ clean = false, roomTypeFilter = null }) {
|
||||
const booking = useBookingContext();
|
||||
const { settings } = useSettingsContext();
|
||||
|
||||
// Generate room options based on settings
|
||||
// Generate room options based on settings and optional filter
|
||||
const roomOptions = useMemo(() => {
|
||||
return Array.from({ length: settings.numberOfRooms }, (_, i) => ({
|
||||
value: `G5:${i + 1}`,
|
||||
label: `G5:${i + 1}`,
|
||||
}));
|
||||
}, [settings.numberOfRooms]);
|
||||
let rooms = [];
|
||||
|
||||
if (!roomTypeFilter || roomTypeFilter === 'litet-grupprum') {
|
||||
// Add small rooms G5:1-15
|
||||
rooms = rooms.concat(
|
||||
Array.from({ length: settings.numberOfRooms }, (_, i) => ({
|
||||
value: `G5:${i + 1}`,
|
||||
label: `G5:${i + 1}`,
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
if (!roomTypeFilter || roomTypeFilter === 'stort-grupprum') {
|
||||
// Add large rooms G10:1-7
|
||||
rooms = rooms.concat(
|
||||
Array.from({ length: 7 }, (_, i) => ({
|
||||
value: `G10:${i + 1}`,
|
||||
label: `G10:${i + 1}`,
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
return rooms;
|
||||
}, [settings.numberOfRooms, roomTypeFilter]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -70,7 +70,7 @@ const Navigation = () => {
|
||||
<div className={styles.top}>
|
||||
<div className={styles.left}>
|
||||
<Link to="/" className={styles.logo}>
|
||||
<img src="su-logo-white.svg" alt="Logo" />
|
||||
<img src="/su-logo-white.svg" alt="Logo" />
|
||||
</Link>
|
||||
<span className={styles.brandText}>Studentportalen</span>
|
||||
</div>
|
||||
|
||||
@@ -295,4 +295,47 @@ export const DEFAULT_DISABLED_OPTIONS = {
|
||||
6: false,
|
||||
7: false,
|
||||
8: true,
|
||||
};
|
||||
};
|
||||
|
||||
export const RANDOM_BOOKING_NAMES = [
|
||||
"Projektmöte grupp 7",
|
||||
"Tentapluggang",
|
||||
"Metodarbete",
|
||||
"Grupparbete IS1",
|
||||
"Redovisning projekt",
|
||||
"Handledning",
|
||||
"Kravanalys meeting",
|
||||
"Pluggsession statistik",
|
||||
"Gruppstudier DIFO",
|
||||
"Projektplanering",
|
||||
"Kodgranskning",
|
||||
"Retrospektiv möte",
|
||||
"Scrum planning",
|
||||
"Design workshop",
|
||||
"Testning och debug",
|
||||
"Databasdesign",
|
||||
"Rapport skrivning",
|
||||
"Presentationsövning",
|
||||
"Peer review",
|
||||
"Brainstorm session",
|
||||
"Algoritm genomgång",
|
||||
"UX research möte",
|
||||
"Prototyping",
|
||||
"Stakeholder meeting",
|
||||
"Code review session",
|
||||
"Agile standup",
|
||||
"Requirements workshop",
|
||||
"System arkitektur",
|
||||
"User testing",
|
||||
"Demo förberedelse",
|
||||
"Krisgrupp - allt är sönder",
|
||||
"Panikprogrammering",
|
||||
"Buggjakt extreme edition",
|
||||
"Kaffepaus (viktigt möte)",
|
||||
"Stack Overflow support group",
|
||||
"Deadline depression circle",
|
||||
"Merge conflict therapy",
|
||||
"Git blame shame session",
|
||||
"Procrastination workshop",
|
||||
"Är det fredag än? mötet"
|
||||
];
|
||||
@@ -1,7 +1,12 @@
|
||||
import React, { createContext, useContext } from 'react';
|
||||
import React, { createContext, useContext, useState } from 'react';
|
||||
import { CalendarDate } from '@internationalized/date';
|
||||
import { useSettingsContext } from './SettingsContext';
|
||||
import { RANDOM_BOOKING_NAMES, PEOPLE } from '../constants/bookingConstants';
|
||||
|
||||
const BookingContext = createContext(null);
|
||||
const BookingsListContext = createContext(null);
|
||||
|
||||
// Provider for individual booking forms (existing functionality)
|
||||
export function BookingProvider({ children, value }) {
|
||||
return (
|
||||
<BookingContext.Provider value={value}>
|
||||
@@ -10,10 +15,194 @@ export function BookingProvider({ children, value }) {
|
||||
);
|
||||
}
|
||||
|
||||
// Provider for managing the list of all bookings
|
||||
export function BookingsListProvider({ children }) {
|
||||
const { getCurrentUser, getEffectiveToday } = useSettingsContext();
|
||||
const currentUser = getCurrentUser();
|
||||
const today = getEffectiveToday();
|
||||
|
||||
// Helper functions for random generation
|
||||
const getRandomElement = (array) => array[Math.floor(Math.random() * array.length)];
|
||||
const getRandomInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
|
||||
const getRoomCategory = (roomName) => {
|
||||
const roomNumber = parseInt(roomName.split(':')[1]);
|
||||
if (roomName.startsWith('G5:')) {
|
||||
// Small rooms G5:1-15
|
||||
if (roomNumber >= 1 && roomNumber <= 4) return 'green';
|
||||
if (roomNumber >= 5 && roomNumber <= 8) return 'red';
|
||||
if (roomNumber >= 9 && roomNumber <= 12) return 'blue';
|
||||
if (roomNumber >= 13 && roomNumber <= 15) return 'yellow';
|
||||
} else if (roomName.startsWith('G10:')) {
|
||||
// Large rooms G10:1-7
|
||||
return 'purple';
|
||||
}
|
||||
return 'green';
|
||||
};
|
||||
|
||||
const generateRandomRoom = (isLargeRoom) => {
|
||||
if (isLargeRoom) {
|
||||
const roomNum = getRandomInt(1, 7);
|
||||
return `G10:${roomNum}`;
|
||||
} else {
|
||||
const roomNum = getRandomInt(1, 15);
|
||||
return `G5:${roomNum}`;
|
||||
}
|
||||
};
|
||||
|
||||
const generateRandomParticipants = (currentUser, isLargeRoom, isCurrentUserBooking) => {
|
||||
const maxParticipants = isLargeRoom ? 10 : 5;
|
||||
const minParticipants = 2; // At least creator + 1 participant
|
||||
const numParticipants = getRandomInt(minParticipants, maxParticipants);
|
||||
|
||||
// Get random people from PEOPLE array
|
||||
const shuffledPeople = [...PEOPLE].sort(() => Math.random() - 0.5);
|
||||
const selectedPeople = shuffledPeople.slice(0, numParticipants - 1); // -1 because we'll add current user or creator
|
||||
|
||||
if (isCurrentUserBooking) {
|
||||
// Current user is the creator, add them first
|
||||
return [currentUser, ...selectedPeople];
|
||||
} else {
|
||||
// Someone else is the creator, current user may or may not be a participant
|
||||
const creator = selectedPeople[0];
|
||||
const otherParticipants = selectedPeople.slice(1);
|
||||
|
||||
// 50% chance current user is a participant in other people's bookings
|
||||
if (Math.random() < 0.5) {
|
||||
return [creator, currentUser, ...otherParticipants];
|
||||
} else {
|
||||
return [creator, ...otherParticipants];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Generate bookings relative to current date
|
||||
const generateInitialBookings = () => {
|
||||
const numBookings = getRandomInt(2, 10);
|
||||
const bookings = [];
|
||||
|
||||
for (let i = 0; i < numBookings; i++) {
|
||||
const isLargeRoom = Math.random() < 0.2; // 20% chance of large room
|
||||
const isCurrentUserBooking = Math.random() > 0.2; // 80% current user's bookings, 20% others'
|
||||
|
||||
const room = generateRandomRoom(isLargeRoom);
|
||||
const participants = generateRandomParticipants(currentUser, isLargeRoom, isCurrentUserBooking);
|
||||
const creator = participants[0];
|
||||
|
||||
// Random date within next 14 days
|
||||
const daysFromNow = getRandomInt(0, 13);
|
||||
const date = today.add({ days: daysFromNow });
|
||||
|
||||
// Random time slots (8:00-17:30, in 30-minute slots)
|
||||
const startTimeSlot = getRandomInt(0, 19); // 8:00-17:30
|
||||
const duration = getRandomInt(1, Math.min(4, 19 - startTimeSlot)); // 30min to 2h, don't exceed 17:30
|
||||
const endTimeSlot = startTimeSlot + duration;
|
||||
|
||||
const booking = {
|
||||
id: i + 1,
|
||||
date: date,
|
||||
startTime: startTimeSlot,
|
||||
endTime: endTimeSlot,
|
||||
room: room,
|
||||
roomCategory: getRoomCategory(room),
|
||||
title: getRandomElement(RANDOM_BOOKING_NAMES),
|
||||
participants: participants,
|
||||
createdBy: creator,
|
||||
isParticipantBooking: !isCurrentUserBooking && participants.includes(currentUser)
|
||||
};
|
||||
|
||||
bookings.push(booking);
|
||||
}
|
||||
|
||||
// Sort by date and time
|
||||
return bookings.sort((a, b) => {
|
||||
if (a.date.compare(b.date) !== 0) {
|
||||
return a.date.compare(b.date);
|
||||
}
|
||||
return a.startTime - b.startTime;
|
||||
});
|
||||
};
|
||||
|
||||
// Initial bookings data (relative to current date)
|
||||
const [bookings, setBookings] = useState(() => generateInitialBookings());
|
||||
|
||||
// Banner states (moved from AppRoutes)
|
||||
const [showSuccessBanner, setShowSuccessBanner] = useState(false);
|
||||
const [lastCreatedBooking, setLastCreatedBooking] = useState(null);
|
||||
const [showDeleteBanner, setShowDeleteBanner] = useState(false);
|
||||
const [lastDeletedBooking, setLastDeletedBooking] = useState(null);
|
||||
const [showLeaveBanner, setShowLeaveBanner] = useState(false);
|
||||
const [lastLeftBooking, setLastLeftBooking] = useState(null);
|
||||
const [showUpdateBanner, setShowUpdateBanner] = useState(false);
|
||||
const [lastUpdatedBooking, setLastUpdatedBooking] = useState(null);
|
||||
|
||||
// Booking management functions (moved from AppRoutes)
|
||||
function addBooking(newBooking) {
|
||||
setBookings([...bookings, newBooking]);
|
||||
setLastCreatedBooking(newBooking);
|
||||
setShowSuccessBanner(true);
|
||||
}
|
||||
|
||||
function updateBooking(updatedBooking) {
|
||||
setBookings(bookings.map(booking =>
|
||||
booking.id === updatedBooking.id ? updatedBooking : booking
|
||||
));
|
||||
setLastUpdatedBooking(updatedBooking);
|
||||
setShowUpdateBanner(true);
|
||||
}
|
||||
|
||||
function deleteBooking(bookingToDelete, actionType = 'delete') {
|
||||
setBookings(bookings.filter(booking => booking.id !== bookingToDelete.id));
|
||||
|
||||
if (actionType === 'leave') {
|
||||
setLastLeftBooking(bookingToDelete);
|
||||
setShowLeaveBanner(true);
|
||||
} else {
|
||||
setLastDeletedBooking(bookingToDelete);
|
||||
setShowDeleteBanner(true);
|
||||
}
|
||||
}
|
||||
|
||||
const value = {
|
||||
bookings,
|
||||
addBooking,
|
||||
updateBooking,
|
||||
deleteBooking,
|
||||
showSuccessBanner,
|
||||
setShowSuccessBanner,
|
||||
lastCreatedBooking,
|
||||
showDeleteBanner,
|
||||
setShowDeleteBanner,
|
||||
lastDeletedBooking,
|
||||
showLeaveBanner,
|
||||
setShowLeaveBanner,
|
||||
lastLeftBooking,
|
||||
showUpdateBanner,
|
||||
setShowUpdateBanner,
|
||||
lastUpdatedBooking
|
||||
};
|
||||
|
||||
return (
|
||||
<BookingsListContext.Provider value={value}>
|
||||
{children}
|
||||
</BookingsListContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
// Hook for individual booking forms (existing functionality)
|
||||
export function useBookingContext() {
|
||||
const context = useContext(BookingContext);
|
||||
if (!context) {
|
||||
throw new Error('useBookingContext must be used within a BookingProvider');
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
// Hook for accessing the list of all bookings
|
||||
export function useBookingsListContext() {
|
||||
const context = useContext(BookingsListContext);
|
||||
if (!context) {
|
||||
throw new Error('useBookingsListContext must be used within a BookingsListProvider');
|
||||
}
|
||||
return context;
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import styles from './NewBooking.module.css';
|
||||
import { TimeCardContainer } from '../components/ui/TimeCardContainer';
|
||||
import { BookingDatePicker } from '../components/forms/BookingDatePicker';
|
||||
@@ -12,6 +13,7 @@ import PageContainer from '../components/layout/PageContainer';
|
||||
import Breadcrumbs from '../components/ui/Breadcrumbs';
|
||||
|
||||
export function NewBooking({ addBooking }) {
|
||||
const { roomType } = useParams();
|
||||
const { getEffectiveToday, settings } = useSettingsContext();
|
||||
const booking = useBookingState(addBooking, getEffectiveToday());
|
||||
const [showFilters, setShowFilters] = useState(false);
|
||||
@@ -23,6 +25,31 @@ export function NewBooking({ addBooking }) {
|
||||
// Check if we should use inline form (hide title and participants from main form)
|
||||
const useInlineForm = settings.bookingFormType === 'inline';
|
||||
|
||||
// Get page title, subtitle, and image based on room type
|
||||
const getPageInfo = () => {
|
||||
if (roomType === 'litet-grupprum') {
|
||||
return {
|
||||
title: 'Litet grupprum',
|
||||
subtitle: 'Plats för upp till 5 personer',
|
||||
imageUrl: '/grupprum.jpg'
|
||||
};
|
||||
} else if (roomType === 'stort-grupprum') {
|
||||
return {
|
||||
title: 'Stort grupprum',
|
||||
subtitle: 'Plats för upp till 10 personer',
|
||||
imageUrl: '/stort-grupprum.jpg'
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
title: 'Boka grupprum',
|
||||
subtitle: 'Välj från tillgängliga rum',
|
||||
imageUrl: '/grupprum.jpg'
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const { title: pageTitle, subtitle: pageSubtitle, imageUrl } = getPageInfo();
|
||||
|
||||
// Check if any filters are active
|
||||
const hasActiveFilters = booking.selectedRoom !== "allRooms" || booking.selectedBookingLength > 0;
|
||||
|
||||
@@ -72,9 +99,9 @@ export function NewBooking({ addBooking }) {
|
||||
<>
|
||||
<div className={styles.headerSection}>
|
||||
<PageHeader
|
||||
title="Litet grupprum"
|
||||
subtitle="Plats för 5 personer"
|
||||
imageUrl="./grupprum.jpg"
|
||||
title={pageTitle}
|
||||
subtitle={pageSubtitle}
|
||||
imageUrl={imageUrl}
|
||||
breadcrumbs={<Breadcrumbs items={breadcrumbItems} />}
|
||||
/>
|
||||
</div>
|
||||
@@ -92,7 +119,7 @@ export function NewBooking({ addBooking }) {
|
||||
/* Always-visible filters */
|
||||
<div className={styles.filtersContent}>
|
||||
<div className={styles.filtersRow}>
|
||||
<RoomSelectionField />
|
||||
<RoomSelectionField roomTypeFilter={roomType} />
|
||||
<BookingLengthField />
|
||||
</div>
|
||||
</div>
|
||||
@@ -113,7 +140,7 @@ export function NewBooking({ addBooking }) {
|
||||
{showFilters && (
|
||||
<div className={styles.filtersContent}>
|
||||
<div className={styles.filtersRow}>
|
||||
<RoomSelectionField />
|
||||
<RoomSelectionField roomTypeFilter={roomType} />
|
||||
<BookingLengthField />
|
||||
</div>
|
||||
{hasActiveFilters && (
|
||||
@@ -149,9 +176,9 @@ export function NewBooking({ addBooking }) {
|
||||
/* Stacked layout (original) */
|
||||
<>
|
||||
<PageHeader
|
||||
title="Litet grupprum"
|
||||
subtitle="Plats för 5 personer"
|
||||
imageUrl="./grupprum.jpg"
|
||||
title={pageTitle}
|
||||
subtitle={pageSubtitle}
|
||||
imageUrl={imageUrl}
|
||||
breadcrumbs={<Breadcrumbs items={breadcrumbItems} />}
|
||||
/>
|
||||
<div className={styles.formContainer}>
|
||||
@@ -167,7 +194,7 @@ export function NewBooking({ addBooking }) {
|
||||
/* Always-visible filters */
|
||||
<div className={styles.filtersContent}>
|
||||
<div className={styles.filtersRow}>
|
||||
<RoomSelectionField />
|
||||
<RoomSelectionField roomTypeFilter={roomType} />
|
||||
<BookingLengthField />
|
||||
</div>
|
||||
</div>
|
||||
@@ -188,7 +215,7 @@ export function NewBooking({ addBooking }) {
|
||||
{showFilters && (
|
||||
<div className={styles.filtersContent}>
|
||||
<div className={styles.filtersRow}>
|
||||
<RoomSelectionField />
|
||||
<RoomSelectionField roomTypeFilter={roomType} />
|
||||
<BookingLengthField />
|
||||
</div>
|
||||
{hasActiveFilters && (
|
||||
|
||||
@@ -32,10 +32,10 @@ export function RoomBooking({ bookings, showSuccessBanner, lastCreatedBooking, o
|
||||
<h2 className={styles.sectionHeading}>Ny bokning</h2>
|
||||
|
||||
<div className={styles.roomCategoryCards}>
|
||||
<Link to='/new-booking'>
|
||||
<Link to='/new-booking/litet-grupprum'>
|
||||
<Card imageUrl="./grupprum.jpg" header="Litet grupprum" subheader="Plats för 5 personer" />
|
||||
</Link>
|
||||
<Link to='/new-booking'>
|
||||
<Link to='/new-booking/stort-grupprum'>
|
||||
<Card imageUrl="./stort-grupprum.jpg" header="Stort grupprum" subheader="Plats för 10 personer" />
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user