1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-30 19:52:20 +01:00

fix pending traning modal

This commit is contained in:
Sylvain 2021-06-18 12:47:04 +02:00
parent f9a8453b70
commit 4ecdf431d5
5 changed files with 82 additions and 42 deletions

View File

@ -65,10 +65,12 @@ const MachineCardComponent: React.FC<MachineCardProps> = ({ user, machine, onSho
<i className="fas fa-bookmark" />
{t('app.public.machine_card.book')}
</ReserveButton>}
<button onClick={handleShowMachine} className="show-button">
<i className="fas fa-eye" />
{t('app.public.machine_card.consult')}
</button>
<span>
<button onClick={handleShowMachine} className="show-button">
<i className="fas fa-eye" />
{t('app.public.machine_card.consult')}
</button>
</span>
</div>
</div>
);

View File

@ -1,7 +1,11 @@
import React from 'react';
import moment from 'moment';
import { FabModal } from '../base/fab-modal';
import { useTranslation } from 'react-i18next';
import { HtmlTranslate } from '../base/html-translate';
import { IFablab } from '../../models/fablab';
declare var Fablab: IFablab;
interface PendingTrainingModalProps {
isOpen: boolean,
@ -15,8 +19,10 @@ export const PendingTrainingModal: React.FC<PendingTrainingModalProps> = ({ isOp
/**
* Return the formatted localized date for the given date
*/
const formatDate = (date: Date): string => {
return Intl.DateTimeFormat().format(date);
const formatDateTime = (date: Date): string => {
const day = Intl.DateTimeFormat().format(moment(date).toDate());
const time = Intl.DateTimeFormat(Fablab.intl_locale, { hour: 'numeric', minute: 'numeric' }).format(moment(date).toDate());
return t('app.logged.pending_training_modal.DATE_TIME', { DATE: day, TIME:time });
}
return (
@ -25,7 +31,7 @@ export const PendingTrainingModal: React.FC<PendingTrainingModalProps> = ({ isOp
toggleModal={toggleModal}
closeButton={true}>
<p>{t('app.logged.pending_training_modal.wait_for_validated')}</p>
<p><HtmlTranslate trKey="app.logged.pending_training_modal.training_will_occur_DATE_html" options={{DATE: formatDate(nextReservation)}} /></p>
<p><HtmlTranslate trKey="app.logged.pending_training_modal.training_will_occur_DATE_html" options={{ DATE: formatDateTime(nextReservation) }} /></p>
</FabModal>
)
}

View File

@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { BaseSyntheticEvent, useState } from 'react';
import { PendingTrainingModal } from './pending-training-modal';
import MachineAPI from '../../api/machine';
import { Machine } from '../../models/machine';
@ -20,17 +20,27 @@ interface ReserveButtonProps {
*/
export const ReserveButton: React.FC<ReserveButtonProps> = ({ currentUser, machineId, onLoginRequested, onLoadingStart, onLoadingEnd, onError, onReserveMachine, className, children }) => {
const [machine, setMachine] = useState<Machine>(null);
const [pendingTraining, setPendingTraining] = useState<boolean>(false);
/**
* Callback triggered when the user clicks on the 'reserve' button.
* We load the full machine data, then we check if the user has passed the training for it (if it's needed)
*/
const handleClick = (user?: User): void => {
const handleClick = (event: BaseSyntheticEvent): void => {
event.preventDefault();
getMachine(currentUser);
};
/**
* We load the full machine data, including data on the current user status for this machine.
* Then we check if the user has passed the training for it (if it's needed)
*/
const getMachine = (user: User): void => {
if (onLoadingStart) onLoadingStart();
MachineAPI.get(machineId)
.then(data => {
setMachine(data);
checkTraining(data, user);
if (onLoadingEnd) onLoadingEnd();
})
@ -38,7 +48,14 @@ export const ReserveButton: React.FC<ReserveButtonProps> = ({ currentUser, machi
onError(error);
if (onLoadingEnd) onLoadingEnd();
});
}
};
/**
* Open/closes the alert modal informing the user about his pending training
*/
const togglePendingTrainingModal = (): void => {
setPendingTraining(!pendingTraining);
};
/**
* Check that the current user has passed the required training before allowing him to book
@ -47,7 +64,7 @@ export const ReserveButton: React.FC<ReserveButtonProps> = ({ currentUser, machi
// if there's no user currently logged, trigger the logging process
if (!user) {
onLoginRequested()
.then(user => handleClick(user))
.then(user => getMachine(user))
.catch(error => onError(error));
return;
}
@ -58,17 +75,22 @@ export const ReserveButton: React.FC<ReserveButtonProps> = ({ currentUser, machi
return onReserveMachine(machineId);
}
// if a user is authenticated and have booked a training for this machine, tell him that he must wait
// if there's an authenticated user, and he booked a training for this machine, tell him that he must wait
// for an admin to validate the training before he can book the reservation
if (machine.current_user_next_training_reservation) {
return setPendingTraining(true);
}
}
};
return (
<button onClick={() => handleClick(currentUser)} className={className}>
{children}
<PendingTrainingModal isOpen={pendingTraining} />
</button>
<span>
<button onClick={handleClick} className={className}>
{children}
</button>
<PendingTrainingModal isOpen={pendingTraining}
toggleModal={togglePendingTrainingModal}
nextReservation={machine?.current_user_next_training_reservation?.slots_attributes[0]?.start_at} />
</span>
);
}

View File

@ -17,6 +17,7 @@
background: rgba(29, 29, 29, 0.5);
border-radius: 6px;
margin: -1px;
z-index: 1;
}
&.loading::after {
@ -25,9 +26,9 @@
text-align: center;
font-weight: 900;
position: absolute;
left: 41%;
width: 100%;
font-size: 4em;
top: 35%;
top: 110px;
color: white;
animation: spin 2s linear infinite;
}
@ -83,7 +84,10 @@
font-weight: 600;
color: #000;
margin: 0;
line-height: 1.8rem;
height: 4em;
display: flex;
justify-content: center;
align-items: center;
}
.machine-actions {
@ -95,31 +99,36 @@
text-align: center;
display: flex;
& > button {
border: none !important;
padding: 15px 12px;
display: block;
& > span {
width: 50%;
background-color: #fbfbfb;
margin-bottom: 0;
font-weight: normal;
text-align: center;
white-space: nowrap;
vertical-align: middle;
touch-action: manipulation;
cursor: pointer;
background-image: none;
font-size: 16px;
line-height: 1.5;
border-radius: 4px;
& > i {
margin-right: 5px;
& > button {
border: none !important;
padding: 15px 12px;
display: block;
width: 100%;
background-color: #fbfbfb;
margin-bottom: 0;
font-weight: normal;
text-align: center;
white-space: nowrap;
vertical-align: middle;
touch-action: manipulation;
cursor: pointer;
background-image: none;
font-size: 16px;
line-height: 1.5;
border-radius: 4px;
& > i {
margin-right: 5px;
}
&.reserve-button {
border-right: 1px solid #dddddd !important;
}
}
&.reserve-button {
border-right: 1px solid #dddddd !important;
}
}
}

View File

@ -170,6 +170,7 @@ en:
machine_reservation: "Machine reservation"
wait_for_validated: "You must wait for your training is being validated by the FabLab team to book this machine."
training_will_occur_DATE_html: "Your training will occur at <strong>{DATE}</strong>"
DATE_TIME: "{DATE} {TIME}"
#book a training
trainings_reserve:
trainings_planning: "Trainings planning"