diff --git a/app/controllers/api/prepaid_packs_controller.rb b/app/controllers/api/prepaid_packs_controller.rb index b16771884..313f12c51 100644 --- a/app/controllers/api/prepaid_packs_controller.rb +++ b/app/controllers/api/prepaid_packs_controller.rb @@ -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 diff --git a/app/frontend/src/javascript/components/pricing/configure-packs-button.tsx b/app/frontend/src/javascript/components/pricing/configure-packs-button.tsx index cf938939a..a69c6f94e 100644 --- a/app/frontend/src/javascript/components/pricing/configure-packs-button.tsx +++ b/app/frontend/src/javascript/components/pricing/configure-packs-button.tsx @@ -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 = ({ pack const [showList, setShowList] = useState(false); const [addPackModal, setAddPackModal] = useState(false); const [editPackModal, setEditPackModal] = useState(false); - const [deletePackModal, setDeletePackModal] = useState(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 = ({ 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 = ({ pack {showList &&
    {packs?.map(p => -
  • +
  • {formatDuration(p.minutes)} - {formatPrice(p.amount)} - +
  • )}
@@ -112,7 +105,7 @@ export const ConfigurePacksButton: React.FC = ({ pack
} 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 = ({ onSuccess, onError, pack }) => { + const { t } = useTranslation('admin'); + + const [deletionModal, setDeletionModal] = useState(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 ( +
+ } onClick={toggleDeletionModal} /> + + {t('app.admin.delete_pack.delete_confirmation')} + +
+ ) +}; + + +export const DeletePack: React.FC = ({ onSuccess, onError, pack }) => { + return ( + + + + ); +} diff --git a/app/frontend/src/javascript/components/pricing/pack-form.tsx b/app/frontend/src/javascript/components/pricing/pack-form.tsx index 6ee5c0830..cdc2fe95c 100644 --- a/app/frontend/src/javascript/components/pricing/pack-form.tsx +++ b/app/frontend/src/javascript/components/pricing/pack-form.tsx @@ -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 = ({ formId, onSubmit, packData } }); } + /** + * Callback triggered when the user disables the pack. + */ + const handleUpdateDisabled = (checked: boolean) => { + updatePack(draft => { + draft.disabled = checked; + }) + } + return (
@@ -119,6 +129,10 @@ export const PackForm: React.FC = ({ formId, onSubmit, packData } onChange={handleUpdateValidityInterval} options={buildOptions()} /> + +
+ +
); } diff --git a/app/frontend/src/javascript/models/prepaid-pack.ts b/app/frontend/src/javascript/models/prepaid-pack.ts index d4b3bfed0..e0b944398 100644 --- a/app/frontend/src/javascript/models/prepaid-pack.ts +++ b/app/frontend/src/javascript/models/prepaid-pack.ts @@ -15,4 +15,5 @@ export interface PrepaidPack { minutes: number, amount: number, usages?: number, + disabled?: boolean, } diff --git a/app/frontend/src/stylesheets/application.scss b/app/frontend/src/stylesheets/application.scss index 5ea58837a..c69dd1745 100644 --- a/app/frontend/src/stylesheets/application.scss +++ b/app/frontend/src/stylesheets/application.scss @@ -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"; diff --git a/app/frontend/src/stylesheets/modules/pricing/configure-packs-button.scss b/app/frontend/src/stylesheets/modules/pricing/configure-packs-button.scss index a035709e2..ab2cf5bec 100644 --- a/app/frontend/src/stylesheets/modules/pricing/configure-packs-button.scss +++ b/app/frontend/src/stylesheets/modules/pricing/configure-packs-button.scss @@ -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; } } } diff --git a/app/frontend/src/stylesheets/modules/pricing/delete-pack.scss b/app/frontend/src/stylesheets/modules/pricing/delete-pack.scss new file mode 100644 index 000000000..37d87274c --- /dev/null +++ b/app/frontend/src/stylesheets/modules/pricing/delete-pack.scss @@ -0,0 +1,8 @@ +.delete-pack { + display: inline; + + .remove-pack-button { + background-color: #cb1117; + color: white; + } +} diff --git a/app/views/api/prepaid_packs/_pack.json.jbuilder b/app/views/api/prepaid_packs/_pack.json.jbuilder index 424fca946..c8f48cb14 100644 --- a/app/views/api/prepaid_packs/_pack.json.jbuilder +++ b/app/views/api/prepaid_packs/_pack.json.jbuilder @@ -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 diff --git a/app/views/api/prepaid_packs/index.json.jbuilder b/app/views/api/prepaid_packs/index.json.jbuilder index e9d64cb27..26d38f919 100644 --- a/app/views/api/prepaid_packs/index.json.jbuilder +++ b/app/views/api/prepaid_packs/index.json.jbuilder @@ -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 diff --git a/config/locales/app.admin.en.yml b/config/locales/app.admin.en.yml index 048476c5c..9d89d7dea 100644 --- a/config/locales/app.admin.en.yml +++ b/config/locales/app.admin.en.yml @@ -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" diff --git a/db/migrate/20210621122103_create_prepaid_packs.rb b/db/migrate/20210621122103_create_prepaid_packs.rb index 9bb8d1270..91bdff8bc 100644 --- a/db/migrate/20210621122103_create_prepaid_packs.rb +++ b/db/migrate/20210621122103_create_prepaid_packs.rb @@ -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 diff --git a/db/structure.sql b/db/structure.sql index 9b41fde36..7427b5394 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -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 );