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:
parent
f9a8453b70
commit
4ecdf431d5
@ -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>
|
||||
);
|
||||
|
@ -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>
|
||||
)
|
||||
}
|
||||
|
@ -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>
|
||||
|
||||
);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user