improving-week-36 #1

Merged
jare2473 merged 41 commits from improving-week-36 into main 2025-09-04 10:49:05 +02:00
5 changed files with 196 additions and 20 deletions
Showing only changes of commit b5e9c738dd - Show all commits

View File

@@ -84,6 +84,10 @@ const AppRoutes = () => {
));
}
function deleteBooking(bookingToDelete) {
setBookings(bookings.filter(booking => booking.id !== bookingToDelete.id));
}
useEffect(() => {
setLoading(true);
const timer = setTimeout(() => setLoading(false), 800);
@@ -98,7 +102,7 @@ const AppRoutes = () => {
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<RoomBooking bookings={bookings} showSuccessBanner={showSuccessBanner} lastCreatedBooking={lastCreatedBooking} onDismissBanner={() => setShowSuccessBanner(false)} onBookingUpdate={updateBooking} />} />
<Route index element={<RoomBooking bookings={bookings} showSuccessBanner={showSuccessBanner} lastCreatedBooking={lastCreatedBooking} onDismissBanner={() => setShowSuccessBanner(false)} onBookingUpdate={updateBooking} onBookingDelete={deleteBooking} />} />
<Route path="new-booking" element={<NewBooking addBooking={addBooking} />} />
<Route path="booking-settings" element={<BookingSettings />} />
</Route>

View File

@@ -8,11 +8,12 @@ import { ParticipantsSelector } from './ParticipantsSelector';
import { BookingProvider } from '../context/BookingContext';
import { PEOPLE } from '../constants/bookingConstants';
function BookingCard({ booking, onClick, isExpanded, onBookingUpdate }) {
function BookingCard({ booking, onClick, isExpanded, onBookingUpdate, onBookingDelete }) {
const [selectedLength, setSelectedLength] = useState(null);
const [calculatedEndTime, setCalculatedEndTime] = useState(null);
const [editedTitle, setEditedTitle] = useState('');
const [editedParticipants, setEditedParticipants] = useState([]);
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
// Calculate current booking length and available hours
const currentLength = booking.endTime - booking.startTime;
@@ -102,6 +103,21 @@ function BookingCard({ booking, onClick, isExpanded, onBookingUpdate }) {
onClick(); // Close the expanded view
}
function handleDelete() {
setShowDeleteConfirm(true);
}
function confirmDelete() {
if (onBookingDelete) {
onBookingDelete(booking);
}
setShowDeleteConfirm(false);
}
function cancelDelete() {
setShowDeleteConfirm(false);
}
function getTimeFromIndex(timeIndex) {
const totalHalfHoursFromStart = timeIndex;
@@ -175,21 +191,53 @@ function BookingCard({ booking, onClick, isExpanded, onBookingUpdate }) {
/>
</div>
<div className={styles.buttonSection}>
<Button
className={styles.cancelButton}
onPress={handleCancel}
>
Avbryt
</Button>
<Button
className={`${styles.saveButton} ${selectedLength === null ? styles.disabledButton : ''}`}
onPress={handleSave}
isDisabled={selectedLength === null}
>
{selectedLength !== null ? 'Spara ändringar' : 'Välj längd först'}
</Button>
</div>
{!showDeleteConfirm ? (
<div className={styles.buttonSection}>
<Button
className={styles.deleteButton}
onPress={handleDelete}
>
Radera
</Button>
<Button
className={styles.cancelButton}
onPress={handleCancel}
>
Avbryt
</Button>
<Button
className={`${styles.saveButton} ${selectedLength === null ? styles.disabledButton : ''}`}
onPress={handleSave}
isDisabled={selectedLength === null}
>
{selectedLength !== null ? 'Spara ändringar' : 'Välj längd först'}
</Button>
</div>
) : (
<div className={styles.confirmationSection}>
<div className={styles.confirmationMessage}>
<span className={styles.warningIcon}></span>
<p>Är du säker att du vill radera denna bokning?</p>
<p className={styles.bookingDetails}>
"{booking.title}" den {booking.date.day}/{booking.date.month} kl. {getTimeFromIndex(booking.startTime)}
</p>
</div>
<div className={styles.confirmationButtons}>
<Button
className={styles.confirmDeleteButton}
onPress={confirmDelete}
>
Ja, radera
</Button>
<Button
className={styles.cancelDeleteButton}
onPress={cancelDelete}
>
Avbryt
</Button>
</div>
</div>
)}
</div>
</BookingProvider>
)}

View File

@@ -153,6 +153,31 @@
align-items: center;
}
.deleteButton {
flex: 2;
background-color: #DC2626;
color: white;
height: 3rem;
font-weight: 600;
font-size: 0.9rem;
border: 2px solid #B91C1C;
border-radius: 0.5rem;
transition: all 0.2s ease;
box-shadow: 0 2px 4px rgba(220, 38, 38, 0.2);
cursor: pointer;
}
.deleteButton:hover {
background-color: #B91C1C;
box-shadow: 0 4px 8px rgba(220, 38, 38, 0.3);
}
.deleteButton:active {
background-color: #991B1B;
transform: translateY(1px);
box-shadow: 0 1px 2px rgba(220, 38, 38, 0.2);
}
.cancelButton {
flex: 2;
background-color: white;
@@ -202,7 +227,8 @@
}
.saveButton[data-focused],
.cancelButton[data-focused] {
.cancelButton[data-focused],
.deleteButton[data-focused] {
outline: 2px solid #2563EB;
outline-offset: -1px;
}
@@ -355,4 +381,100 @@
color: #999;
font-style: italic;
font-size: 0.9rem;
}
/* Confirmation dialog styles */
.confirmationSection {
background-color: #FFF8DC;
border: 2px solid #FFD700;
border-radius: 0.5rem;
padding: 1.5rem;
margin-top: 1rem;
}
.confirmationMessage {
text-align: center;
margin-bottom: 1.5rem;
}
.warningIcon {
font-size: 2rem;
display: block;
margin-bottom: 0.5rem;
}
.confirmationMessage p {
margin: 0.5rem 0;
color: #333;
}
.confirmationMessage p:first-of-type {
font-weight: 600;
font-size: 1.1rem;
}
.bookingDetails {
font-size: 0.9rem;
color: #666;
font-style: italic;
}
.confirmationButtons {
display: flex;
gap: 1rem;
justify-content: center;
}
.confirmDeleteButton {
background-color: #DC2626;
color: white;
height: 3rem;
font-weight: 600;
font-size: 0.95rem;
border: 2px solid #B91C1C;
border-radius: 0.5rem;
transition: all 0.2s ease;
box-shadow: 0 2px 4px rgba(220, 38, 38, 0.2);
cursor: pointer;
padding: 0 1.5rem;
}
.confirmDeleteButton:hover {
background-color: #B91C1C;
box-shadow: 0 4px 8px rgba(220, 38, 38, 0.3);
}
.confirmDeleteButton:active {
background-color: #991B1B;
transform: translateY(1px);
box-shadow: 0 1px 2px rgba(220, 38, 38, 0.2);
}
.cancelDeleteButton {
background-color: white;
height: 3rem;
color: #374151;
font-weight: 600;
border: 2px solid #d1d5db;
border-radius: 0.5rem;
transition: all 0.2s ease;
cursor: pointer;
font-size: 0.95rem;
padding: 0 1.5rem;
}
.cancelDeleteButton:hover {
background-color: #f9fafb;
border-color: #9ca3af;
}
.cancelDeleteButton:active {
background-color: #e5e7eb;
transform: translateY(1px);
}
.confirmDeleteButton[data-focused],
.cancelDeleteButton[data-focused] {
outline: 2px solid #2563EB;
outline-offset: -1px;
}

View File

@@ -4,7 +4,7 @@ import styles from './BookingsList.module.css';
import BookingCard from './BookingCard';
import BookingConfirmationBanner from './BookingConfirmationBanner';
function BookingsList({ bookings, handleEditBooking, onBookingUpdate, showSuccessBanner, lastCreatedBooking, onDismissBanner, showDevelopmentBanner, showBookingConfirmationBanner }) {
function BookingsList({ bookings, handleEditBooking, onBookingUpdate, onBookingDelete, showSuccessBanner, lastCreatedBooking, onDismissBanner, showDevelopmentBanner, showBookingConfirmationBanner }) {
const [showAll, setShowAll] = useState(false);
const [expandedBookingId, setExpandedBookingId] = useState(null);
const INITIAL_DISPLAY_COUNT = 3;
@@ -56,6 +56,7 @@ function BookingsList({ bookings, handleEditBooking, onBookingUpdate, showSucces
onClick={() => handleBookingClick(booking)}
isExpanded={expandedBookingId === booking.id}
onBookingUpdate={onBookingUpdate}
onBookingDelete={onBookingDelete}
/>
))}
{hasMoreBookings && (

View File

@@ -5,7 +5,7 @@ import BookingsList from '../components/BookingsList';
import Card from '../components/Card';
import { useSettingsContext } from '../context/SettingsContext';
export function RoomBooking({ bookings, showSuccessBanner, lastCreatedBooking, onDismissBanner, onBookingUpdate }) {
export function RoomBooking({ bookings, showSuccessBanner, lastCreatedBooking, onDismissBanner, onBookingUpdate, onBookingDelete }) {
const { settings } = useSettingsContext();
function handleEditBooking(booking) {
@@ -21,6 +21,7 @@ export function RoomBooking({ bookings, showSuccessBanner, lastCreatedBooking, o
bookings={bookings}
handleEditBooking={handleEditBooking}
onBookingUpdate={onBookingUpdate}
onBookingDelete={onBookingDelete}
showSuccessBanner={showSuccessBanner}
lastCreatedBooking={lastCreatedBooking}
onDismissBanner={onDismissBanner}