mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2024-11-28 09:24:24 +01:00
(feat) report status of user's prepaid packs in dashboard
This commit is contained in:
parent
4650d0e1cb
commit
4c4ebe3b47
@ -17,6 +17,8 @@ class API::UserPacksController < API::ApiController
|
||||
end
|
||||
|
||||
def item
|
||||
return nil if params[:priceable_type].nil?
|
||||
|
||||
params[:priceable_type].classify.constantize.find(params[:priceable_id])
|
||||
end
|
||||
end
|
||||
|
@ -1,6 +1,11 @@
|
||||
import { FabPanel } from '../../base/fab-panel';
|
||||
import { Loader } from '../../base/loader';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { UserPack } from '../../../models/user-pack';
|
||||
import UserPackAPI from '../../../api/user-pack';
|
||||
import FormatLib from '../../../lib/format';
|
||||
import SettingAPI from '../../../api/setting';
|
||||
|
||||
interface PrepaidPacksPanelProps {
|
||||
userId: number,
|
||||
@ -10,36 +15,59 @@ interface PrepaidPacksPanelProps {
|
||||
/**
|
||||
* List all available prepaid packs for the given user
|
||||
*/
|
||||
const PrepaidPacksPanel: React.FC<PrepaidPacksPanelProps> = () => {
|
||||
const PrepaidPacksPanel: React.FC<PrepaidPacksPanelProps> = ({ userId, onError }) => {
|
||||
const { t } = useTranslation('logged');
|
||||
|
||||
const [packs, setPacks] = useState<Array<UserPack>>([]);
|
||||
const [threshold, setThreshold] = useState<number>(null);
|
||||
|
||||
useEffect(() => {
|
||||
UserPackAPI.index({ user_id: userId })
|
||||
.then(res => setPacks(res))
|
||||
.catch(error => onError(error));
|
||||
SettingAPI.get('renew_pack_threshold')
|
||||
.then(data => setThreshold(parseFloat(data.value)))
|
||||
.catch(error => onError(error));
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Check if the provided pack has a remaining amount of hours under the defined threshold
|
||||
*/
|
||||
const isLow = (pack: UserPack): boolean => {
|
||||
if (threshold < 1) {
|
||||
return pack.prepaid_pack.minutes - pack.minutes_used <= pack.prepaid_pack.minutes * threshold;
|
||||
}
|
||||
return pack.prepaid_pack.minutes - pack.minutes_used <= threshold * 60;
|
||||
};
|
||||
|
||||
return (
|
||||
<FabPanel className='prepaid-packs-panel'>
|
||||
<p className="title">{t('app.logged.dashboard.reservations_dashboard.prepaid_packs_panel.title')}</p>
|
||||
|
||||
{/* map */}
|
||||
<div className='prepaid-packs is-low'>
|
||||
<div className='prepaid-packs-list'>
|
||||
<span className="prepaid-packs-list-label name">{t('app.logged.dashboard.reservations_dashboard.prepaid_packs_panel.name')}</span>
|
||||
<span className="prepaid-packs-list-label end">{t('app.logged.dashboard.reservations_dashboard.prepaid_packs_panel.end')}</span>
|
||||
<span className="prepaid-packs-list-label countdown">{t('app.logged.dashboard.reservations_dashboard.prepaid_packs_panel.countdown')}</span>
|
||||
{packs.map(pack => (
|
||||
<div className={`prepaid-packs ${isLow(pack) ? 'is-low' : ''}`} key={pack.id}>
|
||||
<div className='prepaid-packs-list'>
|
||||
<span className="prepaid-packs-list-label name">{t('app.logged.dashboard.reservations_dashboard.prepaid_packs_panel.name')}</span>
|
||||
<span className="prepaid-packs-list-label end">{t('app.logged.dashboard.reservations_dashboard.prepaid_packs_panel.end')}</span>
|
||||
<span className="prepaid-packs-list-label countdown">{t('app.logged.dashboard.reservations_dashboard.prepaid_packs_panel.countdown')}</span>
|
||||
|
||||
<div className='prepaid-packs-list-item'>
|
||||
<p className='name'>Pack name</p>
|
||||
<p className='end'>00/00/0000</p>
|
||||
<p className="countdown"><span>00H</span> / 00H</p>
|
||||
<div className='prepaid-packs-list-item'>
|
||||
<p className='name'>{pack.prepaid_pack.priceable.name}</p>
|
||||
{FormatLib.date(pack.expires_at) && <p className="end">{FormatLib.date(pack.expires_at)}</p>}
|
||||
<p className="countdown"><span>{pack.minutes_used / 60}H</span> / {pack.prepaid_pack.minutes / 60}H</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="prepaid-packs-list is-history">
|
||||
<span className='prepaid-packs-list-label'>{t('app.logged.dashboard.reservations_dashboard.prepaid_packs_panel.history')}</span>
|
||||
|
||||
<div className='prepaid-packs-list-item'>
|
||||
<p className='name'>00{t('app.logged.dashboard.reservations_dashboard.prepaid_packs_panel.consumed_hours')}</p>
|
||||
<p className="date">00/00/00</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="prepaid-packs-list is-history">
|
||||
<span className='prepaid-packs-list-label'>{t('app.logged.dashboard.reservations_dashboard.prepaid_packs_panel.history')}</span>
|
||||
|
||||
<div className='prepaid-packs-list-item'>
|
||||
<p className='name'>00{t('app.logged.dashboard.reservations_dashboard.prepaid_packs_panel.consumed_hours')}</p>
|
||||
<p className="date">00/00/00</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<div className='prepaid-packs-cta'>
|
||||
<p>{t('app.logged.dashboard.reservations_dashboard.prepaid_packs_panel.cta_info')}</p>
|
||||
|
@ -31,17 +31,17 @@ const ReservationsDashboard: React.FC<ReservationsDashboardProps> = ({ onError,
|
||||
|
||||
return (
|
||||
<div className="reservations-dashboard">
|
||||
<div className="section">
|
||||
{modules?.get('machines_module') !== 'false' && <div className="section">
|
||||
<p className="section-title">{t('app.logged.dashboard.reservations_dashboard.machine_section_title')}</p>
|
||||
{modules?.get('machines_module') !== 'false' && <CreditsPanel userId={userId} onError={onError} reservableType="Machine" />}
|
||||
<CreditsPanel userId={userId} onError={onError} reservableType="Machine" />
|
||||
<PrepaidPacksPanel userId={userId} onError={onError} />
|
||||
{modules?.get('machines_module') !== 'false' && <ReservationsPanel userId={userId} onError={onError} reservableType="Machine" />}
|
||||
</div>
|
||||
<div className="section">
|
||||
<ReservationsPanel userId={userId} onError={onError} reservableType="Machine" />
|
||||
</div>}
|
||||
{modules?.get('spaces_module') !== 'false' && <div className="section">
|
||||
<p className="section-title">{t('app.logged.dashboard.reservations_dashboard.space_section_title')}</p>
|
||||
{modules?.get('spaces_module') !== 'false' && <CreditsPanel userId={userId} onError={onError} reservableType="Space" />}
|
||||
{modules?.get('spaces_module') !== 'false' && <ReservationsPanel userId={userId} onError={onError} reservableType="Space" />}
|
||||
</div>
|
||||
<CreditsPanel userId={userId} onError={onError} reservableType="Space" />
|
||||
<ReservationsPanel userId={userId} onError={onError} reservableType="Space" />
|
||||
</div>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -2,15 +2,20 @@ import { TDateISO } from '../typings/date-iso';
|
||||
import { ApiFilter } from './api';
|
||||
|
||||
export interface UserPackIndexFilter extends ApiFilter {
|
||||
user_id?: number,
|
||||
priceable_type: string,
|
||||
priceable_id: number
|
||||
user_id: number,
|
||||
priceable_type?: string,
|
||||
priceable_id?: number
|
||||
}
|
||||
|
||||
export interface UserPack {
|
||||
id: number,
|
||||
minutes_used: number,
|
||||
expires_at: TDateISO,
|
||||
prepaid_pack: {
|
||||
minutes: number,
|
||||
priceable_type: 'Machine'|'Space',
|
||||
priceable: {
|
||||
name: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,10 @@
|
||||
# Provides methods for PrepaidPack
|
||||
class PrepaidPackService
|
||||
class << self
|
||||
# @param filters [Hash{Symbol=>Integer,String}]
|
||||
# @option filters [Integer] :group_id
|
||||
# @option filters [Integer] :priceable_id
|
||||
# @option filters [String] :priceable_type 'Machine' | 'Space'
|
||||
def list(filters)
|
||||
packs = PrepaidPack.where(nil)
|
||||
|
||||
@ -19,18 +23,24 @@ class PrepaidPackService
|
||||
end
|
||||
|
||||
# return the not expired packs for the given item bought by the given user
|
||||
def user_packs(user, priceable)
|
||||
StatisticProfilePrepaidPack
|
||||
.includes(:prepaid_pack)
|
||||
.references(:prepaid_packs)
|
||||
.where(statistic_profile_id: user.statistic_profile.id)
|
||||
.where('expires_at > ? OR expires_at IS NULL', Time.current)
|
||||
.where(prepaid_packs: { priceable_id: priceable.id })
|
||||
.where(prepaid_packs: { priceable_type: priceable.class.name })
|
||||
.where('minutes_used < prepaid_packs.minutes')
|
||||
# @param user [User]
|
||||
# @param priceable [Machine,Space,NilClass]
|
||||
def user_packs(user, priceable = nil)
|
||||
sppp = StatisticProfilePrepaidPack.includes(:prepaid_pack)
|
||||
.references(:prepaid_packs)
|
||||
.where(statistic_profile_id: user.statistic_profile.id)
|
||||
.where('expires_at > ? OR expires_at IS NULL', Time.current)
|
||||
.where('minutes_used < prepaid_packs.minutes')
|
||||
unless priceable.nil?
|
||||
sppp = sppp.where(prepaid_packs: { priceable_id: priceable.id })
|
||||
.where(prepaid_packs: { priceable_type: priceable.class.name })
|
||||
end
|
||||
sppp
|
||||
end
|
||||
|
||||
# subtract the number of used prepaid minutes from the user's count
|
||||
# @param user [User]
|
||||
# @param reservation [Reservation]
|
||||
def update_user_minutes(user, reservation)
|
||||
# total number of minutes available in user's packs
|
||||
available_minutes = minutes_available(user, reservation.reservable)
|
||||
@ -59,7 +69,9 @@ class PrepaidPackService
|
||||
end
|
||||
end
|
||||
|
||||
## Total number of prepaid minutes available
|
||||
# Total number of prepaid minutes available
|
||||
# @param user [User]
|
||||
# @param priceable [Machine,Space]
|
||||
def minutes_available(user, priceable)
|
||||
return 0 if Setting.get('pack_only_for_subscription') && !user.subscribed_plan
|
||||
|
||||
|
@ -1,8 +1,11 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
json.array!(@user_packs) do |user_pack|
|
||||
json.extract! user_pack, :minutes_used, :expires_at
|
||||
json.extract! user_pack, :id, :minutes_used, :expires_at
|
||||
json.prepaid_pack do
|
||||
json.extract! user_pack.prepaid_pack, :minutes
|
||||
json.extract! user_pack.prepaid_pack, :minutes, :priceable_type
|
||||
json.priceable do
|
||||
json.extract! user_pack.prepaid_pack.priceable, :name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user