-
Notifications
You must be signed in to change notification settings - Fork 4
feat: sponsor cart view #748
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| /** | ||
| * 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 { | ||
| authErrorHandler, | ||
| createAction, | ||
| getRequest, | ||
| deleteRequest, | ||
| startLoading, | ||
| stopLoading | ||
| } from "openstack-uicore-foundation/lib/utils/actions"; | ||
|
|
||
| import T from "i18n-react"; | ||
| import { escapeFilterValue, getAccessTokenSafely } from "../utils/methods"; | ||
| import { snackbarErrorHandler, snackbarSuccessHandler } from "./base-actions"; | ||
| import { ERROR_CODE_404 } from "../utils/constants"; | ||
|
|
||
| export const REQUEST_SPONSOR_CART = "REQUEST_SPONSOR_CART"; | ||
| export const RECEIVE_SPONSOR_CART = "RECEIVE_SPONSOR_CART"; | ||
| export const SPONSOR_CART_FORM_DELETED = "SPONSOR_CART_FORM_DELETED"; | ||
|
|
||
| const customErrorHandler = (err, res) => (dispatch, state) => { | ||
| const code = err.status; | ||
| dispatch(stopLoading()); | ||
| switch (code) { | ||
| case ERROR_CODE_404: | ||
| break; | ||
| default: | ||
| authErrorHandler(err, res)(dispatch, state); | ||
| } | ||
| }; | ||
|
|
||
| export const getSponsorCart = | ||
| (term = "") => | ||
| async (dispatch, getState) => { | ||
| const { currentSummitState, currentSponsorState } = getState(); | ||
| const { currentSummit } = currentSummitState; | ||
| const { | ||
| entity: { id: sponsorId } | ||
| } = currentSponsorState; | ||
| const accessToken = await getAccessTokenSafely(); | ||
| const summitTZ = currentSummit.time_zone.name; | ||
| const filter = []; | ||
|
|
||
| dispatch(startLoading()); | ||
|
|
||
| if (term) { | ||
| const escapedTerm = escapeFilterValue(term); | ||
| filter.push(`name=@${escapedTerm},code=@${escapedTerm}`); | ||
| } | ||
|
|
||
| const params = { | ||
| access_token: accessToken | ||
| }; | ||
|
|
||
| if (filter.length > 0) { | ||
| params["filter[]"] = filter; | ||
| } | ||
|
|
||
| return getRequest( | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @santipalenque as stated on ticket
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it is handled in customErrorHandler |
||
| createAction(REQUEST_SPONSOR_CART), | ||
| createAction(RECEIVE_SPONSOR_CART), | ||
| `${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/carts/current`, | ||
| customErrorHandler, | ||
| { term, summitTZ } | ||
| )(params)(dispatch) | ||
| .catch((err) => { | ||
| console.error(err); | ||
| }) | ||
| .finally(() => { | ||
| dispatch(stopLoading()); | ||
| }); | ||
| }; | ||
|
|
||
|
|
||
| export const deleteSponsorCartForm = | ||
| (formId) => async (dispatch, getState) => { | ||
| const { currentSummitState, currentSponsorState } = getState(); | ||
| const { currentSummit } = currentSummitState; | ||
| const { | ||
| entity: { id: sponsorId } | ||
| } = currentSponsorState; | ||
| const accessToken = await getAccessTokenSafely(); | ||
| const params = { access_token: accessToken }; | ||
|
|
||
| dispatch(startLoading()); | ||
|
|
||
| return deleteRequest( | ||
| null, | ||
| createAction(SPONSOR_CART_FORM_DELETED)({ formId }), | ||
| `${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/sponsor-forms/${formId}`, | ||
| null, | ||
| snackbarErrorHandler | ||
| )(params)(dispatch) | ||
| .then(() => { | ||
| dispatch( | ||
| snackbarSuccessHandler({ | ||
| title: T.translate("general.success"), | ||
| html: T.translate("sponsor_forms.form_delete_success") | ||
| }) | ||
| ); | ||
| }) | ||
| .finally(() => { | ||
| dispatch(stopLoading()); | ||
| }); | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| import TableCell from "@mui/material/TableCell"; | ||
| import TableRow from "@mui/material/TableRow"; | ||
| import * as React from "react"; | ||
| import { Typography } from "@mui/material"; | ||
|
|
||
| const NotesRow = ({ colCount, note }) => ( | ||
| <TableRow> | ||
| <TableCell sx={{ fontWeight: 800 }} colSpan={colCount}> | ||
| <Typography variant="body2" sx={{ color: "text.secondary" }}> | ||
| {note} | ||
| </Typography> | ||
| </TableCell> | ||
| </TableRow> | ||
| ); | ||
|
|
||
| export default NotesRow; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| import TableCell from "@mui/material/TableCell"; | ||
| import TableRow from "@mui/material/TableRow"; | ||
| import * as React from "react"; | ||
| import T from "i18n-react/dist/i18n-react"; | ||
|
|
||
| const TotalRow = ({ columns, targetCol, total, trailing = 0 }) => { | ||
| return ( | ||
| <TableRow> | ||
| {columns.map((col, i) => { | ||
| if (i === 0) | ||
| return ( | ||
| <TableCell key={col.columnKey} sx={{ fontWeight: 800, textTransform: "uppercase" }}> | ||
| {T.translate("mui_table.total")} | ||
| </TableCell> | ||
| ); | ||
| if (col.columnKey === targetCol) | ||
| return ( | ||
| <TableCell key={col.columnKey} sx={{ fontWeight: 800 }}> | ||
| {total} | ||
| </TableCell> | ||
| ); | ||
| return <TableCell key={col.columnKey} />; | ||
| })} | ||
| {[...Array(trailing)].map((_, i) => ( | ||
| // eslint-disable-next-line react/no-array-index-key | ||
| <TableCell key={`extra-row-total-${i}`} sx={{ width: 40 }} /> | ||
| ))} | ||
| </TableRow> | ||
| ); | ||
| }; | ||
|
|
||
| export default TotalRow; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| export { default as TotalRow } from "./TotalRow"; | ||
| export { default as NotesRow } from "./NotesRow"; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,9 +3,9 @@ import T from "i18n-react/dist/i18n-react"; | |
| import { isBoolean } from "lodash"; | ||
| import { | ||
| Box, | ||
| Button, | ||
| IconButton, | ||
| Paper, | ||
| Button, | ||
| Table, | ||
| TableBody, | ||
| TableCell, | ||
|
|
@@ -31,6 +31,7 @@ import styles from "./mui-table.module.less"; | |
| const MuiTable = ({ | ||
| columns = [], | ||
| data = [], | ||
| children, | ||
| totalRows, | ||
| perPage, | ||
| currentPage, | ||
|
|
@@ -253,6 +254,8 @@ const MuiTable = ({ | |
| )} | ||
| </TableRow> | ||
| ))} | ||
| {/* Here we inject extra rows passed as children */} | ||
| {children} | ||
| {data.length === 0 && ( | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @santipalenque we need to review this logic
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure I understand, you want to hide the total row if no data ? |
||
| <TableRow> | ||
| <TableCell colSpan={columns.length} align="center"> | ||
|
|
@@ -265,28 +268,30 @@ const MuiTable = ({ | |
| </TableContainer> | ||
|
|
||
| {/* PAGINATION */} | ||
| <TablePagination | ||
| component="div" | ||
| count={totalRows} | ||
| rowsPerPageOptions={customPerPageOptions} | ||
| rowsPerPage={perPage} | ||
| page={currentPage - 1} | ||
| onPageChange={handleChangePage} | ||
| onRowsPerPageChange={handleChangeRowsPerPage} | ||
| labelRowsPerPage={T.translate("mui_table.rows_per_page")} | ||
| sx={{ | ||
| ".MuiTablePagination-toolbar": { | ||
| alignItems: "baseline", | ||
| marginTop: "1.6rem" | ||
| }, | ||
| ".MuiTablePagination-spacer": { | ||
| display: "none" | ||
| }, | ||
| ".MuiTablePagination-displayedRows": { | ||
| marginLeft: "auto" | ||
| } | ||
| }} | ||
| /> | ||
| {perPage && currentPage && ( | ||
| <TablePagination | ||
| component="div" | ||
| count={totalRows} | ||
| rowsPerPageOptions={customPerPageOptions} | ||
| rowsPerPage={perPage} | ||
| page={currentPage - 1} | ||
| onPageChange={handleChangePage} | ||
| onRowsPerPageChange={handleChangeRowsPerPage} | ||
| labelRowsPerPage={T.translate("mui_table.rows_per_page")} | ||
| sx={{ | ||
| ".MuiTablePagination-toolbar": { | ||
| alignItems: "baseline", | ||
| marginTop: "1.6rem" | ||
| }, | ||
| ".MuiTablePagination-spacer": { | ||
| display: "none" | ||
| }, | ||
| ".MuiTablePagination-displayedRows": { | ||
| marginLeft: "auto" | ||
| } | ||
| }} | ||
| /> | ||
| )} | ||
| </Paper> | ||
| </Box> | ||
| ); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2434,6 +2434,20 @@ | |
| "unarchived": "Form successfully unarchived." | ||
| } | ||
| }, | ||
| "cart_tab": { | ||
| "new_form": "New Form", | ||
| "forms": "forms", | ||
| "code": "Code", | ||
| "name": "Name", | ||
| "add_ons": "Add-ons", | ||
| "discount": "Discount", | ||
| "amount": "Amount", | ||
| "manage_items": "Manage Items", | ||
| "add_form": "Add Form", | ||
| "no_cart": "No cart found.", | ||
| "pay_cc": "pay with credit card or ach", | ||
| "pay_invoice": "pay with invoice" | ||
| }, | ||
|
Comment on lines
+2437
to
+2450
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# First, explore the i18n directory structure
echo "=== Locale files in src/i18n ==="
ls -la src/i18n/ | grep -E "\.(json|js)$"
# Count total locale files
echo "=== Total locale files ==="
fd -e json src/i18n | wc -lRepository: fntechgit/summit-admin Length of output: 542 🏁 Script executed: #!/bin/bash
# Read the exact lines around the cart_tab section
echo "=== Content at lines 2437-2450 in en.json ==="
sed -n '2437,2450p' src/i18n/en.jsonRepository: fntechgit/summit-admin Length of output: 508 🏁 Script executed: #!/bin/bash
# Search for cart_tab in all locale files
echo "=== Files containing 'cart_tab' ==="
rg "cart_tab" src/i18n -l
# Show content of cart_tab in each file
echo -e "\n=== cart_tab definitions across locales ==="
rg -A 12 '"cart_tab"' src/i18nRepository: fntechgit/summit-admin Length of output: 774 🏁 Script executed: #!/bin/bash
# Search for JSON files that might be locale files
echo "=== All JSON files in repo ==="
fd -e json . | grep -iE "(locale|lang|i18n|translation)" | head -20
# Check if there's a locales directory elsewhere
echo -e "\n=== Searching for locale-like directories ==="
fd -type d -iE "(locale|lang|i18n|translation)" .
# Verify all json files in src/i18n
echo -e "\n=== All files in src/i18n ==="
fd . src/i18nRepository: fntechgit/summit-admin Length of output: 396 🏁 Script executed: #!/bin/bash
# Check git history to see if this is a new feature
echo "=== Recent changes to src/i18n/en.json ==="
git log --oneline -10 -- src/i18n/en.json
# Check if cart_tab was recently added
echo -e "\n=== Checking cart_tab presence in git ==="
git log -p --all -S "cart_tab" -- "*.json" | head -50Repository: fntechgit/summit-admin Length of output: 182 🏁 Script executed: #!/bin/bash
# Check if the application uses i18n/internationalization
echo "=== Checking for i18n usage in code ==="
rg -t js -t ts "i18n|i18next|translation|locale" src --max-count=5
# Check package.json for i18n libraries
echo -e "\n=== I18n related dependencies ==="
rg "i18n|i18next|react-intl" package.jsonRepository: fntechgit/summit-admin Length of output: 41358 🏁 Script executed: #!/bin/bash
# Check if there's a build process or config that expects multiple locales
echo "=== Checking for locale config/setup ==="
rg "locale|lang" . --type json -t toml -t yaml -t js --max-count=10
# Look for any comments or documentation about locales
echo -e "\n=== README or docs mentioning locales ==="
fd README . && cat README.md | grep -iA 5 -B 5 "locale\|language\|i18n" || echo "No README found"Repository: fntechgit/summit-admin Length of output: 50437 Normalize capitalization in cart_tab values for UI consistency. The cart_tab strings have inconsistent capitalization: "forms", "pay with credit card or ach", and "pay with invoice" are lowercase while other values use Title Case ("New Form", "Code", "Name", etc.). Standardize to Title Case to match the rest of the object. 🤖 Prompt for AI Agents |
||
| "placeholders": { | ||
| "select_sponsorship": "Select a Sponsorship", | ||
| "sponsorship_type": "Start typing to choose a Tier...", | ||
|
|
@@ -3762,7 +3776,8 @@ | |
| "no_items": "No items found.", | ||
| "rows_per_page": "Rows per page", | ||
| "sorted_desc": "sorted descending", | ||
| "sorted_asc": "sorted ascending" | ||
| "sorted_asc": "sorted ascending", | ||
| "total": "Total" | ||
| }, | ||
| "event_rsvp_list": { | ||
| "name": "Name", | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add quotes around the PURCHASES_API_SCOPES value for consistency and correct parsing.
The value contains space-separated scopes but lacks surrounding quotes, inconsistent with other scope variables in the file (lines 5, 16, 17, 18) and flagged by dotenv-linter. Space-separated values should be quoted to ensure proper dotenv parsing.
🔧 Proposed fix
📝 Committable suggestion
🧰 Tools
🪛 dotenv-linter (4.0.0)
[warning] 15-15: [ValueWithoutQuotes] This value needs to be surrounded in quotes
(ValueWithoutQuotes)
🤖 Prompt for AI Agents