new-modal #4
@@ -47,4 +47,30 @@ export function convertDateObjectToString( date ) {
|
||||
}
|
||||
return 'Ogiltigt datum';
|
||||
}
|
||||
}
|
||||
|
||||
export function formatBookingDate(date) {
|
||||
console.log('formatBookingDate called with:', date);
|
||||
|
||||
if (!date || !date.day || !date.month || !date.year) {
|
||||
console.log('Date validation failed:', { date, day: date?.day, month: date?.month, year: date?.year });
|
||||
return 'Ogiltigt datum';
|
||||
}
|
||||
|
||||
const months = ["januari", "februari", "mars", "april", "maj", "juni", "juli", "augusti", "september", "oktober", "november", "december"];
|
||||
|
||||
const monthIndex = date.month;
|
||||
console.log('Month index:', monthIndex);
|
||||
const monthName = months[monthIndex - 1]; // month is 1-based, array is 0-based
|
||||
console.log('Month name:', monthName);
|
||||
|
||||
if (!monthName) {
|
||||
console.log('Month name not found, falling back');
|
||||
// If month is out of range, fall back to simple format
|
||||
return `${date.day}/${date.month}/${date.year}`;
|
||||
}
|
||||
|
||||
const result = `${date.day} ${monthName} ${date.year}`;
|
||||
console.log('Final result:', result);
|
||||
return result;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useNavigate, useLocation } from 'react-router-dom';
|
||||
import styles from './BookingDetails.module.css';
|
||||
import { BookingTitleField } from '../components/forms/BookingTitleField';
|
||||
@@ -7,13 +7,14 @@ import { useBookingContext } from '../context/BookingContext';
|
||||
import { BookingProvider } from '../context/BookingContext';
|
||||
import { useSettingsContext } from '../context/SettingsContext';
|
||||
import { useBookingState } from '../hooks/useBookingState';
|
||||
import { convertDateObjectToString, getTimeFromIndex } from '../helpers';
|
||||
import { convertDateObjectToString, formatBookingDate, getTimeFromIndex } from '../helpers';
|
||||
|
||||
export function BookingDetails({ addBooking }) {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const { getEffectiveToday } = useSettingsContext();
|
||||
const booking = useBookingState(addBooking, getEffectiveToday());
|
||||
const [isAccordionOpen, setIsAccordionOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
window.scrollTo(0, 0);
|
||||
@@ -45,37 +46,76 @@ export function BookingDetails({ addBooking }) {
|
||||
booking.handleSave();
|
||||
};
|
||||
|
||||
const toggleAccordion = () => {
|
||||
setIsAccordionOpen(!isAccordionOpen);
|
||||
};
|
||||
|
||||
return (
|
||||
<BookingProvider value={booking}>
|
||||
<div className={styles.pageContainer}>
|
||||
<div className={styles.header}>
|
||||
<h2 className={styles.pageTitle}>Ny bokning</h2>
|
||||
<div className={styles.dateTimeSection}>
|
||||
<div className={styles.dateContainer}>
|
||||
<span className={styles.date}>{booking.selectedDate ? formatBookingDate(booking.selectedDate) : 'Välj datum'}</span>
|
||||
</div>
|
||||
<div className={styles.timeContainer}>
|
||||
<span className={styles.time}>{getTimeFromIndex(booking.selectedStartIndex)} - {getTimeFromIndex(booking.selectedEndIndex)}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.mainSection}>
|
||||
<button
|
||||
className={styles.backButton}
|
||||
onClick={handleBack}
|
||||
>
|
||||
← Tillbaka
|
||||
className={styles.backButton}
|
||||
onClick={handleBack}
|
||||
>
|
||||
← Tillbaka
|
||||
</button>
|
||||
<h2>Bokningsuppgifter</h2>
|
||||
</div>
|
||||
|
||||
<div className={styles.timeInfo}>
|
||||
<p className={styles.dateTime}>
|
||||
{convertDateObjectToString(booking.selectedDate)} · {getTimeFromIndex(booking.selectedStartIndex)} - {getTimeFromIndex(booking.selectedEndIndex)}
|
||||
</p>
|
||||
</div>
|
||||
<div className={styles.roomVisualization}>
|
||||
<div className={styles.roomArea}></div>
|
||||
<div className={`${styles.roomInfo} ${isAccordionOpen ? styles.expanded : ''}`} onClick={toggleAccordion}>
|
||||
<div className={styles.roomHeader}>
|
||||
<span>Lokal: {booking.assignedRoom || 'G5:12'}</span>
|
||||
<span className={`${styles.dropdown} ${isAccordionOpen ? styles.rotated : ''}`}>
|
||||
{isAccordionOpen ? '▲' : '▼'}
|
||||
</span>
|
||||
</div>
|
||||
{isAccordionOpen && (
|
||||
<div className={styles.roomDetails}>
|
||||
<div className={styles.roomDetailItem}>
|
||||
<span className={styles.roomDetailLabel}>5 platser</span>
|
||||
</div>
|
||||
<div className={styles.roomDetailItem}>
|
||||
<span className={styles.roomDetailLabel}>Plats:</span>
|
||||
<span className={styles.roomDetailValue}>Röda avdelningen</span>
|
||||
</div>
|
||||
<div className={styles.roomDetailItem}>
|
||||
<span className={styles.roomDetailLabel}>Utrustning:</span>
|
||||
<span className={styles.roomDetailValue}>Whiteboard, TV, Tangentbord, Mus.</span>
|
||||
</div>
|
||||
<div className={styles.roomDetailItem}>
|
||||
<span className={styles.roomDetailLabel}>⚠️ Status:</span>
|
||||
<span className={styles.roomDetailValue}>HDMI-kabel glappar.</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.formContainer}>
|
||||
<BookingTitleField />
|
||||
<ParticipantsSelector />
|
||||
</div>
|
||||
<div className={styles.formContainer}>
|
||||
<BookingTitleField />
|
||||
<ParticipantsSelector />
|
||||
</div>
|
||||
|
||||
<div className={styles.footer}>
|
||||
<button
|
||||
className={styles.saveButton}
|
||||
onClick={handleSave}
|
||||
>
|
||||
Boka
|
||||
</button>
|
||||
<div className={styles.footer}>
|
||||
<button
|
||||
className={styles.saveButton}
|
||||
onClick={handleSave}
|
||||
>
|
||||
Boka
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</BookingProvider>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
.pageContainer {
|
||||
margin: 0 auto;
|
||||
padding: 1rem;
|
||||
min-height: calc(100vh - 4rem); /* Adjust for header/footer height */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -11,7 +10,16 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
margin-bottom: 2rem;
|
||||
padding: 0 1rem;
|
||||
border-bottom: 1px solid var(--border-light);
|
||||
background-color: var(--bg-primary);
|
||||
position: sticky;
|
||||
top: 4rem;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.mainSection {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.backButton {
|
||||
@@ -23,32 +31,135 @@
|
||||
padding: 0.5rem;
|
||||
border-radius: 0.25rem;
|
||||
transition: background-color 0.2s ease;
|
||||
width: fit-content;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.backButton:hover {
|
||||
background-color: var(--bg-secondary);
|
||||
}
|
||||
|
||||
.header h2 {
|
||||
margin: 0;
|
||||
font-size: 1.5rem;
|
||||
.pageTitle {
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.timeInfo {
|
||||
background: var(--bg-secondary);
|
||||
padding: 1rem;
|
||||
border-radius: 0.5rem;
|
||||
.bookingInfo {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.dateTime {
|
||||
margin: 0;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 500;
|
||||
.dateTimeSection {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.dateContainer,
|
||||
.timeContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
.date, .time {
|
||||
font-size: 0.9rem;
|
||||
font-weight: 300;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.roomVisualization {
|
||||
margin-bottom: 2rem;
|
||||
border-radius: 0.5rem;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.roomArea {
|
||||
height: 200px;
|
||||
background-image: url('./grupprum.jpg');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.roomInfo {
|
||||
background: #1976d2;
|
||||
color: white;
|
||||
padding: 1rem;
|
||||
font-weight: 500;
|
||||
font-size: 1.1rem;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.roomHeader {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
font-size: 0.8rem;
|
||||
opacity: 0.8;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.dropdown.rotated {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.roomDetails {
|
||||
margin-top: 1rem;
|
||||
padding-top: 1rem;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.2);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
animation: slideDown 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes slideDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.roomDetailItem {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.roomDetailItem:first-child {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.roomDetailItem:first-child .roomDetailLabel {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.roomDetailLabel {
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
font-weight: 500;
|
||||
min-width: fit-content;
|
||||
}
|
||||
|
||||
.roomDetailValue {
|
||||
color: white;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.formContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -56,11 +167,9 @@
|
||||
}
|
||||
|
||||
.footer {
|
||||
margin-top: 2rem;
|
||||
margin-top: auto;
|
||||
padding-top: 2rem;
|
||||
border-top: 1px solid var(--border-light);
|
||||
width: 100%;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.saveButton {
|
||||
|
||||
@@ -354,6 +354,47 @@
|
||||
--loader-text-color: #333;
|
||||
--loader-border: rgba(0, 0, 0, 0.1);
|
||||
--loader-shadow: 0 20px 40px rgba(0, 0, 0, 0.1), 0 8px 16px rgba(0, 0, 0, 0.06);
|
||||
|
||||
/* === STOCKHOLM UNIVERSITY BRAND COLORS === */
|
||||
|
||||
/* Primary university color */
|
||||
--su-university-blue: #002F5F;
|
||||
--su-university-blue-80: #33587F;
|
||||
|
||||
/* Secondary colors - Sky/Himmel */
|
||||
--su-sky: #ACDEE6;
|
||||
--su-sky-70: #C4E8ED;
|
||||
--su-sky-35: #E3F4F7;
|
||||
--su-sky-20: #EEF9FA;
|
||||
|
||||
/* Secondary colors - Water/Vatten */
|
||||
--su-water: #9BB2CE;
|
||||
--su-water-70: #B8C9DC;
|
||||
--su-water-35: #DCE4EE;
|
||||
--su-water-20: #EBF0F5;
|
||||
|
||||
/* Secondary colors - Fire/Eld */
|
||||
--su-fire: #EB7125;
|
||||
--su-fire-70: #F19B66;
|
||||
--su-fire-35: #F8CDB3;
|
||||
--su-fire-20: #FBE2D3;
|
||||
|
||||
/* Secondary colors - Olive/Oliv */
|
||||
--su-olive: #A3A86B;
|
||||
--su-olive-70: #BEC297;
|
||||
--su-olive-35: #DFE1CB;
|
||||
--su-olive-20: #EDEEE1;
|
||||
|
||||
/* Base colors */
|
||||
--su-dark-gray: #4B4B4B;
|
||||
--su-white: #FFFFFF;
|
||||
--su-medium-gray: #BABABA;
|
||||
--su-light-gray: #DADADA;
|
||||
|
||||
/* Utility colors - limited use */
|
||||
--su-green: #499943;
|
||||
--su-red: #B00020;
|
||||
--su-red-10: #F7E5E8;
|
||||
}
|
||||
|
||||
/* === DARK MODE === */
|
||||
|
||||
Reference in New Issue
Block a user