mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-01-29 18:52:22 +01:00
delete & disable packs
This commit is contained in:
parent
1a65b97653
commit
0345d22582
@ -47,6 +47,6 @@ class API::PrepaidPacksController < API::ApiController
|
||||
def pack_params
|
||||
pack_params = params
|
||||
pack_params[:pack][:amount] = pack_params[:pack][:amount].to_f * 100.0 if pack_params[:pack][:amount]
|
||||
params.require(:pack).permit(:priceable_id, :priceable_type, :group_id, :amount, :minutes)
|
||||
params.require(:pack).permit(:priceable_id, :priceable_type, :group_id, :amount, :minutes, :disabled)
|
||||
end
|
||||
end
|
||||
|
@ -7,6 +7,7 @@ import PrepaidPackAPI from '../../api/prepaid-pack';
|
||||
import { IFablab } from '../../models/fablab';
|
||||
import { duration } from 'moment';
|
||||
import { FabButton } from '../base/fab-button';
|
||||
import { DeletePack } from './delete-pack';
|
||||
|
||||
declare var Fablab: IFablab;
|
||||
|
||||
@ -30,7 +31,6 @@ export const ConfigurePacksButton: React.FC<ConfigurePacksButtonProps> = ({ pack
|
||||
const [showList, setShowList] = useState<boolean>(false);
|
||||
const [addPackModal, setAddPackModal] = useState<boolean>(false);
|
||||
const [editPackModal, setEditPackModal] = useState<boolean>(false);
|
||||
const [deletePackModal, setDeletePackModal] = useState<boolean>(false);
|
||||
|
||||
/**
|
||||
* Return the formatted localized amount for the given price (e.g. 20.5 => "20,50 €")
|
||||
@ -68,17 +68,10 @@ export const ConfigurePacksButton: React.FC<ConfigurePacksButtonProps> = ({ pack
|
||||
}
|
||||
|
||||
/**
|
||||
* Open/closes the "confirm delete pack" modal
|
||||
* Callback triggered when the PrepaidPack was successfully created/deleted/updated.
|
||||
* We refresh the list of packs for the current tooltip to display the new data.
|
||||
*/
|
||||
const toggleRemovePackModal = (): void => {
|
||||
setDeletePackModal(!deletePackModal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback triggered when the PrepaidPack was successfully created.
|
||||
* We refresh the list of packs for the current button to get the new one.
|
||||
*/
|
||||
const handlePackCreated = (message: string) => {
|
||||
const handleSuccess = (message: string) => {
|
||||
onSuccess(message);
|
||||
PrepaidPackAPI.index({ group_id: groupId, priceable_id: priceableId, priceable_type: priceableType })
|
||||
.then(data => setPacks(data))
|
||||
@ -100,11 +93,11 @@ export const ConfigurePacksButton: React.FC<ConfigurePacksButtonProps> = ({ pack
|
||||
{showList && <FabPopover title={t('app.admin.configure_packs_button.packs')} headerButton={renderAddButton()}>
|
||||
<ul>
|
||||
{packs?.map(p =>
|
||||
<li key={p.id}>
|
||||
<li key={p.id} className={p.disabled ? 'disabled' : ''}>
|
||||
{formatDuration(p.minutes)} - {formatPrice(p.amount)}
|
||||
<span className="pack-actions">
|
||||
<FabButton className="edit-pack-button" onClick={toggleEditPackModal}><i className="fas fa-edit"/></FabButton>
|
||||
<FabButton className="remove-pack-button" onClick={toggleRemovePackModal}><i className="fas fa-trash"/></FabButton>
|
||||
<DeletePack onSuccess={handleSuccess} onError={onError} pack={p} />
|
||||
</span>
|
||||
</li>)}
|
||||
</ul>
|
||||
@ -112,7 +105,7 @@ export const ConfigurePacksButton: React.FC<ConfigurePacksButtonProps> = ({ pack
|
||||
</FabPopover>}
|
||||
<NewPackModal isOpen={addPackModal}
|
||||
toggleModal={toggleAddPackModal}
|
||||
onSuccess={handlePackCreated}
|
||||
onSuccess={handleSuccess}
|
||||
onError={onError}
|
||||
groupId={groupId}
|
||||
priceableId={priceableId}
|
||||
|
@ -0,0 +1,67 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FabButton } from '../base/fab-button';
|
||||
import { FabModal } from '../base/fab-modal';
|
||||
import { Loader } from '../base/loader';
|
||||
import { PrepaidPack } from '../../models/prepaid-pack';
|
||||
import PrepaidPackAPI from '../../api/prepaid-pack';
|
||||
|
||||
|
||||
interface DeletePackProps {
|
||||
onSuccess: (message: string) => void,
|
||||
onError: (message: string) => void,
|
||||
pack: PrepaidPack,
|
||||
}
|
||||
|
||||
/**
|
||||
* This component shows a button.
|
||||
* When clicked, we show a modal dialog to ask the user for confirmation about the deletion of the provided pack.
|
||||
*/
|
||||
const DeletePackComponent: React.FC<DeletePackProps> = ({ onSuccess, onError, pack }) => {
|
||||
const { t } = useTranslation('admin');
|
||||
|
||||
const [deletionModal, setDeletionModal] = useState<boolean>(false);
|
||||
|
||||
/**
|
||||
* Opens/closes the deletion modal
|
||||
*/
|
||||
const toggleDeletionModal = (): void => {
|
||||
setDeletionModal(!deletionModal);
|
||||
};
|
||||
|
||||
/**
|
||||
* The deletion has been confirmed by the user.
|
||||
* Call the API to trigger the deletion of the temporary set plan-category
|
||||
*/
|
||||
const onDeleteConfirmed = (): void => {
|
||||
PrepaidPackAPI.destroy(pack.id).then(() => {
|
||||
onSuccess(t('app.admin.delete_pack.pack_deleted'));
|
||||
}).catch((error) => {
|
||||
onError(t('app.admin.delete_pack.unable_to_delete') + error);
|
||||
});
|
||||
toggleDeletionModal();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="delete-pack">
|
||||
<FabButton type='button' className="remove-pack-button" icon={<i className="fa fa-trash" />} onClick={toggleDeletionModal} />
|
||||
<FabModal title={t('app.admin.delete_pack.delete_pack')}
|
||||
isOpen={deletionModal}
|
||||
toggleModal={toggleDeletionModal}
|
||||
closeButton={true}
|
||||
confirmButton={t('app.admin.delete_pack.confirm_delete')}
|
||||
onConfirm={onDeleteConfirmed}>
|
||||
<span>{t('app.admin.delete_pack.delete_confirmation')}</span>
|
||||
</FabModal>
|
||||
</div>
|
||||
)
|
||||
};
|
||||
|
||||
|
||||
export const DeletePack: React.FC<DeletePackProps> = ({ onSuccess, onError, pack }) => {
|
||||
return (
|
||||
<Loader>
|
||||
<DeletePackComponent onSuccess={onSuccess} onError={onError} pack={pack} />
|
||||
</Loader>
|
||||
);
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import React, { BaseSyntheticEvent } from 'react';
|
||||
import Select from 'react-select';
|
||||
import Switch from 'react-switch';
|
||||
import { PrepaidPack } from '../../models/prepaid-pack';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useImmer } from 'use-immer';
|
||||
@ -85,6 +86,15 @@ export const PackForm: React.FC<PackFormProps> = ({ formId, onSubmit, packData }
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback triggered when the user disables the pack.
|
||||
*/
|
||||
const handleUpdateDisabled = (checked: boolean) => {
|
||||
updatePack(draft => {
|
||||
draft.disabled = checked;
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<form id={formId} onSubmit={handleSubmit} className="pack-form">
|
||||
<label htmlFor="hours">{t('app.admin.pack_form.hours')} *</label>
|
||||
@ -119,6 +129,10 @@ export const PackForm: React.FC<PackFormProps> = ({ formId, onSubmit, packData }
|
||||
onChange={handleUpdateValidityInterval}
|
||||
options={buildOptions()} />
|
||||
</div>
|
||||
<label htmlFor="disabled">{t('app.admin.pack_form.disabled')}</label>
|
||||
<div>
|
||||
<Switch checked={pack?.disabled || false} onChange={handleUpdateDisabled} id="disabled" />
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
@ -15,4 +15,5 @@ export interface PrepaidPack {
|
||||
minutes: number,
|
||||
amount: number,
|
||||
usages?: number,
|
||||
disabled?: boolean,
|
||||
}
|
||||
|
@ -60,5 +60,6 @@
|
||||
@import "modules/pricing/editable-price";
|
||||
@import "modules/pricing/configure-packs-button";
|
||||
@import "modules/pricing/pack-form";
|
||||
@import "modules/pricing/delete-pack";
|
||||
|
||||
@import "app.responsive";
|
||||
|
@ -44,16 +44,16 @@
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.pack-actions > button {
|
||||
.pack-actions button {
|
||||
font-size: 10px;
|
||||
vertical-align: middle;
|
||||
line-height: 10px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
&.remove-pack-button {
|
||||
background-color: #cb1117;
|
||||
color: white;
|
||||
}
|
||||
&.disabled {
|
||||
background-color: #eeeeee;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,8 @@
|
||||
.delete-pack {
|
||||
display: inline;
|
||||
|
||||
.remove-pack-button {
|
||||
background-color: #cb1117;
|
||||
color: white;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
json.extract! pack, :id, :priceable_id, :priceable_type, :group_id, :validity_interval, :validity_count, :minutes
|
||||
json.extract! pack, :id, :priceable_id, :priceable_type, :group_id, :validity_interval, :validity_count, :minutes, :disabled
|
||||
json.amount pack.amount / 100.0
|
||||
json.usages pack.statistic_profile_prepaid_packs.count
|
||||
|
@ -1,6 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
json.array! @packs do |pack|
|
||||
json.extract! pack, :priceable_id, :priceable_type, :group_id, :minutes
|
||||
json.extract! pack, :id, :priceable_id, :priceable_type, :group_id, :minutes, :disabled
|
||||
json.amount pack.amount / 100.0
|
||||
end
|
||||
|
@ -381,6 +381,7 @@ en:
|
||||
pack_form:
|
||||
hours: "Hours"
|
||||
amount: "Price"
|
||||
disabled: "Disabled"
|
||||
validity_count: "Maximum validity"
|
||||
select_interval: "Interval..."
|
||||
intervals:
|
||||
@ -393,6 +394,12 @@ en:
|
||||
new_pack_info: "A prepaid pack allows users to buy {TYPE, select, Machine{machine} Space{space} other{}} hours before booking any slots. These packs can provide discounts on volumes purchases."
|
||||
create_pack: "Create this pack"
|
||||
pack_successfully_created: "The new prepaid pack was successfully created."
|
||||
delete_pack:
|
||||
pack_deleted: "The prepaid pack was successfully deleted."
|
||||
unable_to_delete: "Unable to delete the prepaid pack: "
|
||||
delete_pack: "Delete the prepaid pack"
|
||||
confirm_delete: "Delete"
|
||||
delete_confirmation: "Are you sure you want to delete this prepaid pack? This won't be possible if the pack was already bought by users."
|
||||
#ajouter un code promotionnel
|
||||
coupons_new:
|
||||
add_a_coupon: "Add a coupon"
|
||||
|
@ -10,6 +10,7 @@ class CreatePrepaidPacks < ActiveRecord::Migration[5.2]
|
||||
t.integer :minutes
|
||||
t.string :validity_interval
|
||||
t.integer :validity_count
|
||||
t.boolean :disabled
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
|
@ -1727,6 +1727,7 @@ CREATE TABLE public.prepaid_packs (
|
||||
minutes integer,
|
||||
validity_interval character varying,
|
||||
validity_count integer,
|
||||
disabled boolean,
|
||||
created_at timestamp without time zone NOT NULL,
|
||||
updated_at timestamp without time zone NOT NULL
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user