improving-week-36 #1
@@ -12,7 +12,8 @@ export function BookingModal({
|
||||
endTimeIndex,
|
||||
setEndTimeIndex,
|
||||
className,
|
||||
onClose
|
||||
onClose,
|
||||
isOpen = true
|
||||
}) {
|
||||
const booking = useBookingContext();
|
||||
const { getCurrentUser } = useSettingsContext();
|
||||
@@ -88,7 +89,13 @@ export function BookingModal({
|
||||
|
||||
|
||||
return (
|
||||
<Modal isDismissable onOpenChange={(isOpen) => !isOpen && onClose && onClose()} className={className} style={{borderRadius: '0.4rem', overflow: 'hidden'}}>
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
isDismissable
|
||||
onOpenChange={(open) => !open && onClose && onClose()}
|
||||
className={className}
|
||||
style={{borderRadius: '0.4rem', overflow: 'hidden'}}
|
||||
>
|
||||
<Dialog style={{overflow: 'hidden'}}>
|
||||
<form>
|
||||
<Heading slot="title">{booking.title == "" ? "Jacobs bokning" : booking.title}</Heading>
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
}
|
||||
|
||||
.modalContainer {
|
||||
background-color: transparent;
|
||||
background-color: white;
|
||||
width: 85%;
|
||||
max-width: 400px;
|
||||
overflow: hidden;
|
||||
@@ -113,6 +113,11 @@
|
||||
|
||||
/* Ensure modal appears above header and handles overflow */
|
||||
:global(.react-aria-ModalOverlay) {
|
||||
position: fixed !important;
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
width: 100vw !important;
|
||||
height: 100vh !important;
|
||||
z-index: 1100 !important;
|
||||
overflow-y: auto !important;
|
||||
display: flex !important;
|
||||
@@ -120,7 +125,7 @@
|
||||
justify-content: center !important;
|
||||
padding: 2rem 1rem !important;
|
||||
box-sizing: border-box !important;
|
||||
background: rgba(0, 0, 0, 0.25) !important;
|
||||
background: rgba(0, 0, 0, 0.5) !important;
|
||||
backdrop-filter: blur(12px) saturate(150%) !important;
|
||||
-webkit-backdrop-filter: blur(12px) saturate(150%) !important;
|
||||
}
|
||||
@@ -129,7 +134,9 @@
|
||||
max-height: calc(100vh - 4rem) !important;
|
||||
max-width: 90vw !important;
|
||||
overflow-y: auto !important;
|
||||
background: rgba(255, 255, 255, 0.85) !important;
|
||||
background: white !important;
|
||||
border-radius: 0.5rem !important;
|
||||
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25) !important;
|
||||
}
|
||||
|
||||
/* New time display styles */
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
import React from 'react';
|
||||
import TimeCard from './TimeCard';
|
||||
import { InlineBookingForm } from './InlineBookingForm';
|
||||
import { BookingModal } from './BookingModal';
|
||||
import styles from './TimeCardContainer.module.css';
|
||||
import modalStyles from './BookingModal.module.css';
|
||||
import { useBookingContext } from '../context/BookingContext';
|
||||
import { useSettingsContext } from '../context/SettingsContext';
|
||||
|
||||
const SLOT_GROUPING_SIZE = 8;
|
||||
|
||||
export function TimeCardContainer() {
|
||||
const booking = useBookingContext();
|
||||
const { settings } = useSettingsContext();
|
||||
|
||||
// Check if we should use inline form
|
||||
const useInlineForm = settings.bookingFormType === 'inline';
|
||||
|
||||
const slotCount = 24; // 12 hours * 2 slots per hour (8:00 to 20:00)
|
||||
const slotIndices = Array.from({ length: slotCount }, (_, i) => i);
|
||||
@@ -116,8 +123,9 @@ export function TimeCardContainer() {
|
||||
);
|
||||
|
||||
// Add inline booking form after the pair that contains the selected time card
|
||||
// Only show inline form if useInlineForm is true
|
||||
// Cards are laid out in pairs: (0,1), (2,3), (4,5), etc.
|
||||
if (booking.selectedStartIndex !== null) {
|
||||
if (useInlineForm && booking.selectedStartIndex !== null) {
|
||||
const selectedPairStart = Math.floor(booking.selectedStartIndex / 2) * 2;
|
||||
const selectedPairEnd = selectedPairStart + 1;
|
||||
|
||||
@@ -142,6 +150,19 @@ export function TimeCardContainer() {
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Show modal when a time slot is selected and not using inline form */}
|
||||
{!useInlineForm && booking.selectedStartIndex !== null && (
|
||||
<BookingModal
|
||||
startTimeIndex={booking.selectedStartIndex}
|
||||
hoursAvailable={booking.selectedEndIndex - booking.selectedStartIndex}
|
||||
endTimeIndex={booking.selectedEndIndex}
|
||||
setEndTimeIndex={booking.setSelectedEndIndex}
|
||||
className={modalStyles.modalContainer}
|
||||
onClose={() => booking.resetTimeSelections()}
|
||||
isOpen={true}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -31,6 +31,7 @@ export const SettingsProvider = ({ children }) => {
|
||||
showDevelopmentBanner: false,
|
||||
showBookingConfirmationBanner: false,
|
||||
showBookingDeleteBanner: false,
|
||||
bookingFormType: 'inline', // 'modal' or 'inline'
|
||||
// Then override with saved values
|
||||
...parsed,
|
||||
// Convert date strings back to DateValue objects
|
||||
@@ -64,6 +65,8 @@ export const SettingsProvider = ({ children }) => {
|
||||
showBookingConfirmationBanner: false,
|
||||
// Booking delete banner toggle
|
||||
showBookingDeleteBanner: false,
|
||||
// Booking form type
|
||||
bookingFormType: 'inline', // 'modal' or 'inline'
|
||||
};
|
||||
});
|
||||
|
||||
@@ -104,6 +107,10 @@ export const SettingsProvider = ({ children }) => {
|
||||
earliestTimeSlot: 0,
|
||||
latestTimeSlot: 23,
|
||||
currentUserName: USER.name,
|
||||
showDevelopmentBanner: false,
|
||||
showBookingConfirmationBanner: false,
|
||||
showBookingDeleteBanner: false,
|
||||
bookingFormType: 'inline',
|
||||
});
|
||||
localStorage.removeItem('calendarSettings');
|
||||
};
|
||||
|
||||
@@ -128,6 +128,27 @@ export function BookingSettings() {
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.setting}>
|
||||
<label htmlFor="bookingFormType">
|
||||
<strong>Booking Form Type</strong>
|
||||
<span className={styles.description}>
|
||||
Choose between modal popup or inline form for creating bookings
|
||||
</span>
|
||||
</label>
|
||||
<select
|
||||
id="bookingFormType"
|
||||
value={settings.bookingFormType}
|
||||
onChange={(e) => updateSettings({ bookingFormType: e.target.value })}
|
||||
className={styles.select}
|
||||
>
|
||||
<option value="inline">Inline Form (New)</option>
|
||||
<option value="modal">Modal Popup (Classic)</option>
|
||||
</select>
|
||||
<div className={styles.currentStatus}>
|
||||
Current: <strong>{settings.bookingFormType === 'inline' ? 'Inline Form' : 'Modal Popup'}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.section}>
|
||||
|
||||
@@ -11,10 +11,13 @@ import { BookingProvider } from '../context/BookingContext';
|
||||
import { useSettingsContext } from '../context/SettingsContext';
|
||||
|
||||
export function NewBooking({ addBooking }) {
|
||||
const { getEffectiveToday } = useSettingsContext();
|
||||
const { getEffectiveToday, settings } = useSettingsContext();
|
||||
const booking = useBookingState(addBooking, getEffectiveToday());
|
||||
const [showFilters, setShowFilters] = useState(false);
|
||||
|
||||
// Check if we should use inline form (hide title and participants from main form)
|
||||
const useInlineForm = settings.bookingFormType === 'inline';
|
||||
|
||||
// Check if any filters are active
|
||||
const hasActiveFilters = booking.selectedRoom !== "allRooms" || booking.selectedBookingLength > 0;
|
||||
|
||||
@@ -57,8 +60,13 @@ export function NewBooking({ addBooking }) {
|
||||
<h2>Boka litet grupprum</h2>
|
||||
<div className={styles.formContainer}>
|
||||
<main style={{ flex: 1 }}>
|
||||
<BookingTitleField />
|
||||
<ParticipantsSelector />
|
||||
{/* Only show title and participants fields in modal mode */}
|
||||
{!useInlineForm && (
|
||||
<>
|
||||
<BookingTitleField />
|
||||
<ParticipantsSelector />
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className={styles.bookingTimesContainer}>
|
||||
<BookingDatePicker />
|
||||
|
||||
Reference in New Issue
Block a user