improving-week-36 #1
@@ -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>
|
||||
|
||||
@@ -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 på 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>
|
||||
)}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 && (
|
||||
|
||||
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user