Skip to content

Commit

Permalink
Merge branch 'feat_for_user_name' into 'main'
Browse files Browse the repository at this point in the history
lumen: 👥 Add 'book for someone' feature

See merge request resa/github!28

GitOrigin-RevId: 7676ff927b1e1394348861def1864ecd566acde2
  • Loading branch information
p-bizouard committed Mar 4, 2024
1 parent d037b65 commit 2585a29
Show file tree
Hide file tree
Showing 17 changed files with 259 additions and 102 deletions.
3 changes: 1 addition & 2 deletions back/src/routes/book.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ router.post("/add/", requireAgendaAnnuaire, async (
/!\ startDate and endDate must be in ISO 8601 string format.
*/

try {
// Sanity check of inputs
validate.input(validate.schema.addEvent, req.body);
Expand All @@ -61,7 +60,7 @@ router.post("/add/", requireAgendaAnnuaire, async (
);
if (!room.allowBookings) {
if (room.belongsTo.length === 0) {
// ? Room need to belongs to a group that has some members
logger.error("Room need to belongs to a group that has some members");
res.sendStatus(500);
return;
}
Expand Down
7 changes: 3 additions & 4 deletions back/src/webservice/book.js
Original file line number Diff line number Diff line change
Expand Up @@ -243,10 +243,9 @@ async function getStapledPersonEventList(
.filter((event) => event.room !== null) // Filter out events about rooms that don't exist anymore in GEODE
.filter((event) => event.endDate.isAfter(moment().subtract(3, "months"))); // Filter out past bookings older than 3 months old

parsedEvents.sort(
(eventA, eventB) => eventA.startDate.valueOf() - eventB.startDate.valueOf(),
);

parsedEvents.sort(
(eventA, eventB) => eventA.startDate.valueOf() - eventB.startDate.valueOf(),
);

// Group past and future events separately
const groupedParsedEvents /* : { [key: "future" | "past" ]: Event_Room[] } */ = groupBy(
Expand Down
57 changes: 42 additions & 15 deletions front/src/actions/bookings/modify/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,46 @@ import {
RECEIVE_MODIF_ALREADY_BOOKED_ERROR,
} from './types';

export const initializeModifModal = makeActionCreator(INITIALIZE_MODIF_MODAL, 'event', 'modifType');
export const setNameOfModifiedEvent = makeActionCreator(SET_NAME_OF_MODIFIED_EVENT, 'newName');
export const setStartHourOfModifiedEvent = makeActionCreator(SET_START_HOUR_OF_MODIFIED_EVENT, 'newStartHour');
export const setStartMinutesOfModifiedEvent = makeActionCreator(SET_START_MINUTES_OF_MODIFIED_EVENT, 'newStartMinutes');
export const setEndHourOfModifiedEvent = makeActionCreator(SET_END_HOUR_OF_MODIFIED_EVENT, 'newEndHour');
export const setEndMinutesOfModifiedEvent = makeActionCreator(SET_END_MINUTES_OF_MODIFIED_EVENT, 'newEndMinutes');
export const setRoomIdOfModifiedEvent = makeActionCreator(SET_ROOM_ID_OF_MODIFIED_EVENT, 'newRoomId');
export const initializeModifModal = makeActionCreator(
INITIALIZE_MODIF_MODAL,
'event',
'modifType',
);
export const setNameOfModifiedEvent = makeActionCreator(
SET_NAME_OF_MODIFIED_EVENT,
'newName',
);
export const setStartHourOfModifiedEvent = makeActionCreator(
SET_START_HOUR_OF_MODIFIED_EVENT,
'newStartHour',
);
export const setStartMinutesOfModifiedEvent = makeActionCreator(
SET_START_MINUTES_OF_MODIFIED_EVENT,
'newStartMinutes',
);
export const setEndHourOfModifiedEvent = makeActionCreator(
SET_END_HOUR_OF_MODIFIED_EVENT,
'newEndHour',
);
export const setEndMinutesOfModifiedEvent = makeActionCreator(
SET_END_MINUTES_OF_MODIFIED_EVENT,
'newEndMinutes',
);
export const setRoomIdOfModifiedEvent = makeActionCreator(
SET_ROOM_ID_OF_MODIFIED_EVENT,
'newRoomId',
);
export const attemptModifConfirm = makeActionCreator(ATTEMPT_MODIF_CONFIRM);
export const requestModif = makeActionCreator(REQUEST_MODIF);
export const receiveModifConfirmation = makeActionCreator(RECEIVE_MODIF_CONFIRMATION);
export const receiveModifUnknownError = makeActionCreator(RECEIVE_MODIF_UNKNOWN_ERROR);
export const receiveModifAlreadyBookedError = makeActionCreator(RECEIVE_MODIF_ALREADY_BOOKED_ERROR);
export const receiveModifConfirmation = makeActionCreator(
RECEIVE_MODIF_CONFIRMATION,
);
export const receiveModifUnknownError = makeActionCreator(
RECEIVE_MODIF_UNKNOWN_ERROR,
);
export const receiveModifAlreadyBookedError = makeActionCreator(
RECEIVE_MODIF_ALREADY_BOOKED_ERROR,
);

export function sendModifRequest(event, newAttr) {
function getUpdatedISOstring(isoDate, hour, minutes) {
Expand All @@ -43,7 +71,6 @@ export function sendModifRequest(event, newAttr) {

// Do nothing if eventName is empty
if (!newAttr.eventName) return;

dispatch(requestModif());

// Format dates
Expand All @@ -60,10 +87,10 @@ export function sendModifRequest(event, newAttr) {

// Test if something has changed
if (
event.name === newAttr.eventName
&& event.startDate === newStartDate
&& event.endDate === newEndDate
&& event.room.id === newAttr.roomId
event.name === newAttr.eventName &&
event.startDate === newStartDate &&
event.endDate === newEndDate &&
event.room.id === newAttr.roomId
) {
dispatch(receiveModifConfirmation());
return;
Expand Down
13 changes: 6 additions & 7 deletions front/src/actions/rooms/book/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { forceFetchBookings } from 'actions/bookings/list';
import {
SELECT_ROOM_TO_BOOK,
SET_EVENT_NAME,
SET_FOR_USER_NAME,
SET_VIDEO_PROVIDER,
ATTEMPT_BOOK_CONFIRM,
REQUEST_BOOK,
Expand All @@ -22,6 +23,7 @@ export const selectRoomToBook = makeActionCreator(
'payload',
);
export const setEventName = makeActionCreator(SET_EVENT_NAME, 'payload');
export const setForUserName = makeActionCreator(SET_FOR_USER_NAME, 'payload');
export const setVideoProvider = makeActionCreator(
SET_VIDEO_PROVIDER,
'payload',
Expand Down Expand Up @@ -50,12 +52,9 @@ export function sendBookRequest() {
dispatch(attemptBookConfirm());

const state = getState();
const { room, eventName, videoProvider } = state.search.book;
const {
selectedDate,
selectedStartTime,
selectedEndTime,
} = state.search.dateTime;
const { room, eventName, forUserName, videoProvider } = state.search.book;
const { selectedDate, selectedStartTime, selectedEndTime } =
state.search.dateTime;
const formattedDate = getFormattedDate(
selectedDate,
selectedStartTime,
Expand All @@ -75,7 +74,7 @@ export function sendBookRequest() {
'Content-Type': 'application/json',
},
body: JSON.stringify({
eventName,
eventName: forUserName ? `${forUserName} - ${eventName}` : eventName,
videoProvider,
startDate: formattedDate.start,
endDate: formattedDate.end,
Expand Down
1 change: 1 addition & 0 deletions front/src/actions/rooms/book/types.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export const SELECT_ROOM_TO_BOOK = 'SELECT_ROOM_TO_BOOK';
export const SET_EVENT_NAME = 'SET_EVENT_NAME';
export const SET_FOR_USER_NAME = 'SET_FOR_USER_NAME';
export const SET_VIDEO_PROVIDER = 'SET_VIDEO_PROVIDER';
export const ATTEMPT_BOOK_CONFIRM = 'ATTEMPT_BOOK_CONFIRM';
export const REQUEST_BOOK = 'REQUEST_BOOK';
Expand Down
17 changes: 5 additions & 12 deletions front/src/components/partials/EventList.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ const EventList = ({
Aucun évènement n'est prévu
{!useToday && ` le ${moment(selectedDate).format('D MMMM')} `}
{useToday && " aujourd'hui "}
en
 
en  
<span className="font-weight-bold">{roomName}</span>
</h6>
);
Expand All @@ -37,8 +36,7 @@ const EventList = ({
{events.length >= 2 && `${events.length} évènements sont prévus`}
{!useToday && ` le ${moment(selectedDate).format('D MMMM')} `}
{useToday && " aujourd'hui "}
en
&nbsp;
en &nbsp;
<span className="font-weight-bold">{roomName}</span>
</h6>
<div className="list-group mt-3">
Expand All @@ -55,18 +53,13 @@ const EventList = ({
<h5 className="mb-1">{event.name}</h5>
<span className={!isHighlighted ? 'text-muted' : ''}>
de&nbsp;
{moment(event.startDate)
.utc()
.format('H[h]mm')}
{moment(event.startDate).utc().format('H[h]mm')}
&nbsp;à&nbsp;
{moment(event.endDate)
.utc()
.format('H[h]mm')}
{moment(event.endDate).utc().format('H[h]mm')}
</span>
</div>
<span className={!isHighlighted ? 'text-muted' : ''}>
Réservé par
&nbsp;
Réservé par &nbsp;
<a
className={!isHighlighted ? 'text-secondary' : 'text-white'}
href={`mailto:${event.author.email}`}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ import 'moment/locale/fr';
import RoomResource from 'containers/partials/RoomResource';
import extractResources from 'services/extractResources';

const Booking = ({
event, handleCancelEvent, handleModifyEvent, isFuture,
}) => (
const Booking = ({ event, handleCancelEvent, handleModifyEvent, isFuture }) => (
<div className="card mb-3">
<div className="card-body">
<div className="row align-items-center justify-content-between">
Expand All @@ -23,8 +21,8 @@ const Booking = ({
</div>
<div className="col-lg-4">
<ul>
{event.room
&& extractResources(event.room, true).map((res) => (
{event.room &&
extractResources(event.room, true).map((res) => (
<RoomResource
key={`${event.room.id}#${res.type}`}
resource={res}
Expand All @@ -35,19 +33,13 @@ const Booking = ({
</div>
<div className="col-lg-3 my-4 custom-info-text-color">
<h5>{event.name}</h5>
{moment(event.startDate)
.utc()
.format('dddd D MMMM YYYY')}
{moment(event.startDate).utc().format('dddd D MMMM YYYY')}
<br />
{moment(event.startDate)
.utc()
.format('H[h]mm')}
{moment(event.startDate).utc().format('H[h]mm')}
&nbsp;
<FontAwesomeIcon icon={faAngleRight} />
&nbsp;
{moment(event.endDate)
.utc()
.format('H[h]mm')}
{moment(event.endDate).utc().format('H[h]mm')}
</div>
<div className="col-lg-3 custom-text-right-above-lg custom-text-center-under-lg">
{isFuture && !event.local && (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// lib
import React from 'react';
import PropTypes from 'prop-types';
// src
import BookingSummary from './BookingSummary';

const ForUserNameChangeBody = ({
event,
handleForUserNameInputChange,
forUserName,
detectEnter,
attemptedConfirm,
}) => [
<div
className={attemptedConfirm ? 'form-group was-validated' : 'form-group'}
key="forUserNameForm"
>
<label htmlFor="forUserName">Pour le compte de :</label>
<input
type="text"
className={forUserName ? 'form-control valid' : 'form-control invalid'}
id="forUserName"
maxLength="150"
value={forUserName}
onChange={handleForUserNameInputChange}
onKeyPress={detectEnter}
/>
</div>,
<div className="text-center" key="eventDetails">
<BookingSummary event={event} />
</div>,
];

ForUserNameChangeBody.propTypes = {
event: PropTypes.object.isRequired,
handleForUserNameInputChange: PropTypes.func.isRequired,
forUserName: PropTypes.string.isRequired,
detectEnter: PropTypes.func.isRequired,
attemptedConfirm: PropTypes.bool.isRequired,
};

export default ForUserNameChangeBody;
Original file line number Diff line number Diff line change
Expand Up @@ -16,32 +16,33 @@ const ConfirmModify = ({
detectEnter,
attemptedConfirm,
}) => {
const body = modifType === 'name' ? (
<NameChangeBody
event={event}
handleNameInputChange={handleNameInputChange}
eventName={newAttributes.eventName}
detectEnter={detectEnter}
attemptedConfirm={attemptedConfirm}
/>
) : (
<TimeChangeBody
event={event}
handleDateInputChange={handleDateInputChange}
newAttributes={newAttributes}
/>
);
const body =
modifType === 'name' ? (
<NameChangeBody
event={event}
handleNameInputChange={handleNameInputChange}
eventName={newAttributes.eventName}
detectEnter={detectEnter}
attemptedConfirm={attemptedConfirm}
/>
) : (
<TimeChangeBody
event={event}
handleDateInputChange={handleDateInputChange}
newAttributes={newAttributes}
/>
);

return (
<ConfirmModal
title="Modification de votre réservation"
body={body}
confirmButtonText={(
confirmButtonText={
<span>
Modifier
<span className="d-none d-sm-inline"> la réservation</span>
</span>
)}
}
confirmButtonFunction={sendUpdatedBooking}
cancelActionText="Ne pas modifier"
/>
Expand Down
16 changes: 8 additions & 8 deletions front/src/components/scenes/Bookings/ModifyEventModal/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default class extends React.PureComponent {

static defaultProps = {
event: null,
}
};

sendUpdatedBooking = () => {
const { dispatch, event, newAttributes } = this.props;
Expand Down Expand Up @@ -65,16 +65,16 @@ export default class extends React.PureComponent {
/>
) : null}
{status.isFetching && <Loading />}
{status.frontendValidationPassed
&& !status.isFetching
&& status.success && <SuccessfulModify />}
{status.frontendValidationPassed
&& !status.isFetching
&& !status.success && (
{status.frontendValidationPassed &&
!status.isFetching &&
status.success && <SuccessfulModify />}
{status.frontendValidationPassed &&
!status.isFetching &&
!status.success && (
<FailedModify
failedBecauseAlreadyBooked={status.failedBecauseAlreadyBooked}
/>
)}
)}
</div>
</div>
);
Expand Down
Loading

0 comments on commit 2585a29

Please sign in to comment.