diff --git a/src/actions/sponsor-forms-actions.js b/src/actions/sponsor-forms-actions.js
index e54fc2134..934e81458 100644
--- a/src/actions/sponsor-forms-actions.js
+++ b/src/actions/sponsor-forms-actions.js
@@ -65,6 +65,31 @@ export const SPONSOR_CUSTOMIZED_FORM_DELETED =
export const SPONSOR_CUSTOMIZED_FORM_ARCHIVED_CHANGED =
"SPONSOR_CUSTOMIZED_FORM_ARCHIVED_CHANGED";
+export const RECEIVE_SPONSOR_CUSTOMIZED_FORM_ITEMS =
+ "RECEIVE_SPONSOR_CUSTOMIZED_FORM_ITEMS";
+export const REQUEST_SPONSOR_CUSTOMIZED_FORM_ITEMS =
+ "REQUEST_SPONSOR_CUSTOMIZED_FORM_ITEMS";
+export const RECEIVE_SPONSOR_CUSTOMIZED_FORM_ITEM =
+ "RECEIVE_SPONSOR_CUSTOMIZED_FORM_ITEM";
+export const SPONSOR_CUSTOMIZED_FORM_ITEM_DELETED =
+ "SPONSOR_CUSTOMIZED_FORM_ITEM_DELETED";
+export const SPONSOR_CUSTOMIZED_FORM_ITEM_ARCHIVED =
+ "SPONSOR_CUSTOMIZED_FORM_ITEM_ARCHIVED";
+export const SPONSOR_CUSTOMIZED_FORM_ITEM_UNARCHIVED =
+ "SPONSOR_CUSTOMIZED_FORM_ITEM_UNARCHIVED";
+export const UPDATE_SPONSOR_FORM_MANAGED_ITEM =
+ "UPDATE_SPONSOR_FORM_MANAGED_ITEM";
+export const SPONSOR_FORM_MANAGED_ITEM_UPDATED =
+ "SPONSOR_FORM_MANAGED_ITEM_UPDATED";
+export const SPONSOR_FORM_MANAGED_ITEM_ADDED =
+ "SPONSOR_FORM_MANAGED_ITEM_ADDED";
+export const SPONSOR_FORM_MANAGED_ITEM_DELETED =
+ "SPONSOR_FORM_MANAGED_ITEM_DELETED";
+export const SPONSOR_CUSTOMIZED_FORM_ITEMS_ADDED =
+ "SPONSOR_CUSTOMIZED_FORM_ITEMS_ADDED";
+export const RESET_SPONSOR_FORM_MANAGED_ITEM =
+ "RESET_SPONSOR_FORM_MANAGED_ITEM";
+
// ITEMS
export const REQUEST_SPONSOR_FORM_ITEMS = "REQUEST_SPONSOR_FORM_ITEMS";
export const RECEIVE_SPONSOR_FORM_ITEMS = "RECEIVE_SPONSOR_FORM_ITEMS";
@@ -633,6 +658,61 @@ export const getSponsorCustomizedForm =
});
};
+export const getSponsorCustomizedFormItems =
+ (
+ formId,
+ term = "",
+ page = DEFAULT_CURRENT_PAGE,
+ perPage = DEFAULT_PER_PAGE,
+ order = "id",
+ orderDir = DEFAULT_ORDER_DIR,
+ hideArchived = false
+ ) =>
+ async (dispatch, getState) => {
+ const { currentSummitState, currentSponsorState } = getState();
+ const { currentSummit } = currentSummitState;
+ const {
+ entity: { id: sponsorId }
+ } = currentSponsorState;
+ const accessToken = await getAccessTokenSafely();
+ const filter = [];
+
+ dispatch(startLoading());
+
+ if (term) {
+ const escapedTerm = escapeFilterValue(term);
+ filter.push(`name=@${escapedTerm},code=@${escapedTerm}`);
+ }
+
+ const params = {
+ page,
+ per_page: perPage,
+ access_token: accessToken
+ };
+
+ if (hideArchived) filter.push("is_archived==0");
+
+ if (filter.length > 0) {
+ params["filter[]"] = filter;
+ }
+
+ // order
+ if (order != null && orderDir != null) {
+ const orderDirSign = orderDir === 1 ? "" : "-";
+ params.order = `${orderDirSign}${order}`;
+ }
+
+ return getRequest(
+ createAction(REQUEST_SPONSOR_CUSTOMIZED_FORM_ITEMS),
+ createAction(RECEIVE_SPONSOR_CUSTOMIZED_FORM_ITEMS),
+ `${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/sponsor-forms/${formId}/items`,
+ authErrorHandler,
+ { term, order, orderDir, page, perPage, hideArchived }
+ )(params)(dispatch).then(() => {
+ dispatch(stopLoading());
+ });
+ };
+
export const saveSponsorCustomizedForm =
(entity) => async (dispatch, getState) => {
const { currentSummitState, currentSponsorState } = getState();
@@ -1134,9 +1214,6 @@ const normalizeItem = (entity) => {
const normalizedEntity = { ...entity };
const {
meta_fields,
- early_bird_rate,
- standard_rate,
- onsite_rate,
quantity_limit_per_show,
quantity_limit_per_sponsor,
default_quantity,
@@ -1151,15 +1228,7 @@ const normalizeItem = (entity) => {
normalizedEntity.images = images?.filter((img) => img.file_path);
}
- if (early_bird_rate === "" || typeof early_bird_rate === "undefined")
- delete normalizedEntity.early_bird_rate;
- else normalizedEntity.early_bird_rate = amountToCents(early_bird_rate);
- if (standard_rate === "" || typeof standard_rate === "undefined")
- delete normalizedEntity.standard_rate;
- else normalizedEntity.standard_rate = amountToCents(standard_rate);
- if (onsite_rate === "" || typeof onsite_rate === "undefined")
- delete normalizedEntity.onsite_rate;
- else normalizedEntity.onsite_rate = amountToCents(onsite_rate);
+ normalizeRates(entity, normalizedEntity);
if (quantity_limit_per_show === "")
delete normalizedEntity.quantity_limit_per_show;
@@ -1205,3 +1274,246 @@ export const addInventoryItems =
dispatch(stopLoading());
});
};
+
+export const saveSponsorFormManagedItem =
+ (formId, entity) => async (dispatch, getState) => {
+ const { currentSummitState, currentSponsorState } = getState();
+ const accessToken = await getAccessTokenSafely();
+ const { currentSummit } = currentSummitState;
+ const {
+ entity: { id: sponsorId }
+ } = currentSponsorState;
+
+ dispatch(startLoading());
+
+ const params = {
+ access_token: accessToken
+ };
+
+ const normalizedEntity = normalizeManagedItem(entity);
+
+ if (entity.id) {
+ return putRequest(
+ createAction(UPDATE_SPONSOR_FORM_MANAGED_ITEM),
+ createAction(SPONSOR_FORM_MANAGED_ITEM_UPDATED),
+ `${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/sponsor-forms/${formId}/items/${entity.id}`,
+ normalizedEntity,
+ snackbarErrorHandler,
+ entity
+ )(params)(dispatch)
+ .then(() => {
+ dispatch(
+ snackbarSuccessHandler({
+ title: T.translate("general.success"),
+ html: T.translate(
+ "edit_sponsor.forms_tab.form_manage_items.item_updated"
+ )
+ })
+ );
+ })
+ .finally(() => {
+ dispatch(stopLoading());
+ });
+ }
+
+ const successMessage = {
+ title: T.translate("general.done"),
+ html: T.translate(
+ "edit_sponsor.forms_tab.form_manage_items.item_created"
+ ),
+ type: "success"
+ };
+
+ return postRequest(
+ createAction(UPDATE_SPONSOR_FORM_MANAGED_ITEM),
+ createAction(SPONSOR_FORM_MANAGED_ITEM_ADDED),
+ `${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/sponsor-forms/${formId}/items`,
+ normalizedEntity,
+ snackbarErrorHandler,
+ entity
+ )(params)(dispatch)
+ .then(() => {
+ dispatch(snackbarSuccessHandler(successMessage));
+ })
+ .finally(() => {
+ dispatch(stopLoading());
+ });
+ };
+
+export const resetSponsorFormManagedItem = () => (dispatch) => {
+ dispatch(createAction(RESET_SPONSOR_FORM_MANAGED_ITEM)({}));
+};
+
+const normalizeManagedItem = (entity) => {
+ const normalizedEntity = { ...entity };
+ normalizedEntity.meta_fields = normalizedEntity.meta_fields?.filter(
+ (mf) => mf.name
+ );
+ normalizedEntity.images = normalizedEntity.images?.filter(
+ (img) => img.file_path
+ );
+
+ normalizeRates(entity, normalizedEntity);
+
+ return normalizedEntity;
+};
+
+const normalizeRates = (entity, normalizedEntity) => {
+ const { early_bird_rate, standard_rate, onsite_rate } = entity;
+
+ if (early_bird_rate === "" || early_bird_rate === undefined)
+ delete normalizedEntity.early_bird_rate;
+ else normalizedEntity.early_bird_rate = amountToCents(early_bird_rate);
+
+ if (standard_rate === "" || standard_rate === undefined)
+ delete normalizedEntity.standard_rate;
+ else normalizedEntity.standard_rate = amountToCents(standard_rate);
+
+ if (onsite_rate === "" || onsite_rate === undefined)
+ delete normalizedEntity.onsite_rate;
+ else normalizedEntity.onsite_rate = amountToCents(onsite_rate);
+};
+
+export const deleteSponsorFormManagedItem =
+ (formId, itemId) => async (dispatch, getState) => {
+ const { currentSummitState, currentSponsorState } = getState();
+ const accessToken = await getAccessTokenSafely();
+ const { currentSummit } = currentSummitState;
+ const {
+ entity: { id: sponsorId }
+ } = currentSponsorState;
+
+ dispatch(startLoading());
+
+ const params = {
+ access_token: accessToken
+ };
+
+ return deleteRequest(
+ null,
+ createAction(SPONSOR_FORM_MANAGED_ITEM_DELETED)({ itemId }),
+ `${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/sponsor-forms/${formId}/items/${itemId}`,
+ null,
+ snackbarErrorHandler
+ )(params)(dispatch)
+ .then(() => {
+ dispatch(
+ snackbarSuccessHandler({
+ title: T.translate("general.success"),
+ html: T.translate("sponsor_forms.form_delete_success")
+ })
+ );
+ })
+ .finally(() => {
+ dispatch(stopLoading());
+ });
+ };
+
+export const getSponsorFormManagedItem =
+ (formId, itemId) => async (dispatch, getState) => {
+ const { currentSummitState, currentSponsorState } = getState();
+ const accessToken = await getAccessTokenSafely();
+ const { currentSummit } = currentSummitState;
+ const {
+ entity: { id: sponsorId }
+ } = currentSponsorState;
+
+ dispatch(startLoading());
+
+ const params = {
+ access_token: accessToken
+ };
+
+ return getRequest(
+ null,
+ createAction(RECEIVE_SPONSOR_CUSTOMIZED_FORM_ITEM),
+ `${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/sponsor-forms/${formId}/items/${itemId}`,
+ authErrorHandler
+ )(params)(dispatch).then(() => {
+ dispatch(stopLoading());
+ });
+ };
+
+export const addSponsorManagedFormItems =
+ (formId, itemIds) => async (dispatch, getState) => {
+ const { currentSummitState, currentSponsorState } = getState();
+ const accessToken = await getAccessTokenSafely();
+ const { currentSummit } = currentSummitState;
+ const {
+ entity: { id: sponsorId }
+ } = currentSponsorState;
+
+ dispatch(startLoading());
+
+ const params = {
+ access_token: accessToken
+ };
+
+ return postRequest(
+ null,
+ createAction(SPONSOR_CUSTOMIZED_FORM_ITEMS_ADDED),
+ `${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/sponsor-forms/${formId}/items/clone`,
+ { inventory_item_ids: itemIds },
+ snackbarErrorHandler
+ )(params)(dispatch)
+ .then(() => {
+ dispatch(getSponsorCustomizedFormItems(formId));
+ dispatch(
+ snackbarSuccessHandler({
+ title: T.translate("general.success"),
+ html: T.translate(
+ "sponsor_form_item_list.add_from_inventory.items_added"
+ )
+ })
+ );
+ })
+ .finally(() => {
+ dispatch(stopLoading());
+ });
+ };
+
+export const archiveSponsorCustomizedFormItem =
+ (formId, itemId) => async (dispatch, getState) => {
+ const { currentSummitState, currentSponsorState } = getState();
+ const accessToken = await getAccessTokenSafely();
+ const { currentSummit } = currentSummitState;
+ const {
+ entity: { id: sponsorId }
+ } = currentSponsorState;
+ const params = { access_token: accessToken };
+
+ dispatch(startLoading());
+
+ return putRequest(
+ null,
+ createAction(SPONSOR_CUSTOMIZED_FORM_ITEM_ARCHIVED),
+ `${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/sponsor-forms/${formId}/items/${itemId}/archive`,
+ null,
+ snackbarErrorHandler
+ )(params)(dispatch).then(() => {
+ dispatch(stopLoading());
+ });
+ };
+
+export const unarchiveSponsorCustomizedFormItem =
+ (formId, itemId) => async (dispatch, getState) => {
+ const { currentSummitState, currentSponsorState } = getState();
+ const accessToken = await getAccessTokenSafely();
+ const { currentSummit } = currentSummitState;
+ const {
+ entity: { id: sponsorId }
+ } = currentSponsorState;
+ const params = { access_token: accessToken };
+
+ dispatch(startLoading());
+
+ return deleteRequest(
+ null,
+ createAction(SPONSOR_CUSTOMIZED_FORM_ITEM_UNARCHIVED)({ itemId }),
+ `${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/sponsor-forms/${formId}/items/${itemId}/archive`,
+ null,
+ snackbarErrorHandler
+ )(params)(dispatch).then(() => {
+ dispatch(stopLoading());
+ });
+ };
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 7384e4d74..8c16c2989 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -2432,6 +2432,27 @@
"error": "There was a problem creating the forms, please try again.",
"archived": "Form successfully archived.",
"unarchived": "Form successfully unarchived."
+ },
+ "form_manage_items": {
+ "add_item": "Add Item",
+ "add_item_inventory": "Add Item from Inventory",
+ "alert_info": "You can add or archive items from the list. To edit an item click on the item's Edit button. You can also change only a rate by clicking on it.",
+ "hide_archived": "Hide archived items",
+ "select_items": "Select items",
+ "code": "Code",
+ "name": "Name",
+ "early_bird_rate": "Early Bird Rate",
+ "standard_rate": "Standard Rate",
+ "onsite_rate": "On site rate",
+ "default_quantity": "Default Quantity",
+ "add_selected": "Add Selected Items",
+ "item_updated": "Form item updated successfully",
+ "item_created": "Form item created successfully",
+ "sort_asc_label": "A-Z",
+ "sort_desc_label": "Z-A",
+ "placeholder": {
+ "search": "Search..."
+ }
}
},
"placeholders": {
@@ -2528,7 +2549,7 @@
},
"sponsor_form_item_list": {
"form_items": "Form Items",
- "alert_info": "You can add or archive items from the list. To edit an item click on the item's Edit botton. You can also change only a rate by clicking on it.",
+ "alert_info": "You can add or archive items from the list. To edit an item click on the item's Edit button. You can also change only a rate by clicking on it.",
"code": "Code",
"name": "Name",
"early_bird_rate": "Early bird rate",
@@ -2570,7 +2591,7 @@
"code": "Code",
"name": "Name",
"early_bird_rate": "Early bird rate",
- "standard_rate": "Standad rate",
+ "standard_rate": "Standard rate",
"onsite_rate": "On site rate",
"save": "Add selected items",
"items_added": "Items added successfully."
@@ -3617,6 +3638,8 @@
"inventory_item": "Item",
"inventory_item_created": "Inventory Item created successfully.",
"inventory_item_saved": "Inventory Item saved successfully.",
+ "new_item": "New Item",
+ "edit_item": "Edit Item",
"code": "Code",
"name": "Name",
"default_quantity": "Default Quantity",
diff --git a/src/layouts/sponsor-id-layout.js b/src/layouts/sponsor-id-layout.js
index ae3eee227..4b117c411 100644
--- a/src/layouts/sponsor-id-layout.js
+++ b/src/layouts/sponsor-id-layout.js
@@ -141,7 +141,13 @@ class SponsorIdLayout extends React.Component {
)}
/>
-
+
+
+
+
diff --git a/src/pages/sponsors/edit-sponsor-page.js b/src/pages/sponsors/edit-sponsor-page.js
index 5f3b6e214..470592250 100644
--- a/src/pages/sponsors/edit-sponsor-page.js
+++ b/src/pages/sponsors/edit-sponsor-page.js
@@ -42,6 +42,8 @@ import SponsorGeneralForm from "../../components/forms/sponsor-general-form/inde
import SponsorUsersListPerSponsorPage from "./sponsor-users-list-per-sponsor";
import SponsorFormsTab from "./sponsor-forms-tab";
import SponsorBadgeScans from "./sponsor-badge-scans";
+import SponsorFormsManageItems from "./sponsor-forms-tab/components/manage-items/sponsor-forms-manage-items";
+import { SPONSOR_TABS } from "../../utils/constants";
const CustomTabPanel = (props) => {
const { children, value, index, ...other } = props;
@@ -68,6 +70,9 @@ const EditSponsorPage = (props) => {
const {
entity,
member,
+ history,
+ location,
+ match,
currentSummit,
resetSponsorForm,
getSponsorAdvertisements,
@@ -91,10 +96,16 @@ const EditSponsorPage = (props) => {
getExtraQuestionMeta
} = props;
- const [selectedTab, setSelectedTab] = useState(0);
+ const [selectedTab, setSelectedTab] = useState(
+ location.pathname.includes("/sponsor-forms/") &&
+ location.pathname.includes("/items")
+ ? SPONSOR_TABS.FORMS
+ : 0
+ );
const handleTabChange = (event, newValue) => {
setSelectedTab(newValue);
+ history.push(`/app/summits/${currentSummit.id}/sponsors/${entity.id}`);
};
useEffect(() => {
@@ -115,19 +126,35 @@ const EditSponsorPage = (props) => {
};
const tabs = [
- { label: T.translate("edit_sponsor.tab.general"), value: 0 },
- { label: T.translate("edit_sponsor.tab.users"), value: 1 },
- { label: T.translate("edit_sponsor.tab.pages"), value: 2 },
- { label: T.translate("edit_sponsor.tab.media_uploads"), value: 3 },
- { label: T.translate("edit_sponsor.tab.forms"), value: 4 },
- { label: T.translate("edit_sponsor.tab.cart"), value: 5 },
- { label: T.translate("edit_sponsor.tab.purchases"), value: 6 },
- { label: T.translate("edit_sponsor.tab.badge_scans"), value: 7 }
+ {
+ label: T.translate("edit_sponsor.tab.general"),
+ value: SPONSOR_TABS.GENERAL
+ },
+ { label: T.translate("edit_sponsor.tab.users"), value: SPONSOR_TABS.USERS },
+ { label: T.translate("edit_sponsor.tab.pages"), value: SPONSOR_TABS.PAGES },
+ {
+ label: T.translate("edit_sponsor.tab.media_uploads"),
+ value: SPONSOR_TABS.MEDIA_UPLOADS
+ },
+ { label: T.translate("edit_sponsor.tab.forms"), value: SPONSOR_TABS.FORMS },
+ { label: T.translate("edit_sponsor.tab.cart"), value: SPONSOR_TABS.CART },
+ {
+ label: T.translate("edit_sponsor.tab.purchases"),
+ value: SPONSOR_TABS.PURCHASES
+ },
+ {
+ label: T.translate("edit_sponsor.tab.badge_scans"),
+ value: SPONSOR_TABS.BADGE_SCANS
+ }
];
+ const sponsorFormItemRoute =
+ location.pathname.includes("/sponsor-forms/") &&
+ location.pathname.includes("/items");
+
return (
-
+
{entity.company?.name}
@@ -144,6 +171,7 @@ const EditSponsorPage = (props) => {
key={t.value}
label={t.label}
value={t.value}
+ onClick={() => handleTabChange(null, t.value)}
sx={{
fontSize: "1.4rem",
lineHeight: "1.8rem",
@@ -183,7 +211,15 @@ const EditSponsorPage = (props) => {
-
+ {sponsorFormItemRoute ? (
+
+ ) : (
+
+ )}
diff --git a/src/pages/sponsors/sponsor-form-item-list-page/index.js b/src/pages/sponsors/sponsor-form-item-list-page/index.js
index 94a3bd0a7..e6cddeb62 100644
--- a/src/pages/sponsors/sponsor-form-item-list-page/index.js
+++ b/src/pages/sponsors/sponsor-form-item-list-page/index.js
@@ -15,7 +15,6 @@ import React, { useEffect, useState } from "react";
import { Breadcrumb } from "react-breadcrumbs";
import { connect } from "react-redux";
import T from "i18n-react/dist/i18n-react";
-import * as yup from "yup";
import {
Alert,
Box,
@@ -29,7 +28,6 @@ import AddIcon from "@mui/icons-material/Add";
import IconButton from "@mui/material/IconButton";
import Tooltip from "@mui/material/Tooltip";
import ImageIcon from "@mui/icons-material/Image";
-import { parsePrice } from "openstack-uicore-foundation/lib/utils/money";
import {
deleteSponsorFormItem,
getSponsorFormItem,
@@ -42,6 +40,7 @@ import ItemPopup from "./components/item-popup";
import InventoryPopup from "./components/inventory-popup";
import MuiTableEditable from "../../../components/mui/editable-table/mui-table-editable";
import { DEFAULT_CURRENT_PAGE } from "../../../utils/constants";
+import { rateCellValidation } from "../../../utils/yup";
const SponsorFormItemListPage = ({
match,
@@ -92,7 +91,8 @@ const SponsorFormItemListPage = ({
};
const handleCellEdit = (rowId, column, value) => {
- const tmpEntity = { id: rowId, [column]: parsePrice(value) };
+ const valueWithNoSign = String(value).replace(/^[^\d.-]+/, "");
+ const tmpEntity = { id: rowId, [column]: valueWithNoSign };
updateSponsorFormItem(formId, tmpEntity);
};
@@ -113,37 +113,6 @@ const SponsorFormItemListPage = ({
setOpenPopup("inventory");
};
- const rateCellValidation = () =>
- yup
- .number()
- // allow $ at the start
- .transform((value, originalValue) => {
- if (typeof originalValue === "string") {
- const cleaned = originalValue.replace(/^\$/, "");
- return cleaned === "" ? undefined : parseFloat(cleaned);
- }
- return value;
- })
- // check if there's letters or characters
- .test({
- name: "valid-format",
- message: T.translate("validation.number"),
- test: (value, { originalValue }) => {
- if (
- originalValue === undefined ||
- originalValue === null ||
- originalValue === ""
- )
- return true;
- return /^\$?-?\d+(\.\d+)?$/.test(originalValue);
- }
- })
- .min(0, T.translate("validation.number_positive"))
- .test("max-decimals", T.translate("validation.two_decimals"), (value) => {
- if (value === undefined || value === null) return true;
- return /^\d+(\.\d{1,2})?$/.test(value.toString());
- });
-
const columns = [
{
columnKey: "code",
diff --git a/src/pages/sponsors/sponsor-forms-tab/components/manage-items/sponsor-form-item-from-inventory.js b/src/pages/sponsors/sponsor-forms-tab/components/manage-items/sponsor-form-item-from-inventory.js
new file mode 100644
index 000000000..b7299ca8a
--- /dev/null
+++ b/src/pages/sponsors/sponsor-forms-tab/components/manage-items/sponsor-form-item-from-inventory.js
@@ -0,0 +1,288 @@
+import React, { useEffect, useState } from "react";
+import T from "i18n-react/dist/i18n-react";
+import PropTypes from "prop-types";
+import { connect } from "react-redux";
+import {
+ Box,
+ Button,
+ Checkbox,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ Divider,
+ FormControlLabel,
+ Grid2,
+ IconButton,
+ Tooltip,
+ Typography
+} from "@mui/material";
+import CloseIcon from "@mui/icons-material/Close";
+import ImageIcon from "@mui/icons-material/Image";
+import SwapVertIcon from "@mui/icons-material/SwapVert";
+import { currencyAmountFromCents } from "openstack-uicore-foundation/lib/utils/money";
+import SearchInput from "../../../../../components/mui/search-input";
+import {
+ DEFAULT_CURRENT_PAGE,
+ DEFAULT_PER_PAGE
+} from "../../../../../utils/constants";
+
+import { getInventoryItems } from "../../../../../actions/inventory-item-actions";
+import MuiTable from "../../../../../components/mui/table/mui-table";
+import MenuButton from "../../../../../components/mui/menu-button";
+
+const SponsorFormItemFromInventoryPopup = ({
+ open,
+ inventoryItems,
+ term,
+ order,
+ perPage,
+ orderDir,
+ currentPage,
+ totalInventoryItems,
+ onSave,
+ onClose,
+ getInventoryItems
+}) => {
+ const [selectedRows, setSelectedRows] = useState([]);
+
+ useEffect(() => {
+ getInventoryItems("", 1, DEFAULT_PER_PAGE, "id", 1);
+ }, []);
+
+ const handleSort = (key, dir) => {
+ getInventoryItems(term, 1, DEFAULT_PER_PAGE, key, dir);
+ };
+
+ const handlePageChange = (page) => {
+ getInventoryItems(term, page, perPage, order, orderDir);
+ };
+
+ const handlePerPageChange = (newPerPage) => {
+ getInventoryItems(term, DEFAULT_CURRENT_PAGE, newPerPage, order, orderDir);
+ };
+
+ const handleClose = () => {
+ setSelectedRows([]);
+ onClose();
+ };
+
+ const handleOnCheck = (rowId, checked) => {
+ if (checked) {
+ setSelectedRows([...selectedRows, rowId]);
+ } else {
+ setSelectedRows(selectedRows.filter((r) => r !== rowId));
+ }
+ };
+
+ const handleOnSearch = (searchTerm) => {
+ getInventoryItems(searchTerm, 1, DEFAULT_PER_PAGE, "id", 1);
+ };
+
+ const handleOnSave = () => {
+ onSave(selectedRows);
+ };
+
+ const columns = [
+ {
+ columnKey: "select",
+ header: "",
+ width: 30,
+ align: "center",
+ render: (row) => (
+ handleOnCheck(row.id, ev.target.checked)}
+ />
+ }
+ />
+ )
+ },
+ {
+ columnKey: "code",
+ header: T.translate("edit_sponsor.forms_tab.form_manage_items.code"),
+ sortable: false
+ },
+ {
+ columnKey: "name",
+ header: T.translate("edit_sponsor.forms_tab.form_manage_items.name"),
+ sortable: false
+ },
+ {
+ columnKey: "early_bird_rate",
+ header: T.translate(
+ "edit_sponsor.forms_tab.form_manage_items.early_bird_rate"
+ ),
+ sortable: false,
+ render: (row) => currencyAmountFromCents(row.early_bird_rate)
+ },
+ {
+ columnKey: "standard_rate",
+ header: T.translate(
+ "edit_sponsor.forms_tab.form_manage_items.standard_rate"
+ ),
+ sortable: false,
+ render: (row) => currencyAmountFromCents(row.standard_rate)
+ },
+ {
+ columnKey: "onsite_rate",
+ header: T.translate(
+ "edit_sponsor.forms_tab.form_manage_items.onsite_rate"
+ ),
+ sortable: false,
+ render: (row) => currencyAmountFromCents(row.onsite_rate)
+ },
+ {
+ columnKey: "default_quantity",
+ header: T.translate(
+ "edit_sponsor.forms_tab.form_manage_items.default_quantity"
+ ),
+ sortable: false
+ },
+ {
+ columnKey: "images",
+ header: "",
+ width: 40,
+ align: "center",
+ render: (row) =>
+ row.images?.length > 0 ? (
+
+
+
+ window.open(
+ row.images[0].file_url,
+ "_blank",
+ "noopener,noreferrer"
+ )
+ }
+ />
+
+
+ ) : null
+ }
+ ];
+
+ const tableOptions = {
+ sortCol: order,
+ sortDir: orderDir
+ };
+
+ return (
+
+ );
+};
+
+SponsorFormItemFromInventoryPopup.propTypes = {
+ onClose: PropTypes.func.isRequired,
+ onSave: PropTypes.func.isRequired,
+ open: PropTypes.bool.isRequired,
+ inventoryItems: PropTypes.array.isRequired,
+ term: PropTypes.string,
+ order: PropTypes.string,
+ perPage: PropTypes.number,
+ orderDir: PropTypes.string,
+ currentPage: PropTypes.number,
+ totalInventoryItems: PropTypes.number,
+ getInventoryItems: PropTypes.func.isRequired
+};
+
+const mapStateToProps = ({ currentInventoryItemListState }) => ({
+ ...currentInventoryItemListState
+});
+
+export default connect(mapStateToProps, {
+ getInventoryItems
+})(SponsorFormItemFromInventoryPopup);
diff --git a/src/pages/sponsors/sponsor-forms-tab/components/manage-items/sponsor-forms-manage-items.js b/src/pages/sponsors/sponsor-forms-tab/components/manage-items/sponsor-forms-manage-items.js
new file mode 100644
index 000000000..d4a292af0
--- /dev/null
+++ b/src/pages/sponsors/sponsor-forms-tab/components/manage-items/sponsor-forms-manage-items.js
@@ -0,0 +1,403 @@
+/**
+ * Copyright 2024 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,
+ Checkbox,
+ FormControlLabel,
+ FormGroup,
+ Grid2,
+ IconButton,
+ Tooltip
+} from "@mui/material";
+import AddIcon from "@mui/icons-material/Add";
+import ImageIcon from "@mui/icons-material/Image";
+import {
+ addSponsorManagedFormItems,
+ archiveSponsorCustomizedFormItem,
+ getSponsorCustomizedFormItems,
+ saveSponsorFormManagedItem,
+ deleteSponsorFormManagedItem,
+ resetSponsorFormManagedItem,
+ unarchiveSponsorCustomizedFormItem,
+ getSponsorFormManagedItem
+} from "../../../../../actions/sponsor-forms-actions";
+import CustomAlert from "../../../../../components/mui/custom-alert";
+import SearchInput from "../../../../../components/mui/search-input";
+import MuiTableEditable from "../../../../../components/mui/editable-table/mui-table-editable";
+import SponsorInventoryDialog from "../../../../sponsors_inventory/popup/sponsor-inventory-popup";
+import SponsorFormItemFromInventoryPopup from "./sponsor-form-item-from-inventory";
+import { DEFAULT_CURRENT_PAGE } from "../../../../../utils/constants";
+import { rateCellValidation } from "../../../../../utils/yup";
+
+const SponsorFormsManageItems = ({
+ term,
+ match,
+ hideArchived,
+ items,
+ order,
+ orderDir,
+ perPage,
+ currentPage,
+ totalCount,
+ getSponsorCustomizedFormItems,
+ currentInventoryItem,
+ resetSponsorFormManagedItem,
+ addSponsorManagedFormItems,
+ saveSponsorFormManagedItem,
+ deleteSponsorFormManagedItem,
+ archiveSponsorCustomizedFormItem,
+ unarchiveSponsorCustomizedFormItem,
+ getSponsorFormManagedItem
+}) => {
+ const [openPopup, setOpenPopup] = useState(null);
+
+ const handleClose = () => {
+ setOpenPopup(null);
+ };
+
+ const formId = match.params.form_id;
+
+ useEffect(() => {
+ getSponsorCustomizedFormItems(formId);
+ }, []);
+
+ const handlePageChange = (page) => {
+ getSponsorCustomizedFormItems(
+ formId,
+ term,
+ page,
+ perPage,
+ order,
+ orderDir,
+ hideArchived
+ );
+ };
+
+ const handlePerPageChange = (newPerPage) => {
+ getSponsorCustomizedFormItems(
+ formId,
+ term,
+ DEFAULT_CURRENT_PAGE,
+ newPerPage,
+ order,
+ orderDir,
+ hideArchived
+ );
+ };
+
+ const handleSort = (key, dir) => {
+ getSponsorCustomizedFormItems(
+ formId,
+ term,
+ DEFAULT_CURRENT_PAGE,
+ perPage,
+ key,
+ dir,
+ hideArchived
+ );
+ };
+
+ const handleSearch = (searchTerm) => {
+ getSponsorCustomizedFormItems(
+ formId,
+ searchTerm,
+ DEFAULT_CURRENT_PAGE,
+ perPage,
+ order,
+ orderDir,
+ hideArchived
+ );
+ };
+
+ const handleItemSave = (item) => {
+ saveSponsorFormManagedItem(formId, item).then(() => {
+ getSponsorCustomizedFormItems(
+ formId,
+ term,
+ DEFAULT_CURRENT_PAGE,
+ perPage,
+ order,
+ orderDir,
+ hideArchived
+ );
+ resetSponsorFormManagedItem();
+ setOpenPopup(null);
+ });
+ };
+
+ const handleOpenItemPopup = () => {
+ resetSponsorFormManagedItem();
+ setOpenPopup("add_item");
+ };
+
+ const handleArchiveItem = (item) =>
+ item.is_archived
+ ? unarchiveSponsorCustomizedFormItem(formId, item.id)
+ : archiveSponsorCustomizedFormItem(formId, item.id);
+
+ const handleHideArchivedItems = (ev) => {
+ getSponsorCustomizedFormItems(
+ formId,
+ term,
+ DEFAULT_CURRENT_PAGE,
+ perPage,
+ order,
+ orderDir,
+ ev.target.checked
+ );
+ };
+
+ const handleAddFromInventory = (itemsId) => {
+ addSponsorManagedFormItems(formId, itemsId).then(() => handleClose());
+ };
+
+ const handleCellEdit = (rowId, column, value) => {
+ const valueWithNoSign = String(value).replace(/^[^\d.-]+/, "");
+ const tmpEntity = {
+ id: rowId,
+ [column]: valueWithNoSign
+ };
+ saveSponsorFormManagedItem(formId, tmpEntity);
+ };
+
+ const handleRowEdit = (row) => {
+ getSponsorFormManagedItem(formId, row.id).then(() =>
+ setOpenPopup("add_item")
+ );
+ };
+
+ const handleRowDelete = (rowId) => {
+ deleteSponsorFormManagedItem(formId, rowId).then(() =>
+ getSponsorCustomizedFormItems(
+ formId,
+ term,
+ DEFAULT_CURRENT_PAGE,
+ perPage,
+ order,
+ orderDir,
+ hideArchived
+ )
+ );
+ };
+
+ const sponsorItemColumns = [
+ {
+ columnKey: "code",
+ header: T.translate("edit_sponsor.forms_tab.form_manage_items.code"),
+ sortable: false
+ },
+ {
+ columnKey: "name",
+ header: T.translate("edit_sponsor.forms_tab.form_manage_items.name"),
+ sortable: false
+ },
+ {
+ columnKey: "early_bird_rate",
+ header: T.translate(
+ "edit_sponsor.forms_tab.form_manage_items.early_bird_rate"
+ ),
+ sortable: false,
+ editable: true,
+ validation: {
+ schema: rateCellValidation()
+ }
+ },
+ {
+ columnKey: "standard_rate",
+ header: T.translate(
+ "edit_sponsor.forms_tab.form_manage_items.standard_rate"
+ ),
+ sortable: false,
+ editable: true,
+ validation: {
+ schema: rateCellValidation()
+ }
+ },
+ {
+ columnKey: "onsite_rate",
+ header: T.translate(
+ "edit_sponsor.forms_tab.form_manage_items.onsite_rate"
+ ),
+ sortable: false,
+ editable: true,
+ validation: {
+ schema: rateCellValidation()
+ }
+ },
+ {
+ columnKey: "default_quantity",
+ header: T.translate(
+ "edit_sponsor.forms_tab.form_manage_items.default_quantity"
+ ),
+ sortable: false
+ },
+ {
+ columnKey: "images",
+ header: "",
+ width: 40,
+ align: "center",
+ render: (row) =>
+ row.images?.length > 0 ? (
+
+
+
+ window.open(
+ row.images[0].file_url,
+ "_blank",
+ "noopener,noreferrer"
+ )
+ }
+ />
+
+
+ ) : null
+ }
+ ];
+
+ return (
+
+
+
+
+ {totalCount} items
+
+
+
+
+ }
+ label={T.translate(
+ "edit_sponsor.forms_tab.form_manage_items.hide_archived"
+ )}
+ />
+
+
+
+
+
+
+ }
+ sx={{ height: "36px" }}
+ >
+ {T.translate("edit_sponsor.forms_tab.form_manage_items.add_item")}
+
+
+
+
+
+
+
+
+
+
+
+ {/* ADD ITEM */}
+ {openPopup === "add_item" && (
+
+ )}
+
+
+
+ );
+};
+
+const mapStateToProps = ({ sponsorCustomizedFormItemsListState }) => ({
+ ...sponsorCustomizedFormItemsListState,
+ currentInventoryItem: sponsorCustomizedFormItemsListState.currentItem
+});
+
+export default connect(mapStateToProps, {
+ getSponsorCustomizedFormItems,
+ resetSponsorFormManagedItem,
+ addSponsorManagedFormItems,
+ saveSponsorFormManagedItem,
+ deleteSponsorFormManagedItem,
+ getSponsorFormManagedItem,
+ archiveSponsorCustomizedFormItem,
+ unarchiveSponsorCustomizedFormItem
+})(SponsorFormsManageItems);
diff --git a/src/pages/sponsors/sponsor-forms-tab/index.js b/src/pages/sponsors/sponsor-forms-tab/index.js
index 06920a737..b4b679cf8 100644
--- a/src/pages/sponsors/sponsor-forms-tab/index.js
+++ b/src/pages/sponsors/sponsor-forms-tab/index.js
@@ -41,6 +41,7 @@ import { DEFAULT_CURRENT_PAGE } from "../../../utils/constants";
const SponsorFormsTab = ({
term,
+ history,
hideArchived,
managedForms,
customizedForms,
@@ -111,7 +112,9 @@ const SponsorFormsTab = ({
: archiveSponsorCustomizedForm(item.id);
const handleManageItems = (item) => {
- console.log("MANAGE ITEMS : ", item);
+ history.push(
+ `/app/summits/${summitId}/sponsors/${sponsor.id}/sponsor-forms/${item.id}/items`
+ );
};
const handleCustomizedEdit = (item) => {
diff --git a/src/pages/sponsors_inventory/popup/sponsor-inventory-popup.js b/src/pages/sponsors_inventory/popup/sponsor-inventory-popup.js
index c079e005a..ffa3bcf2d 100644
--- a/src/pages/sponsors_inventory/popup/sponsor-inventory-popup.js
+++ b/src/pages/sponsors_inventory/popup/sponsor-inventory-popup.js
@@ -30,7 +30,7 @@ import {
import showConfirmDialog from "../../../components/mui/showConfirmDialog";
import MetaFieldValues from "./meta-field-values";
import MuiFormikTextField from "../../../components/mui/formik-inputs/mui-formik-textfield";
-import MuiFormikPriceField from "../../../components/mui/formik-inputs/mui-formik-pricefield.js";
+import MuiFormikPriceField from "../../../components/mui/formik-inputs/mui-formik-pricefield";
import useScrollToError from "../../../hooks/useScrollToError";
import MuiFormikSelect from "../../../components/mui/formik-inputs/mui-formik-select";
import MuiFormikCheckbox from "../../../components/mui/formik-inputs/mui-formik-checkbox";
@@ -69,7 +69,7 @@ const SponsorItemDialog = ({
code: yup.string().required(T.translate("validation.required")),
name: yup.string().required(T.translate("validation.required")),
description: yup.string().required(T.translate("validation.required")),
- images: yup.array().min(1, T.translate("validation.required")),
+ images: yup.array(),
early_bird_rate: decimalValidation(),
standard_rate: decimalValidation(),
onsite_rate: decimalValidation(),
@@ -182,7 +182,7 @@ const SponsorItemDialog = ({
}
};
- if (fieldType.id) {
+ if (fieldType.id && onMetaFieldTypeDeleted) {
onMetaFieldTypeDeleted(initialEntity.id, fieldType.id)
.then(() => removeOrResetField())
.catch((err) => console.log("Error at delete field from API", err));
@@ -243,7 +243,9 @@ const SponsorItemDialog = ({
disableRestoreFocus
>
- Edit Item
+ {initialEntity.id
+ ? T.translate("edit_inventory_item.edit_item")
+ : T.translate("edit_inventory_item.new_item")}
@@ -582,7 +584,7 @@ const SponsorItemDialog = ({
>
- {T.translate("edit_inventory_item.images")} *
+ {T.translate("edit_inventory_item.images")}
{formik.touched.images && formik.errors.images && (
{formik.errors.images}
diff --git a/src/reducers/sponsors/sponsor-customized-form-items-list-reducer.js b/src/reducers/sponsors/sponsor-customized-form-items-list-reducer.js
new file mode 100644
index 000000000..a1f436f84
--- /dev/null
+++ b/src/reducers/sponsors/sponsor-customized-form-items-list-reducer.js
@@ -0,0 +1,195 @@
+/**
+ * Copyright 2019 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 { LOGOUT_USER } from "openstack-uicore-foundation/lib/security/actions";
+import {
+ amountFromCents,
+ currencyAmountFromCents
+} from "openstack-uicore-foundation/lib/utils/money";
+import {
+ RECEIVE_SPONSOR_CUSTOMIZED_FORM_ITEMS,
+ REQUEST_SPONSOR_CUSTOMIZED_FORM_ITEMS,
+ RECEIVE_SPONSOR_CUSTOMIZED_FORM_ITEM,
+ SPONSOR_CUSTOMIZED_FORM_ITEM_ARCHIVED,
+ SPONSOR_CUSTOMIZED_FORM_ITEM_DELETED,
+ SPONSOR_CUSTOMIZED_FORM_ITEM_UNARCHIVED,
+ SPONSOR_FORM_MANAGED_ITEM_UPDATED,
+ SPONSOR_CUSTOMIZED_FORM_ITEMS_ADDED,
+ RESET_SPONSOR_FORM_MANAGED_ITEM
+} from "../../actions/sponsor-forms-actions";
+import { SET_CURRENT_SUMMIT } from "../../actions/summit-actions";
+
+const DEFAULT_ITEM_ENTITY = {
+ code: "",
+ name: "",
+ description: "",
+ early_bird_rate: 0,
+ standard_rate: 0,
+ onsite_rate: 0,
+ quantity_limit_per_show: 0,
+ quantity_limit_per_sponsor: 0,
+ default_quantity: 0,
+ images: [],
+ meta_fields: [
+ {
+ name: "",
+ type: "Text",
+ is_required: false,
+ values: []
+ }
+ ]
+};
+
+const DEFAULT_STATE = {
+ items: [],
+ hideArchived: false,
+ term: "",
+ order: "name",
+ orderDir: 1,
+ currentPage: 1,
+ lastPage: 1,
+ perPage: 10,
+ totalCount: 0,
+ currentItem: DEFAULT_ITEM_ENTITY
+};
+
+const sponsorCustomizedFormItemsListReducer = (
+ state = DEFAULT_STATE,
+ action
+) => {
+ const { type, payload } = action;
+
+ switch (type) {
+ case SET_CURRENT_SUMMIT:
+ case LOGOUT_USER: {
+ return DEFAULT_STATE;
+ }
+ case REQUEST_SPONSOR_CUSTOMIZED_FORM_ITEMS: {
+ const { term, order, orderDir, page, perPage, hideArchived } = payload;
+
+ return {
+ ...state,
+ term,
+ order,
+ orderDir,
+ items: [],
+ currentPage: page,
+ perPage,
+ hideArchived
+ };
+ }
+ case RECEIVE_SPONSOR_CUSTOMIZED_FORM_ITEMS: {
+ const {
+ current_page: currentPage,
+ total,
+ last_page: lastPage
+ } = payload.response;
+
+ const items = payload.response.data.map((a) => ({
+ id: a.id,
+ code: a.code,
+ name: a.name,
+ early_bird_rate: currencyAmountFromCents(a.early_bird_rate),
+ standard_rate: currencyAmountFromCents(a.standard_rate),
+ onsite_rate: currencyAmountFromCents(a.onsite_rate),
+ default_quantity: a.default_quantity,
+ is_archived: a.is_archived,
+ images: a.images
+ }));
+
+ return {
+ ...state,
+ items,
+ currentPage,
+ totalCount: total,
+ lastPage
+ };
+ }
+ case RECEIVE_SPONSOR_CUSTOMIZED_FORM_ITEM: {
+ const item = payload.response;
+
+ const currentItem = {
+ ...item,
+ early_bird_rate: amountFromCents(item.early_bird_rate),
+ standard_rate: amountFromCents(item.standard_rate),
+ onsite_rate: amountFromCents(item.onsite_rate),
+ meta_fields:
+ item.meta_fields.length > 0
+ ? item.meta_fields
+ : [
+ {
+ name: "",
+ type: "Text",
+ is_required: false,
+ values: []
+ }
+ ]
+ };
+ return { ...state, currentItem };
+ }
+ case SPONSOR_CUSTOMIZED_FORM_ITEM_DELETED: {
+ const { itemId } = payload;
+ const items = state.items.filter((it) => it.id !== itemId);
+
+ return { ...state, items };
+ }
+ case SPONSOR_CUSTOMIZED_FORM_ITEM_ARCHIVED: {
+ const { id: itemId } = payload.response;
+
+ const items = state.items.map((item) =>
+ item.id === itemId ? { ...item, is_archived: true } : item
+ );
+
+ return { ...state, items };
+ }
+ case SPONSOR_CUSTOMIZED_FORM_ITEM_UNARCHIVED: {
+ const { itemId } = payload;
+
+ const items = state.items.map((item) =>
+ item.id === itemId ? { ...item, is_archived: false } : item
+ );
+
+ return { ...state, items };
+ }
+ case SPONSOR_FORM_MANAGED_ITEM_UPDATED: {
+ const updatedItem = payload.response;
+ const items = state.items.map((item) =>
+ item.id === updatedItem.id
+ ? {
+ id: updatedItem.id,
+ code: updatedItem.code,
+ name: updatedItem.name,
+ early_bird_rate: currencyAmountFromCents(
+ updatedItem.early_bird_rate
+ ),
+ standard_rate: currencyAmountFromCents(updatedItem.standard_rate),
+ onsite_rate: currencyAmountFromCents(updatedItem.onsite_rate),
+ default_quantity: updatedItem.default_quantity,
+ is_archived: updatedItem.is_archived,
+ images: updatedItem.images
+ }
+ : item
+ );
+ return { ...state, items };
+ }
+ case SPONSOR_CUSTOMIZED_FORM_ITEMS_ADDED: {
+ return { ...state };
+ }
+ case RESET_SPONSOR_FORM_MANAGED_ITEM:
+ return { ...state, currentItem: DEFAULT_ITEM_ENTITY };
+ default:
+ return state;
+ }
+};
+
+export default sponsorCustomizedFormItemsListReducer;
diff --git a/src/store.js b/src/store.js
index 64762f8ac..ef7e2e218 100644
--- a/src/store.js
+++ b/src/store.js
@@ -164,6 +164,7 @@ import eventRSVPInvitationListReducer from "./reducers/rsvps/event-rsvp-invitati
import eventRSVPReducer from "./reducers/events/event-rsvp-reducer.js";
import sponsorPageFormsListReducer from "./reducers/sponsors/sponsor-page-forms-list-reducer.js";
import sponsorCustomizedFormReducer from "./reducers/sponsors/sponsor-customized-form-reducer.js";
+import sponsorCustomizedFormItemsListReducer from "./reducers/sponsors/sponsor-customized-form-items-list-reducer.js";
// default: localStorage if web, AsyncStorage if react-native
@@ -250,6 +251,7 @@ const reducers = persistCombineReducers(config, {
sponsorUsersListState: sponsorUsersListReducer,
sponsorPageFormsListState: sponsorPageFormsListReducer,
sponsorCustomizedFormState: sponsorCustomizedFormReducer,
+ sponsorCustomizedFormItemsListState: sponsorCustomizedFormItemsListReducer,
currentSponsorPromocodeListState: sponsorPromocodeListReducer,
currentSponsorExtraQuestionState: sponsorExtraQuestionReducer,
currentSponsorAdvertisementState: sponsorAdvertisementReducer,
diff --git a/src/utils/constants.js b/src/utils/constants.js
index a6d2d7139..360988a92 100644
--- a/src/utils/constants.js
+++ b/src/utils/constants.js
@@ -223,3 +223,14 @@ export const ROOM_OCCUPANCY_OPTIONS = [
];
export const BADGE_QR_MINIMUM_EXPECTED_FIELDS = 3;
+
+export const SPONSOR_TABS = {
+ GENERAL: 0,
+ USERS: 1,
+ PAGES: 2,
+ MEDIA_UPLOADS: 3,
+ FORMS: 4,
+ CART: 5,
+ PURCHASES: 6,
+ BADGE_SCANS: 7
+};
diff --git a/src/utils/yup.js b/src/utils/yup.js
index 0b3999935..86c770b39 100644
--- a/src/utils/yup.js
+++ b/src/utils/yup.js
@@ -47,6 +47,33 @@ export const decimalValidation = () =>
.typeError(T.translate("validation.number"))
.positive(T.translate("validation.number_positive"))
.required(T.translate("validation.required"))
+
+export const rateCellValidation = () =>
+ yup
+ .number()
+ // allow $ at the start
+ .transform((value, originalValue) => {
+ if (typeof originalValue === "string") {
+ const cleaned = originalValue.replace(/^\$/, "");
+ return cleaned === "" ? undefined : parseFloat(cleaned);
+ }
+ return value;
+ })
+ // check if there's letters or characters
+ .test({
+ name: "valid-format",
+ message: T.translate("validation.number"),
+ test: (value, { originalValue }) => {
+ if (
+ originalValue === undefined ||
+ originalValue === null ||
+ originalValue === ""
+ )
+ return true;
+ return /^\$?-?\d+(\.\d+)?$/.test(originalValue);
+ }
+ })
+ .positive(T.translate("validation.number_positive"))
.test("max-decimals", T.translate("validation.two_decimals"), (value) => {
if (value === undefined || value === null) return true;
return /^\d+(\.\d{1,2})?$/.test(value.toString());