diff --git a/src/actions/ticket-actions.js b/src/actions/ticket-actions.js
index 3730f26ce..18ebfb589 100644
--- a/src/actions/ticket-actions.js
+++ b/src/actions/ticket-actions.js
@@ -47,6 +47,7 @@ import {
EXPORT_PAGE_SIZE_100,
TEN
} from "../utils/constants";
+import { snackbarErrorHandler, snackbarSuccessHandler } from "./base-actions";
export const REQUEST_TICKETS = "REQUEST_TICKETS";
export const RECEIVE_TICKETS = "RECEIVE_TICKETS";
@@ -1186,6 +1187,7 @@ export const deleteRefundPolicy =
export const getPaymentProfiles =
(
+ term = "",
page = DEFAULT_CURRENT_PAGE,
perPage = DEFAULT_PER_PAGE,
order = "id",
@@ -1195,6 +1197,7 @@ export const getPaymentProfiles =
const { currentSummitState } = getState();
const accessToken = await getAccessTokenSafely();
const { currentSummit } = currentSummitState;
+ const filter = [];
dispatch(startLoading());
@@ -1204,19 +1207,30 @@ export const getPaymentProfiles =
access_token: accessToken
};
+ if (term) {
+ const escapedTerm = escapeFilterValue(term);
+ filter.push(
+ `provider=@${escapedTerm},id=@${escapedTerm},application_type=@${escapedTerm}`
+ );
+ }
+
// order
if (order != null && orderDir != null) {
const orderDirSign = orderDir === DEFAULT_ORDER_DIR ? "+" : "-";
params.order = `${orderDirSign}${order}`;
}
+ if (filter.length > 0) {
+ params["filter[]"] = filter;
+ }
+
return getRequest(
createAction(REQUEST_PAYMENT_PROFILES),
createAction(RECEIVE_PAYMENT_PROFILES),
`${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/payment-profiles`,
- authErrorHandler,
- { page, perPage, order, orderDir }
+ snackbarErrorHandler,
+ { term, page, perPage, order, orderDir }
)(params)(dispatch).then(() => {
dispatch(stopLoading());
});
@@ -1232,41 +1246,34 @@ export const savePaymentProfile = (entity) => async (dispatch, getState) => {
};
if (entity.id) {
- putRequest(
+ return putRequest(
createAction(UPDATE_PAYMENT_PROFILE),
createAction(PAYMENT_PROFILE_UPDATED),
`${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/payment-profiles/${entity.id}`,
entity,
- authErrorHandler,
+ snackbarErrorHandler,
entity
)(params)(dispatch).then(() => {
dispatch(
- showSuccessMessage(
- T.translate("edit_payment_profile.payment_profile_saved")
- )
+ snackbarSuccessHandler({
+ title: T.translate("general.success"),
+ html: T.translate("edit_payment_profile.payment_profile_saved")
+ })
);
});
- return;
}
- const success_message = {
- title: T.translate("general.done"),
- html: T.translate("edit_payment_profile.payment_profile_created"),
- type: "success"
- };
-
- postRequest(
+ return postRequest(
createAction(UPDATE_PAYMENT_PROFILE),
createAction(PAYMENT_PROFILE_ADDED),
`${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/payment-profiles`,
entity,
- authErrorHandler
- )(params)(dispatch).then((payload) => {
+ snackbarErrorHandler
+ )(params)(dispatch).then(() => {
dispatch(
- showMessage(success_message, () => {
- history.push(
- `/app/summits/${currentSummit.id}/payment-profiles/${payload.response.id}`
- );
+ snackbarSuccessHandler({
+ title: T.translate("general.success"),
+ html: T.translate("edit_payment_profile.payment_profile_created")
})
);
});
@@ -1287,7 +1294,7 @@ export const deletePaymentProfile =
createAction(PAYMENT_PROFILE_DELETED)({ paymentProfileId }),
`${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/payment-profiles/${paymentProfileId}`,
null,
- authErrorHandler
+ snackbarErrorHandler
)(params)(dispatch).then(() => {
dispatch(stopLoading());
});
@@ -1309,7 +1316,7 @@ export const getPaymentProfile =
null,
createAction(RECEIVE_PAYMENT_PROFILE),
`${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/payment-profiles/${paymentProfileId}`,
- authErrorHandler
+ snackbarErrorHandler
)(params)(dispatch).then(() => {
dispatch(stopLoading());
});
@@ -1347,7 +1354,7 @@ export const getPaymentFeeTypes =
createAction(RECEIVE_PAYMENT_FEE_TYPES),
`${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/payment-profiles/${paymentProfileId}/fee-types`,
- authErrorHandler,
+ snackbarErrorHandler,
{ page, perPage, order, orderDir }
)(params)(dispatch).then(() => {
dispatch(stopLoading());
@@ -1366,45 +1373,44 @@ export const savePaymentFeeType = (entity) => async (dispatch, getState) => {
access_token: accessToken
};
+ dispatch(startLoading());
+
if (entity.id) {
- putRequest(
+ return putRequest(
createAction(UPDATE_PAYMENT_FEE_TYPE),
createAction(PAYMENT_FEE_TYPE_UPDATED),
`${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/payment-profiles/${paymentProfileId}/fee-types/${entity.id}`,
entity,
- authErrorHandler,
+ snackbarErrorHandler,
entity
- )(params)(dispatch).then(() => {
- dispatch(
- showSuccessMessage(
- T.translate("edit_payment_fee_type.payment_fee_type_saved")
- )
- );
- });
- return;
+ )(params)(dispatch)
+ .then(() => {
+ dispatch(
+ snackbarSuccessHandler({
+ title: T.translate("general.success"),
+ html: T.translate("edit_payment_fee_type.payment_fee_type_saved")
+ })
+ );
+ })
+ .finally(() => dispatch(stopLoading()));
}
- const success_message = {
- title: T.translate("general.done"),
- html: T.translate("edit_payment_fee_type.payment_fee_type_created"),
- type: "success"
- };
-
- postRequest(
+ return postRequest(
createAction(UPDATE_PAYMENT_FEE_TYPE),
createAction(PAYMENT_FEE_TYPE_ADDED),
`${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/payment-profiles/${paymentProfileId}/fee-types`,
entity,
- authErrorHandler
- )(params)(dispatch).then(() => {
- dispatch(
- showMessage(success_message, () => {
- history.push(
- `/app/summits/${currentSummit.id}/payment-profiles/${paymentProfileId}`
- );
- })
- );
- });
+ snackbarErrorHandler
+ )(params)(dispatch)
+ .then(() => {
+ dispatch(
+ snackbarSuccessHandler({
+ title: T.translate("general.success"),
+ html: T.translate("edit_payment_fee_type.payment_fee_type_created")
+ })
+ );
+ })
+ .finally(() => dispatch(stopLoading()));
};
export const deletePaymentFeeType =
@@ -1425,7 +1431,7 @@ export const deletePaymentFeeType =
createAction(PAYMENT_FEE_TYPE_DELETED)({ paymentFeeTypeId }),
`${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/payment-profiles/${paymentProfileId}/fee-types/${paymentFeeTypeId}`,
null,
- authErrorHandler
+ snackbarErrorHandler
)(params)(dispatch).then(() => {
dispatch(stopLoading());
});
@@ -1450,7 +1456,7 @@ export const getPaymentFeeType =
null,
createAction(RECEIVE_PAYMENT_FEE_TYPE),
`${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/payment-profiles/${paymentProfileId}/fee-types/${paymentFeeTypeId}`,
- authErrorHandler
+ snackbarErrorHandler
)(params)(dispatch).then(() => {
dispatch(stopLoading());
});
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 22c593037..047b457e6 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -1922,9 +1922,13 @@
"active": "Is Active?",
"payment_profiles_list": "Payment Profiles List",
"payment_profiles": "Payment Profiles",
+ "payment_profile": "Payment Profile",
"add_payment_profile": "Add Payment Profile",
"no_payment_profiles": "No Payment Profiles found for current search criteria.",
- "remove_warning": "Are you sure you want to delete this Payment Profile?"
+ "remove_warning": "Are you sure you want to delete profile #{name}",
+ "placeholders": {
+ "search_profiles": "Search payment profiles"
+ }
},
"edit_payment_profile": {
"payment_profile": "Payment Profile",
@@ -1944,7 +1948,9 @@
"send_email_receipt": "Send Stripe Email receipt?",
"merchant_account_id": "Merchant Account Id",
"payment_type_fee": "Payment Type Fee",
+ "payment_type_fees": "Payment Type Fees",
"new_fee_type": "Add New Fee Type",
+ "save_fee_type": "Save Fee Type",
"payment_type_fee_name": "Name",
"payment_type_fee_kind": "Kind",
"payment_type_fee_method": "Method",
diff --git a/src/layouts/payment-profile-layout.js b/src/layouts/payment-profile-layout.js
index 3950ab6d0..f5eeef8bf 100644
--- a/src/layouts/payment-profile-layout.js
+++ b/src/layouts/payment-profile-layout.js
@@ -17,10 +17,8 @@ import T from "i18n-react/dist/i18n-react";
import { Breadcrumb } from "react-breadcrumbs";
import Restrict from "../routes/restrict";
-import PaymentProfileListPage from "../pages/tickets/payment-profile-list-page";
-import EditPaymentProfilePage from "../pages/tickets/edit-payment-profile-page";
+import PaymentProfileListPage from "../pages/tickets/payment-profile/payment-profile-list-page";
import NoMatchPage from "../pages/no-match-page";
-import EditPaymentFeeTypePage from "../pages/tickets/edit-payment-fee-type-page";
const PaymentProfileLayout = ({ match }) => (
@@ -32,31 +30,6 @@ const PaymentProfileLayout = ({ match }) => (
/>
-
-
-
-
-
diff --git a/src/pages/tickets/edit-payment-fee-type-page.js b/src/pages/tickets/edit-payment-fee-type-page.js
deleted file mode 100644
index a8d156a79..000000000
--- a/src/pages/tickets/edit-payment-fee-type-page.js
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * Copyright 2018 OpenStack Foundation
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * */
-
-import React, { useEffect } from "react";
-import { connect } from "react-redux";
-import { Breadcrumb } from "react-breadcrumbs";
-import T from "i18n-react/dist/i18n-react";
-import PaymentFeeTypeForm from "../../components/forms/payment-fee-type-form";
-import {
- getPaymentFeeType,
- resetPaymentFeeTypeForm,
- savePaymentFeeType
-} from "../../actions/ticket-actions";
-import AddNewButton from "../../components/buttons/add-new-button";
-
-const EditPaymentFeeType = ({
- currentSummit,
- entity,
- errors,
- match,
- getPaymentFeeType,
- resetPaymentFeeTypeForm,
- savePaymentFeeType
-}) => {
- useEffect(() => {
- const { params } = match;
- if (params.payment_fee_type_id) {
- getPaymentFeeType(params.payment_fee_type_id);
- } else {
- resetPaymentFeeTypeForm();
- }
- }, [match.params.payment_fee_type_id]);
-
- const title = entity.id
- ? T.translate("general.edit")
- : T.translate("general.add");
- const breadcrumb = entity.id ? entity.name : T.translate("general.new");
-
- return (
-
-
-
- {title} {T.translate("edit_payment_fee_type.payment_fee_type")}
-
-
-
- {currentSummit && (
-
- )}
-
- );
-};
-
-const mapStateToProps = ({
- currentSummitState,
- currentPaymentFeeTypeState
-}) => ({
- currentSummit: currentSummitState.currentSummit,
- ...currentPaymentFeeTypeState
-});
-
-export default connect(mapStateToProps, {
- getPaymentFeeType,
- resetPaymentFeeTypeForm,
- savePaymentFeeType
-})(EditPaymentFeeType);
diff --git a/src/pages/tickets/edit-payment-profile-page.js b/src/pages/tickets/edit-payment-profile-page.js
deleted file mode 100644
index 9630768a6..000000000
--- a/src/pages/tickets/edit-payment-profile-page.js
+++ /dev/null
@@ -1,131 +0,0 @@
-/**
- * Copyright 2018 OpenStack Foundation
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * */
-
-import React from "react";
-import { connect } from "react-redux";
-import { Breadcrumb } from "react-breadcrumbs";
-import T from "i18n-react/dist/i18n-react";
-import Swal from "sweetalert2";
-import PaymentProfile from "../../components/forms/payment-profile-form";
-import { getSummitById } from "../../actions/summit-actions";
-import {
- getPaymentProfile,
- resetPaymentProfileForm,
- savePaymentProfile,
- getPaymentFeeTypes,
- deletePaymentFeeType
-} from "../../actions/ticket-actions";
-import AddNewButton from "../../components/buttons/add-new-button";
-
-class EditPaymentProfilePage extends React.Component {
- constructor(props) {
- const paymentProfileId = props.match.params.payment_profile_id;
- super(props);
-
- if (!paymentProfileId) {
- props.resetPaymentProfileForm();
- } else {
- props
- .getPaymentProfile(paymentProfileId)
- .then(props.getPaymentFeeTypes(paymentProfileId));
- }
-
- this.handleDeletePaymentFeeType =
- this.handleDeletePaymentFeeType.bind(this);
- }
-
- componentDidUpdate(prevProps) {
- const oldId = prevProps.match.params.payment_profile_id;
- const newId = this.props.match.params.payment_profile_id;
-
- if (newId !== oldId) {
- if (!newId) {
- this.props.resetPaymentProfileForm();
- } else {
- this.props.getPaymentProfile(newId);
- }
- }
- }
-
- handleDeletePaymentFeeType(feeTypeId) {
- const { paymentFeeTypes, deletePaymentFeeType } = this.props;
- const feeType = paymentFeeTypes.paymentFeeTypes.find(
- (r) => r.id === feeTypeId
- );
-
- Swal.fire({
- title: T.translate("general.are_you_sure"),
- text: `${T.translate("edit_location.remove_room_warning")} ${
- feeType.name
- }`,
- type: "warning",
- showCancelButton: true,
- confirmButtonColor: "#DD6B55",
- confirmButtonText: T.translate("general.yes_delete")
- }).then((result) => {
- if (result.value) {
- deletePaymentFeeType(feeTypeId);
- }
- });
- }
-
- render() {
- const { currentSummit, paymentFeeTypes, history, entity, errors, match } =
- this.props;
- const title = entity.id
- ? T.translate("general.edit")
- : T.translate("general.add");
- const breadcrumb = entity.id ? entity.name : T.translate("general.new");
-
- return (
-
-
-
- {title} {T.translate("edit_payment_profile.payment_profile")}
-
-
-
- {currentSummit && (
-
- )}
-
- );
- }
-}
-
-const mapStateToProps = ({
- currentSummitState,
- currentPaymentProfileState,
- currentPaymentFeeListTypeState
-}) => ({
- currentSummit: currentSummitState.currentSummit,
- paymentFeeTypes: currentPaymentFeeListTypeState,
- ...currentPaymentProfileState
-});
-
-export default connect(mapStateToProps, {
- getSummitById,
- getPaymentProfile,
- resetPaymentProfileForm,
- savePaymentProfile,
- getPaymentFeeTypes,
- deletePaymentFeeType
-})(EditPaymentProfilePage);
diff --git a/src/pages/tickets/payment-profile-list-page.js b/src/pages/tickets/payment-profile-list-page.js
deleted file mode 100644
index 465176ccb..000000000
--- a/src/pages/tickets/payment-profile-list-page.js
+++ /dev/null
@@ -1,164 +0,0 @@
-/**
- * Copyright 2020 OpenStack Foundation
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * */
-
-import React from "react";
-import { connect } from "react-redux";
-import T from "i18n-react/dist/i18n-react";
-import Table from "openstack-uicore-foundation/lib/components/table";
-import Swal from "sweetalert2";
-import {
- getPaymentProfiles,
- savePaymentProfile,
- deletePaymentProfile
-} from "../../actions/ticket-actions";
-import { MAX_PER_PAGE } from "../../utils/constants";
-
-class PaymentProfileListPage extends React.Component {
- constructor(props) {
- super(props);
- this.handleEdit = this.handleEdit.bind(this);
- this.handleDelete = this.handleDelete.bind(this);
- this.handleSort = this.handleSort.bind(this);
- this.handleNewPaymentProfile = this.handleNewPaymentProfile.bind(this);
- this.state = {};
- }
-
- componentDidMount() {
- const { currentSummit } = this.props;
- if (currentSummit) {
- this.props.getPaymentProfiles(1, MAX_PER_PAGE);
- }
- }
-
- handleEdit(paymentProfileId) {
- const { currentSummit, history } = this.props;
- history.push(
- `/app/summits/${currentSummit.id}/payment-profiles/${paymentProfileId}`
- );
- }
-
- handleDelete(paymentProfileId) {
- const { deletePaymentProfile } = this.props;
-
- Swal.fire({
- title: T.translate("general.are_you_sure"),
- text: T.translate("payment_profiles.remove_warning"),
- type: "warning",
- showCancelButton: true,
- confirmButtonColor: "#DD6B55",
- confirmButtonText: T.translate("general.yes_delete")
- }).then((result) => {
- if (result.value) {
- deletePaymentProfile(paymentProfileId);
- }
- });
- }
-
- handleSort(index, key, dir) {
- this.props.getPaymentProfiles(1, MAX_PER_PAGE, key, dir);
- }
-
- handleNewPaymentProfile() {
- const { currentSummit, history } = this.props;
- history.push(`/app/summits/${currentSummit.id}/payment-profiles/new`);
- }
-
- render() {
- const {
- currentSummit,
- paymentProfiles,
- order,
- orderDir,
- totalPaymentProfiles
- } = this.props;
-
- const columns = [
- {
- columnKey: "id",
- value: T.translate("payment_profiles.id"),
- sortable: true
- },
- {
- columnKey: "application_type",
- value: T.translate("payment_profiles.application_type")
- },
- {
- columnKey: "provider",
- value: T.translate("payment_profiles.provider")
- },
- {
- columnKey: "is_active",
- value: T.translate("payment_profiles.active"),
- render: (row) => (row.is_active ? "Yes" : "No")
- }
- ];
-
- const table_options = {
- sortCol: order,
- sortDir: orderDir,
- actions: {
- edit: { onClick: this.handleEdit },
- delete: { onClick: this.handleDelete }
- }
- };
-
- if (!currentSummit.id) return
;
-
- return (
-
-
- {" "}
- {T.translate("payment_profiles.payment_profiles_list")} (
- {totalPaymentProfiles})
-
-
-
-
- {T.translate("payment_profiles.add_payment_profile")}
-
-
-
-
- {paymentProfiles.length === 0 && (
-
{T.translate("payment_profiles.no_payment_profiles")}
- )}
-
- {paymentProfiles.length > 0 && (
-
- )}
-
- );
- }
-}
-
-const mapStateToProps = ({
- currentSummitState,
- currentPaymentProfileListState
-}) => ({
- currentSummit: currentSummitState.currentSummit,
- ...currentPaymentProfileListState
-});
-
-export default connect(mapStateToProps, {
- savePaymentProfile,
- deletePaymentProfile,
- getPaymentProfiles
-})(PaymentProfileListPage);
diff --git a/src/pages/tickets/payment-profile/components/payment-profile-dialog.js b/src/pages/tickets/payment-profile/components/payment-profile-dialog.js
new file mode 100644
index 000000000..c6c0caf3a
--- /dev/null
+++ b/src/pages/tickets/payment-profile/components/payment-profile-dialog.js
@@ -0,0 +1,590 @@
+import React, { useState } from "react";
+import PropTypes from "prop-types";
+import T from "i18n-react/dist/i18n-react";
+import {
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ Button,
+ Divider,
+ Grid2,
+ IconButton,
+ MenuItem,
+ Box,
+ InputLabel,
+ Tooltip
+} from "@mui/material";
+import CloseIcon from "@mui/icons-material/Close";
+import AddIcon from "@mui/icons-material/Add";
+import InfoIcon from "@mui/icons-material/Info";
+import { useFormik, FormikProvider } from "formik";
+import * as yup from "yup";
+import MuiTable from "openstack-uicore-foundation/lib/components/mui/table";
+import MuiFormikSelect from "openstack-uicore-foundation/lib/components/mui/formik-inputs/select";
+import MuiFormikTextField from "openstack-uicore-foundation/lib/components/mui/formik-inputs/textfield";
+import MuiFormikCheckbox from "openstack-uicore-foundation/lib/components/mui/formik-inputs/checkbox";
+import useScrollToError from "../../../../hooks/useScrollToError";
+
+const InfoTooltip = ({ title }) => (
+
+
+
+);
+
+const APPLICATION_TYPE_OPTIONS = [
+ { label: "Registration", value: "Registration" },
+ { label: "Bookable Rooms", value: "BookableRooms" },
+ { label: "Sponsor Services", value: "SponsorServices" }
+];
+
+const PROVIDER_OPTIONS = [
+ { label: "Stripe", value: "Stripe" },
+ { label: "LawPay", value: "LawPay" }
+];
+
+const PAYMENT_TYPE_FEE_KIND = [
+ { label: "Rate", value: "Rate" },
+ { label: "Amount", value: "Amount" }
+];
+
+const PAYMENT_TYPE_FEE_METHOD = [
+ // # Cards & wallets
+ { label: "Card", value: "card" },
+ { label: "Link", value: "link" },
+ { label: "CashApp", value: "cashapp" },
+ { label: "Paypal", value: "paypal" },
+ // # Bank debits
+ { label: "UsBankAccount", value: "us_bank_account" },
+ { label: "SepaDebit", value: "sepa_debit" },
+ { label: "BacsDebit", value: "bacs_debit" },
+ { label: "AuBecsDebit", value: "au_becs_debit" },
+ { label: "AcssDebit", value: "acss_debit" },
+ // # Bank redirects
+ { label: "Ideal", value: "ideal" },
+ { label: "Sofort", value: "sofort" },
+ { label: "Bancontact", value: "bancontact" },
+ { label: "Giropay", value: "giropay" },
+ { label: "Eps", value: "eps" },
+ { label: "P24", value: "p24" },
+ { label: "Blik", value: "blik" },
+ // # Buy Now, Pay Later
+ { label: "Klarna", value: "klarna" },
+ { label: "AfterpayClearpay", value: "afterpay_clearpay" },
+ { label: "Affirm", value: "affirm" },
+ // # Regional / other
+ { label: "Alipay", value: "alipay" },
+ { label: "WechatPay", value: "wechat_pay" },
+ { label: "Grabpay", value: "grabpay" },
+ { label: "Oxxo", value: "oxxo" },
+ { label: "Boleto", value: "boleto" },
+ { label: "Konbini", value: "konbini" }
+];
+
+const PaymentProfileDialog = ({
+ onSave,
+ onClose,
+ entity: initialEntity,
+ paymentFeeTypes,
+ onDeleteFeeType,
+ onSaveFeeType
+}) => {
+ const [showFeeTypeForm, setShowFeeTypeForm] = useState(false);
+
+ const formik = useFormik({
+ initialValues: {
+ id: initialEntity?.id || 0,
+ application_type: initialEntity?.application_type || "",
+ provider: initialEntity?.provider || "",
+ is_active: initialEntity?.is_active || false,
+ test_mode_enabled: initialEntity?.test_mode_enabled || false,
+ send_email_receipt: initialEntity?.send_email_receipt || false,
+ merchant_account_id: initialEntity?.merchant_account_id || "",
+ live_secret_key: initialEntity?.live_secret_key || "",
+ live_publishable_key: initialEntity?.live_publishable_key || "",
+ test_secret_key: initialEntity?.test_secret_key || "",
+ test_publishable_key: initialEntity?.test_publishable_key || ""
+ },
+ // validationSchema: yup.object().shape({
+ // application_type: yup.string().required(T.translate("validation.required")),
+ // provider: yup.string().required(T.translate("validation.required")),
+ // live_secret_key: yup.string().required(T.translate("validation.required")),
+ // live_publishable_key: yup.string().required(T.translate("validation.required"))
+ // }),
+ enableReinitialize: true,
+ onSubmit: (values) => onSave(values)
+ });
+
+ const feeTypeFormik = useFormik({
+ initialValues: {
+ id: 0,
+ name: "",
+ kind: "",
+ payment_method: "",
+ value: "",
+ max_cents: "",
+ min_cents: ""
+ },
+ validationSchema: yup.object().shape({
+ name: yup.string().required(T.translate("validation.required")),
+ kind: yup.string().required(T.translate("validation.required")),
+ payment_method: yup.string().required(T.translate("validation.required")),
+ value: yup.number().required(T.translate("validation.required")),
+ max_cents: yup.number().required(T.translate("validation.required")),
+ min_cents: yup.number().required(T.translate("validation.required"))
+ }),
+ onSubmit: (values) => onSaveFeeType(values).then(() => {
+ feeTypeFormik.resetForm();
+ setShowFeeTypeForm(false);
+ })
+ });
+
+ useScrollToError(formik, true);
+
+ const title = initialEntity.id
+ ? `${T.translate("general.edit")} ${T.translate(
+ "payment_profiles.payment_profile"
+ )}`
+ : `${T.translate("general.add")} ${T.translate(
+ "payment_profiles.payment_profile"
+ )}`;
+
+ const fee_types_options = {
+ sortCol: paymentFeeTypes.order,
+ sortDir: paymentFeeTypes.orderDir
+ };
+
+ const fee_types_columns = [
+ {
+ columnKey: "name",
+ header: T.translate("edit_payment_profile.payment_type_fee_name")
+ },
+ {
+ columnKey: "kind",
+ header: T.translate("edit_payment_profile.payment_type_fee_kind")
+ },
+ {
+ columnKey: "payment_method",
+ header: T.translate("edit_payment_profile.payment_type_fee_method")
+ },
+ {
+ columnKey: "value",
+ header: T.translate("edit_payment_profile.payment_type_fee_value")
+ },
+ {
+ columnKey: "max_cents",
+ header: T.translate("edit_payment_profile.payment_type_fee_max_cents")
+ },
+ {
+ columnKey: "min_cents",
+ header: T.translate("edit_payment_profile.payment_type_fee_min_cents")
+ }
+ ];
+
+ const handleClose = () => {
+ formik.resetForm();
+ onClose();
+ };
+
+ const handleFeeTypeDelete = (feeTypeId) => {
+ onDeleteFeeType(feeTypeId);
+ };
+
+ const handleFeeTypeEdit = (feeType) => {
+ feeTypeFormik.setValues({ ...feeType });
+ setShowFeeTypeForm(true);
+ };
+
+ const handleNewFeeType = () => {
+ feeTypeFormik.resetForm();
+ setShowFeeTypeForm(true);
+ };
+
+ const handleCancelFeeType = () => {
+ feeTypeFormik.resetForm();
+ setShowFeeTypeForm(false);
+ };
+
+ return (
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+
+ {T.translate("edit_payment_profile.application_type")}
+
+
+ {APPLICATION_TYPE_OPTIONS.map((opt) => (
+
+ {opt.label}
+
+ ))}
+
+
+
+
+ {T.translate("edit_payment_profile.provider")}
+
+
+ {PROVIDER_OPTIONS.map((opt) => (
+
+ {opt.label}
+
+ ))}
+
+
+
+
+
+
+
+
+ {T.translate("edit_payment_profile.test_mode_enabled")}
+
+ >
+ }
+ />
+
+ {formik.values.provider === "Stripe" && (
+
+
+ {T.translate("edit_payment_profile.send_email_receipt")}
+
+ >
+ }
+ />
+
+ )}
+
+ {formik.values.provider === "LawPay" && (
+
+
+ {T.translate("edit_payment_profile.merchant_account_id")}
+
+
+
+ )}
+
+
+
+ {T.translate("edit_payment_profile.live_secret_key")}
+
+
+
+
+
+
+ {T.translate("edit_payment_profile.live_publishable_key")}
+
+
+
+
+
+
+ {T.translate("edit_payment_profile.test_secret_key")}
+
+
+
+
+
+
+ {T.translate("edit_payment_profile.test_publishable_key")}
+
+
+
+
+
+ {formik.values.id !== 0 &&
+ formik.values.provider === "Stripe" &&
+ formik.values.application_type === "SponsorServices" && (
+ <>
+
+
+
+ {T.translate("edit_payment_profile.payment_type_fee")}
+
+
+
+ {paymentFeeTypes.totalPaymentFeeTypes}{" "}
+ {T.translate("edit_payment_profile.payment_type_fees")}
+
+
+ {!showFeeTypeForm && (
+ }
+ sx={{
+ height: "36px",
+ fontSize: "1.4rem",
+ lineHeight: "2.4rem",
+ letterSpacing: "0.4px"
+ }}
+ >
+ {T.translate("edit_payment_profile.new_fee_type")}
+
+ )}
+
+
+
+ {showFeeTypeForm && (
+
+
+
+ {T.translate(
+ "edit_payment_profile.payment_type_fee_name"
+ )}
+
+
+
+
+
+ {T.translate(
+ "edit_payment_profile.payment_type_fee_kind"
+ )}
+
+
+ {PAYMENT_TYPE_FEE_KIND.map((opt) => (
+
+ {opt.label}
+
+ ))}
+
+
+
+
+ {T.translate(
+ "edit_payment_profile.payment_type_fee_method"
+ )}
+
+ {
+ if (!selected)
+ return (
+
+ {T.translate(
+ "edit_payment_profile.payment_type_fee_method"
+ )}
+
+ );
+ const opt = PAYMENT_TYPE_FEE_METHOD.find(
+ (o) => o.value === selected
+ );
+ return opt ? opt.label : selected;
+ }}
+ >
+ {PAYMENT_TYPE_FEE_METHOD.map((opt) => (
+
+ {opt.label}
+
+ ))}
+
+
+
+
+ {T.translate(
+ "edit_payment_profile.payment_type_fee_value"
+ )}
+
+
+
+
+
+ {T.translate(
+ "edit_payment_profile.payment_type_fee_max_cents"
+ )}
+
+
+
+
+
+ {T.translate(
+ "edit_payment_profile.payment_type_fee_min_cents"
+ )}
+
+
+
+
+
+ {T.translate("general.cancel")}
+
+
+ {T.translate("edit_payment_profile.save_fee_type")}
+
+
+
+ )}
+
+
+
+ >
+ )}
+
+
+
+
+ {T.translate("general.save")}
+
+
+
+
+ );
+};
+
+PaymentProfileDialog.propTypes = {
+ onClose: PropTypes.func.isRequired,
+ onSave: PropTypes.func.isRequired,
+ entity: PropTypes.object,
+ paymentFeeTypes: PropTypes.array,
+ onSaveFeeType: PropTypes.func.isRequired,
+ onDeleteFeeType: PropTypes.func.isRequired
+};
+
+PaymentProfileDialog.defaultProps = {
+ entity: {}
+};
+
+export default PaymentProfileDialog;
diff --git a/src/pages/tickets/payment-profile/payment-profile-list-page.js b/src/pages/tickets/payment-profile/payment-profile-list-page.js
new file mode 100644
index 000000000..b3d691d4a
--- /dev/null
+++ b/src/pages/tickets/payment-profile/payment-profile-list-page.js
@@ -0,0 +1,256 @@
+/**
+ * Copyright 2020 OpenStack Foundation
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * */
+
+import React, { useEffect, useState } from "react";
+import { connect } from "react-redux";
+import T from "i18n-react/dist/i18n-react";
+import { Box, Button, Grid2 } from "@mui/material";
+import AddIcon from "@mui/icons-material/Add";
+import MuiTable from "openstack-uicore-foundation/lib/components/mui/table";
+import SearchInput from "openstack-uicore-foundation/lib/components/mui/search-input";
+import {
+ getPaymentProfiles,
+ getPaymentProfile,
+ savePaymentProfile,
+ deletePaymentProfile,
+ getPaymentFeeTypes,
+ deletePaymentFeeType,
+ savePaymentFeeType,
+ resetPaymentProfileForm
+} from "../../../actions/ticket-actions";
+import { DEFAULT_CURRENT_PAGE } from "../../../utils/constants";
+import PaymentProfileDialog from "./components/payment-profile-dialog";
+
+const PaymentProfileListPage = ({
+ currentSummit,
+ paymentProfiles,
+ term,
+ currentPage,
+ perPage,
+ order,
+ orderDir,
+ totalPaymentProfiles,
+ getPaymentProfiles,
+ getPaymentProfile,
+ savePaymentProfile,
+ deletePaymentProfile,
+ resetPaymentProfileForm,
+ currentPaymentProfile,
+ paymentFeeTypes,
+ getPaymentFeeTypes,
+ savePaymentFeeType,
+ deletePaymentFeeType
+}) => {
+ useEffect(() => {
+ if (currentSummit?.id)
+ getPaymentProfiles("", DEFAULT_CURRENT_PAGE, perPage);
+ }, [currentSummit?.id]);
+
+ const [paymentProfilePopup, setPaymentProfilePopup] = useState(false);
+
+ const handleEdit = (paymentProfile) => {
+ getPaymentProfile(paymentProfile.id).then(() => {
+ getPaymentFeeTypes(paymentProfile.id);
+ setPaymentProfilePopup(true);
+ });
+ };
+
+ const handleSave = (entity) => {
+ savePaymentProfile(entity).then(() => {
+ getPaymentProfiles("", DEFAULT_CURRENT_PAGE, perPage);
+ setPaymentProfilePopup(false);
+ });
+ };
+
+ const handleDelete = (paymentProfileId) =>
+ deletePaymentProfile(paymentProfileId).then(() =>
+ getPaymentProfiles("", DEFAULT_CURRENT_PAGE, perPage)
+ );
+
+ const handleSearch = (searchTerm) => {
+ getPaymentProfiles(searchTerm, DEFAULT_CURRENT_PAGE, perPage);
+ };
+
+ const handlePageChange = (page) => {
+ getPaymentProfiles(term, page, perPage, order, orderDir);
+ };
+ const handlePerPageChange = (newPerPage) => {
+ getPaymentProfiles(term, DEFAULT_CURRENT_PAGE, newPerPage, order, orderDir);
+ };
+
+ const handleSort = (key, dir) => {
+ getPaymentProfiles(term, DEFAULT_CURRENT_PAGE, perPage, key, dir);
+ };
+
+ const handleClose = () => {
+ resetPaymentProfileForm();
+ setPaymentProfilePopup(false);
+ };
+
+ const handleSaveFeeType = (entity) =>
+ savePaymentFeeType(entity).then(() => {
+ getPaymentFeeTypes(currentPaymentProfile.id);
+ setPaymentProfilePopup(false);
+ });
+
+ const handleDeleteFeeType = (feeTypeId) =>
+ deletePaymentFeeType(feeTypeId).then(() => {
+ getPaymentFeeTypes(currentPaymentProfile.id);
+ });
+
+ const handleNewPaymentProfile = () => {
+ resetPaymentProfileForm();
+ setPaymentProfilePopup(true);
+ };
+
+ const columns = [
+ {
+ columnKey: "id",
+ header: T.translate("payment_profiles.id"),
+ sortable: true
+ },
+ {
+ columnKey: "application_type",
+ header: T.translate("payment_profiles.application_type")
+ },
+ {
+ columnKey: "provider",
+ header: T.translate("payment_profiles.provider")
+ },
+ {
+ columnKey: "is_active",
+ header: T.translate("payment_profiles.active"),
+ render: (row) => (row.is_active ? "Yes" : "No")
+ }
+ ];
+
+ const table_options = {
+ sortCol: order,
+ sortDir: orderDir
+ };
+
+ if (!currentSummit.id) return
;
+
+ return (
+
+
{T.translate("payment_profiles.payment_profiles_list")}
+
+
+
+ {totalPaymentProfiles}{" "}
+ {T.translate("payment_profiles.payment_profiles")}
+
+
+
+
+
+
+ }
+ sx={{
+ height: "36px",
+ padding: "6px 16px",
+ fontSize: "1.4rem",
+ lineHeight: "2.4rem",
+ letterSpacing: "0.4px"
+ }}
+ >
+ {T.translate("payment_profiles.add_payment_profile")}
+
+
+
+
+ {paymentProfiles.length === 0 && (
+
{T.translate("payment_profiles.no_payment_profiles")}
+ )}
+
+ {paymentProfiles.length > 0 && (
+
row.id}
+ deleteDialogBody={(id) =>
+ T.translate("payment_profiles.remove_warning", { name: id })
+ }
+ />
+ )}
+
+ {paymentProfilePopup && (
+
+ )}
+
+ );
+};
+
+const mapStateToProps = ({
+ currentSummitState,
+ currentPaymentProfileListState,
+ currentPaymentProfileState,
+ currentPaymentFeeListTypeState
+}) => ({
+ currentSummit: currentSummitState.currentSummit,
+ paymentFeeTypes: currentPaymentFeeListTypeState,
+ currentPaymentProfile: currentPaymentProfileState.entity,
+ ...currentPaymentProfileListState
+});
+
+export default connect(mapStateToProps, {
+ getPaymentProfiles,
+ getPaymentProfile,
+ savePaymentProfile,
+ deletePaymentProfile,
+ resetPaymentProfileForm,
+ getPaymentFeeTypes,
+ savePaymentFeeType,
+ deletePaymentFeeType
+})(PaymentProfileListPage);
diff --git a/src/reducers/payment_profiles/payment-profile-list-reducer.js b/src/reducers/payment_profiles/payment-profile-list-reducer.js
index d1837784f..4d87563e6 100644
--- a/src/reducers/payment_profiles/payment-profile-list-reducer.js
+++ b/src/reducers/payment_profiles/payment-profile-list-reducer.js
@@ -24,8 +24,12 @@ import { SET_CURRENT_SUMMIT } from "../../actions/summit-actions";
const DEFAULT_STATE = {
paymentProfiles: [],
+ term: "",
order: "id",
orderDir: 1,
+ currentPage: 1,
+ lastPage: 1,
+ perPage: 10,
totalPaymentProfiles: 0
};
@@ -41,13 +45,19 @@ const paymentProfileListReducer = (state = DEFAULT_STATE, action) => {
return { ...state, order, orderDir };
}
case RECEIVE_PAYMENT_PROFILES: {
- const { total } = payload.response;
+ const {
+ current_page: currentPage,
+ total,
+ last_page: lastPage
+ } = payload.response;
const paymentProfiles = payload.response.data;
return {
...state,
paymentProfiles,
- totalPaymentProfiles: total
+ totalPaymentProfiles: total,
+ currentPage,
+ lastPage
};
}
case PAYMENT_PROFILE_ADDED: {