Skip to content

Commit 1ce0c7f

Browse files
feat: sponsor cart view (#748)
* feat: sponsor cart view * fix: remove centsToDollar * fix: translate string * fix: remove unnecesary scopes
1 parent c119116 commit 1ce0c7f

12 files changed

Lines changed: 531 additions & 30 deletions

File tree

.env.example

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ PRINT_APP_URL=https://badge-print-app.dev.fnopen.com
1212
PUB_API_BASE_URL=
1313
OS_BASE_URL=
1414
SCOPES_BASE_REALM=${API_BASE_URL}
15-
PURCHASES_API_SCOPES=purchases-show-medata/read purchases-show-medata/write show-form/read show-form/write
15+
PURCHASES_API_SCOPES=purchases-show-medata/read purchases-show-medata/write show-form/read show-form/write customized-form/write customized-form/read carts/read carts/write
1616
SPONSOR_USERS_API_SCOPES="show-medata/read show-medata/write access-requests/read access-requests/write sponsor-users/read sponsor-users/write groups/read groups/write"
1717
EMAIL_SCOPES="clients/read templates/read templates/write emails/read"
1818
FILE_UPLOAD_SCOPES="files/upload"
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/**
2+
* Copyright 2018 OpenStack Foundation
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
* Unless required by applicable law or agreed to in writing, software
8+
* distributed under the License is distributed on an "AS IS" BASIS,
9+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
* See the License for the specific language governing permissions and
11+
* limitations under the License.
12+
* */
13+
14+
import {
15+
authErrorHandler,
16+
createAction,
17+
getRequest,
18+
deleteRequest,
19+
startLoading,
20+
stopLoading
21+
} from "openstack-uicore-foundation/lib/utils/actions";
22+
23+
import T from "i18n-react";
24+
import { escapeFilterValue, getAccessTokenSafely } from "../utils/methods";
25+
import { snackbarErrorHandler, snackbarSuccessHandler } from "./base-actions";
26+
import { ERROR_CODE_404 } from "../utils/constants";
27+
28+
export const REQUEST_SPONSOR_CART = "REQUEST_SPONSOR_CART";
29+
export const RECEIVE_SPONSOR_CART = "RECEIVE_SPONSOR_CART";
30+
export const SPONSOR_CART_FORM_DELETED = "SPONSOR_CART_FORM_DELETED";
31+
32+
const customErrorHandler = (err, res) => (dispatch, state) => {
33+
const code = err.status;
34+
dispatch(stopLoading());
35+
switch (code) {
36+
case ERROR_CODE_404:
37+
break;
38+
default:
39+
authErrorHandler(err, res)(dispatch, state);
40+
}
41+
};
42+
43+
export const getSponsorCart =
44+
(term = "") =>
45+
async (dispatch, getState) => {
46+
const { currentSummitState, currentSponsorState } = getState();
47+
const { currentSummit } = currentSummitState;
48+
const {
49+
entity: { id: sponsorId }
50+
} = currentSponsorState;
51+
const accessToken = await getAccessTokenSafely();
52+
const summitTZ = currentSummit.time_zone.name;
53+
const filter = [];
54+
55+
dispatch(startLoading());
56+
57+
if (term) {
58+
const escapedTerm = escapeFilterValue(term);
59+
filter.push(`name=@${escapedTerm},code=@${escapedTerm}`);
60+
}
61+
62+
const params = {
63+
access_token: accessToken
64+
};
65+
66+
if (filter.length > 0) {
67+
params["filter[]"] = filter;
68+
}
69+
70+
return getRequest(
71+
createAction(REQUEST_SPONSOR_CART),
72+
createAction(RECEIVE_SPONSOR_CART),
73+
`${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/carts/current`,
74+
customErrorHandler,
75+
{ term, summitTZ }
76+
)(params)(dispatch)
77+
.catch((err) => {
78+
console.error(err);
79+
})
80+
.finally(() => {
81+
dispatch(stopLoading());
82+
});
83+
};
84+
85+
86+
export const deleteSponsorCartForm =
87+
(formId) => async (dispatch, getState) => {
88+
const { currentSummitState, currentSponsorState } = getState();
89+
const { currentSummit } = currentSummitState;
90+
const {
91+
entity: { id: sponsorId }
92+
} = currentSponsorState;
93+
const accessToken = await getAccessTokenSafely();
94+
const params = { access_token: accessToken };
95+
96+
dispatch(startLoading());
97+
98+
return deleteRequest(
99+
null,
100+
createAction(SPONSOR_CART_FORM_DELETED)({ formId }),
101+
`${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/sponsor-forms/${formId}`,
102+
null,
103+
snackbarErrorHandler
104+
)(params)(dispatch)
105+
.then(() => {
106+
dispatch(
107+
snackbarSuccessHandler({
108+
title: T.translate("general.success"),
109+
html: T.translate("sponsor_forms.form_delete_success")
110+
})
111+
);
112+
})
113+
.finally(() => {
114+
dispatch(stopLoading());
115+
});
116+
};
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import TableCell from "@mui/material/TableCell";
2+
import TableRow from "@mui/material/TableRow";
3+
import * as React from "react";
4+
import { Typography } from "@mui/material";
5+
6+
const NotesRow = ({ colCount, note }) => (
7+
<TableRow>
8+
<TableCell sx={{ fontWeight: 800 }} colSpan={colCount}>
9+
<Typography variant="body2" sx={{ color: "text.secondary" }}>
10+
{note}
11+
</Typography>
12+
</TableCell>
13+
</TableRow>
14+
);
15+
16+
export default NotesRow;
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import TableCell from "@mui/material/TableCell";
2+
import TableRow from "@mui/material/TableRow";
3+
import * as React from "react";
4+
import T from "i18n-react/dist/i18n-react";
5+
6+
const TotalRow = ({ columns, targetCol, total, trailing = 0 }) => {
7+
return (
8+
<TableRow>
9+
{columns.map((col, i) => {
10+
if (i === 0)
11+
return (
12+
<TableCell key={col.columnKey} sx={{ fontWeight: 800, textTransform: "uppercase" }}>
13+
{T.translate("mui_table.total")}
14+
</TableCell>
15+
);
16+
if (col.columnKey === targetCol)
17+
return (
18+
<TableCell key={col.columnKey} sx={{ fontWeight: 800 }}>
19+
{total}
20+
</TableCell>
21+
);
22+
return <TableCell key={col.columnKey} />;
23+
})}
24+
{[...Array(trailing)].map((_, i) => (
25+
// eslint-disable-next-line react/no-array-index-key
26+
<TableCell key={`extra-row-total-${i}`} sx={{ width: 40 }} />
27+
))}
28+
</TableRow>
29+
);
30+
};
31+
32+
export default TotalRow;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { default as TotalRow } from "./TotalRow";
2+
export { default as NotesRow } from "./NotesRow";

src/components/mui/table/mui-table.js

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ import T from "i18n-react/dist/i18n-react";
33
import { isBoolean } from "lodash";
44
import {
55
Box,
6+
Button,
67
IconButton,
78
Paper,
8-
Button,
99
Table,
1010
TableBody,
1111
TableCell,
@@ -31,6 +31,7 @@ import styles from "./mui-table.module.less";
3131
const MuiTable = ({
3232
columns = [],
3333
data = [],
34+
children,
3435
totalRows,
3536
perPage,
3637
currentPage,
@@ -253,6 +254,8 @@ const MuiTable = ({
253254
)}
254255
</TableRow>
255256
))}
257+
{/* Here we inject extra rows passed as children */}
258+
{children}
256259
{data.length === 0 && (
257260
<TableRow>
258261
<TableCell colSpan={columns.length} align="center">
@@ -265,28 +268,30 @@ const MuiTable = ({
265268
</TableContainer>
266269

267270
{/* PAGINATION */}
268-
<TablePagination
269-
component="div"
270-
count={totalRows}
271-
rowsPerPageOptions={customPerPageOptions}
272-
rowsPerPage={perPage}
273-
page={currentPage - 1}
274-
onPageChange={handleChangePage}
275-
onRowsPerPageChange={handleChangeRowsPerPage}
276-
labelRowsPerPage={T.translate("mui_table.rows_per_page")}
277-
sx={{
278-
".MuiTablePagination-toolbar": {
279-
alignItems: "baseline",
280-
marginTop: "1.6rem"
281-
},
282-
".MuiTablePagination-spacer": {
283-
display: "none"
284-
},
285-
".MuiTablePagination-displayedRows": {
286-
marginLeft: "auto"
287-
}
288-
}}
289-
/>
271+
{perPage && currentPage && (
272+
<TablePagination
273+
component="div"
274+
count={totalRows}
275+
rowsPerPageOptions={customPerPageOptions}
276+
rowsPerPage={perPage}
277+
page={currentPage - 1}
278+
onPageChange={handleChangePage}
279+
onRowsPerPageChange={handleChangeRowsPerPage}
280+
labelRowsPerPage={T.translate("mui_table.rows_per_page")}
281+
sx={{
282+
".MuiTablePagination-toolbar": {
283+
alignItems: "baseline",
284+
marginTop: "1.6rem"
285+
},
286+
".MuiTablePagination-spacer": {
287+
display: "none"
288+
},
289+
".MuiTablePagination-displayedRows": {
290+
marginLeft: "auto"
291+
}
292+
}}
293+
/>
294+
)}
290295
</Paper>
291296
</Box>
292297
);

src/i18n/en.json

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2434,6 +2434,20 @@
24342434
"unarchived": "Form successfully unarchived."
24352435
}
24362436
},
2437+
"cart_tab": {
2438+
"new_form": "New Form",
2439+
"forms": "forms",
2440+
"code": "Code",
2441+
"name": "Name",
2442+
"add_ons": "Add-ons",
2443+
"discount": "Discount",
2444+
"amount": "Amount",
2445+
"manage_items": "Manage Items",
2446+
"add_form": "Add Form",
2447+
"no_cart": "No cart found.",
2448+
"pay_cc": "pay with credit card or ach",
2449+
"pay_invoice": "pay with invoice"
2450+
},
24372451
"placeholders": {
24382452
"select_sponsorship": "Select a Sponsorship",
24392453
"sponsorship_type": "Start typing to choose a Tier...",
@@ -3762,7 +3776,8 @@
37623776
"no_items": "No items found.",
37633777
"rows_per_page": "Rows per page",
37643778
"sorted_desc": "sorted descending",
3765-
"sorted_asc": "sorted ascending"
3779+
"sorted_asc": "sorted ascending",
3780+
"total": "Total"
37663781
},
37673782
"event_rsvp_list": {
37683783
"name": "Name",

src/pages/sponsors/edit-sponsor-page.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import SponsorGeneralForm from "../../components/forms/sponsor-general-form/inde
4242
import SponsorUsersListPerSponsorPage from "./sponsor-users-list-per-sponsor";
4343
import SponsorFormsTab from "./sponsor-forms-tab";
4444
import SponsorBadgeScans from "./sponsor-badge-scans";
45+
import SponsorCartTab from "./sponsor-cart-tab";
4546

4647
const CustomTabPanel = (props) => {
4748
const { children, value, index, ...other } = props;
@@ -127,7 +128,7 @@ const EditSponsorPage = (props) => {
127128

128129
return (
129130
<Box>
130-
<Container maxWidth="lg" sx={{position: "relative"}}>
131+
<Container maxWidth="lg" sx={{ position: "relative" }}>
131132
<Typography fontSize="3.4rem" variant="h4">
132133
{entity.company?.name}
133134
</Typography>
@@ -185,6 +186,9 @@ const EditSponsorPage = (props) => {
185186
<CustomTabPanel value={selectedTab} index={4}>
186187
<SponsorFormsTab sponsor={entity} summitId={currentSummit.id} />
187188
</CustomTabPanel>
189+
<CustomTabPanel value={selectedTab} index={5}>
190+
<SponsorCartTab sponsor={entity} summitId={currentSummit.id} />
191+
</CustomTabPanel>
188192
<CustomTabPanel value={selectedTab} index={7}>
189193
<SponsorBadgeScans sponsor={entity} />
190194
</CustomTabPanel>

0 commit comments

Comments
 (0)