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

157 lines
5.1 KiB
TypeScript
Raw Normal View History

2021-06-29 11:14:36 +02:00
import React, { useEffect, useState } from 'react';
2021-06-29 15:59:57 +02:00
import _ from 'lodash';
2021-06-29 11:14:36 +02:00
import { Machine } from '../../models/machine';
import { User } from '../../models/user';
import { UserPack } from '../../models/user-pack';
import UserPackAPI from '../../api/user-pack';
import SettingAPI from '../../api/setting';
import { SettingName } from '../../models/setting';
import { FabButton } from '../base/fab-button';
import { useTranslation } from 'react-i18next';
import { ProposePacksModal } from './propose-packs-modal';
import { Loader } from '../base/loader';
import { react2angular } from 'react2angular';
import { IApplication } from '../../models/application';
declare var Application: IApplication;
type PackableItem = Machine;
interface PacksSummaryProps {
item: PackableItem,
itemType: 'Machine',
2021-06-29 15:59:57 +02:00
customer?: User,
2021-06-29 11:14:36 +02:00
operator: User,
onError: (message: string) => void,
onSuccess: (message: string) => void,
refresh?: Promise<void>
2021-06-29 11:14:36 +02:00
}
const PacksSummaryComponent: React.FC<PacksSummaryProps> = ({ item, itemType, customer, operator, onError, onSuccess, refresh }) => {
2021-06-29 11:14:36 +02:00
const { t } = useTranslation('logged');
const [userPacks, setUserPacks] = useState<Array<UserPack>>(null);
const [threshold, setThreshold] = useState<number>(null);
const [packsModal, setPacksModal] = useState<boolean>(false);
useEffect(() => {
SettingAPI.get(SettingName.RenewPackThreshold)
.then(data => setThreshold(parseFloat(data.value)))
.catch(error => onError(error));
2021-06-29 15:59:57 +02:00
}, []);
useEffect(() => {
if (_.isEmpty(customer)) return;
getUserPacksData();
}, [item, itemType, customer]);
useEffect(() => {
if (refresh instanceof Promise) {
refresh.then(getUserPacksData);
}
}, [refresh]);
/**
* Fetch the user packs data from the API
*/
const getUserPacksData = (): void => {
2021-06-29 15:59:57 +02:00
UserPackAPI.index({ user_id: customer.id, priceable_type: itemType, priceable_id: item.id })
.then(data => setUserPacks(data))
.catch(error => onError(error));
}
2021-06-29 11:14:36 +02:00
/**
* Total of minutes used by the customer
*/
const totalUsed = (): number => {
if (!userPacks) return 0;
2021-06-29 15:59:57 +02:00
return userPacks.map(up => up.minutes_used).reduce((acc, curr) => acc + curr, 0);
2021-06-29 11:14:36 +02:00
}
/**
* Total of minutes available is the packs bought by the customer
*/
const totalAvailable = (): number => {
if (!userPacks) return 0;
2021-06-29 15:59:57 +02:00
return userPacks.map(up => up.prepaid_pack.minutes).reduce((acc, curr) => acc + curr, 0);
2021-06-29 11:14:36 +02:00
}
/**
* Total prepaid hours remaining for the current customer
*/
const totalHours = (): number => {
2021-06-29 15:59:57 +02:00
return (totalAvailable() - totalUsed()) / 60;
2021-06-29 11:14:36 +02:00
}
/**
2021-06-29 15:59:57 +02:00
* Do we need to display the "buy new pack" button?
2021-06-29 11:14:36 +02:00
*/
2021-06-29 15:59:57 +02:00
const shouldDisplayButton = (): boolean => {
2021-06-29 11:14:36 +02:00
if (threshold < 1) {
2021-06-29 15:59:57 +02:00
return totalAvailable() - totalUsed() <= totalAvailable() * threshold;
2021-06-29 11:14:36 +02:00
}
2021-06-29 15:59:57 +02:00
return totalAvailable() - totalUsed() <= threshold * 60;
2021-06-29 11:14:36 +02:00
}
/**
* Open/closes the prepaid-pack buying modal
*/
const togglePacksModal = (): void => {
setPacksModal(!packsModal);
}
/**
* Callback triggered when the customer has successfully bought a prepaid-pack
*/
const handlePackBoughtSuccess = (message: string): void => {
onSuccess(message);
togglePacksModal();
UserPackAPI.index({ user_id: customer.id, priceable_type: itemType, priceable_id: item.id })
.then(data => setUserPacks(data))
.catch(error => onError(error));
}
2021-06-29 15:59:57 +02:00
// prevent component rendering if no customer selected
if (_.isEmpty(customer)) return <div />;
2021-06-29 11:14:36 +02:00
return (
<div className="packs-summary">
2021-06-29 15:59:57 +02:00
<h3>{t('app.logged.packs_summary.prepaid_hours')}</h3>
<div className="content">
<span className="remaining-hours">
{totalHours() > 0 && t('app.logged.packs_summary.remaining_HOURS', { HOURS: totalHours(), ITEM: itemType })}
{totalHours() === 0 && t('app.logged.packs_summary.no_hours', { ITEM: itemType })}
</span>
2021-06-29 15:59:57 +02:00
{shouldDisplayButton() && <div className="button-wrapper">
<FabButton className="buy-button" onClick={togglePacksModal} icon={<i className="fa fa-shopping-cart"/>}>
{t('app.logged.packs_summary.buy_a_new_pack')}
</FabButton>
<ProposePacksModal isOpen={packsModal}
toggleModal={togglePacksModal}
item={item}
itemType={itemType}
customer={customer}
operator={operator}
onError={onError}
onDecline={togglePacksModal}
onSuccess={handlePackBoughtSuccess} />
</div>}
</div>
2021-06-29 11:14:36 +02:00
</div>
);
}
export const PacksSummary: React.FC<PacksSummaryProps> = ({ item, itemType, customer, operator, onError, onSuccess, refresh }) => {
2021-06-29 11:14:36 +02:00
return (
<Loader>
<PacksSummaryComponent item={item} itemType={itemType} customer={customer} operator={operator} onError={onError} onSuccess={onSuccess} refresh={refresh} />
2021-06-29 11:14:36 +02:00
</Loader>
);
}
Application.Components.component('packsSummary', react2angular(PacksSummary, ['item', 'itemType', 'customer', 'operator', 'onError', 'onSuccess', 'refresh']));