Skip to content

Conversation

@tomrndom
Copy link

@tomrndom tomrndom commented Oct 15, 2025

ref: https://app.clickup.com/t/86b736jyw

Signed-off-by: Tomás Castillo tcastilloboireau@gmail.com

Summary by CodeRabbit

  • New Features

    • Improved QR parsing and validation for badge check-in with clearer validation flow and error alerts.
  • Bug Fixes

    • Check-in success now shows attendee full name and email.
    • Prevented unintended form submission when toggling camera mode.
    • Replaced generic QR errors with localized/translatable messages.

✏️ Tip: You can customize this high-level summary in your review settings.

Signed-off-by: Tomás Castillo <tcastilloboireau@gmail.com>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds badge data extraction functionality to display proper information in the SweetAlert popup when checking in badges via QR code scanning. The change replaces a previously used qrValid variable with a new utility function that parses badge QR codes.

  • Introduces a new formatBadgeQR utility function to parse QR codes into structured badge data
  • Updates the badge check-in page to use the new function for displaying badge holder information in the success popup
  • Adds a minor improvement by setting the type attribute on a button element

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
src/utils/methods.js Adds new formatBadgeQR function to parse badge QR codes and extract badge prefix, ticket number, email, and full name
src/pages/attendees/badge-checkin-page.js Updates badge check-in flow to use formatBadgeQR for extracting and displaying badge data in the success popup; adds type="button" attribute to camera switch button

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

setScanning(true);
checkInBadge(data)
.then(() => {
const badgeData = formatBadgeQR(data, currentSummit);
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The formatBadgeQR function can return false when the QR code format is invalid, but this code doesn't handle that case. Attempting to access properties like fullName and email on false will cause a runtime error. Add validation to check if badgeData is falsy before accessing its properties, and handle the error case appropriately.

Suggested change
const badgeData = formatBadgeQR(data, currentSummit);
const badgeData = formatBadgeQR(data, currentSummit);
if (!badgeData) {
Swal.fire(
"Error",
"Invalid badge QR code format. Please try again.",
"warning"
);
return;
}

Copilot uses AI. Check for mistakes.
@smarcet
Copy link

smarcet commented Jan 5, 2026

@rabbit review

@fntechgit fntechgit deleted a comment from Copilot AI Jan 5, 2026
export const formatBadgeQR = (code, summit) => {
const qrCodeArray = code.split(summit.qr_registry_field_delimiter);

if (qrCodeArray.length > TWO && qrCodeArray[0] === summit.badge_qr_prefix) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here u check for TWO

  1. its does not provided any readability
  2. u are accessing 4 elements

so lets change TWO by const QR_ELEMENTS_SIZE = 4
and check that qrCodeArray.length =>QR_ELEMENTS_SIZE

Copy link

@smarcet smarcet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tomrndom please review comments

import { formatBadgeQR } from "../../utils/methods";
import styles from "../../styles/badge-checkin-page.module.less";

const BadgeCheckinPage = ({ match, currentSummit, checkInBadge }) => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

current summit is never used removed it if not used

…badge data

Signed-off-by: Tomás Castillo <tcastilloboireau@gmail.com>
@coderabbitai
Copy link

coderabbitai bot commented Jan 5, 2026

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

Added badge QR parsing: a new formatBadgeQR utility and BADGE_QR_MINIMUM_EXPECTED_FIELDS constant; the badge check-in page now parses QR strings, validates parsed badge data after check-in, shows localized error messages on invalid QR, and prevents unintended form submission from the camera toggle button. (49 words)

Changes

Cohort / File(s) Summary
QR Parsing Constants & Utils
src/utils/constants.js, src/utils/methods.js
Added BADGE_QR_MINIMUM_EXPECTED_FIELDS (3) to constants. Added export const formatBadgeQR(code, summit) which parses QR strings using summit.qr_registry_field_delimiter and summit.badge_qr_prefix, returning { badgePrefix, ticketNumber, email, fullName } or null when fields are insufficient.
Badge Check-In Integration
src/pages/attendees/badge-checkin-page.js
Imported and used formatBadgeQR; after checkInBadge success, validate parsed badgeData and abort with a translated error alert if falsy; updated success message to use badgeData.fullName and badgeData.email; replaced hardcoded QR error texts with i18n strings; added type="button" to camera environment toggle to avoid form submit.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I hopped to a scanner, nose all a-twitch,
Bits of a badge fell out, neat and rich.
Prefixes, names, emails in a row,
I validated gently before they could go.
Hooray—checked in, with a tiny rabbit bow! 🥕✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding badge data extraction and validation to display in the SweetAlert popup during badge check-in.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (3)
src/utils/constants.js (1)

228-228: Fix typo in constant name and adjust value to match usage.

Two issues with this constant:

  1. Typo: "MINIMUN" should be "MINIMUM"
  2. Incorrect value: The constant is set to 2, but formatBadgeQR checks qrCodeArray.length > BADGE_QR_MINIMUN_EXPECTED_FIELDS (i.e., > 2 or >= 3) and then accesses qrCodeArray[3], which requires at least 4 elements. This mismatch can cause undefined values when accessing optional fields.

Based on the past review comments, the recommendation is to set this to 4 and use >= comparison, or rename to clarify intent.

🔎 Proposed fix
-export const BADGE_QR_MINIMUN_EXPECTED_FIELDS = 2;
+export const BADGE_QR_MINIMUM_EXPECTED_FIELDS = 4;

Then update the comparison in formatBadgeQR (src/utils/methods.js) to use >=:

-  if (
-    qrCodeArray.length > BADGE_QR_MINIMUN_EXPECTED_FIELDS &&
-    qrCodeArray[0] === summit.badge_qr_prefix
-  ) {
+  if (
+    qrCodeArray.length >= BADGE_QR_MINIMUM_EXPECTED_FIELDS &&
+    qrCodeArray[0] === summit.badge_qr_prefix
+  ) {

Also update the import in both files to use the corrected name.

src/utils/methods.js (2)

33-34: Update constant name after typo fix.

Once the typo in the constant name is fixed in constants.js (MINIMUNMINIMUM), update this import accordingly.


509-525: Add defensive null checks and fix array access logic.

This function has several issues:

  1. Missing null checks: No validation that summit, summit.qr_registry_field_delimiter, or summit.badge_qr_prefix exist before accessing them, which could cause runtime errors.
  2. Missing type validation: No check that code is a string before calling .split().
  3. Logic bug: The condition checks qrCodeArray.length > BADGE_QR_MINIMUN_EXPECTED_FIELDS (i.e., > 2), but then accesses qrCodeArray[3]. If length is 3, accessing index 3 returns undefined. The check should be >= 4 to safely access all four indices.
🔎 Proposed fix with defensive checks
 export const formatBadgeQR = (code, summit) => {
+  // Validate inputs
+  if (
+    typeof code !== "string" ||
+    !summit ||
+    !summit.qr_registry_field_delimiter ||
+    !summit.badge_qr_prefix
+  ) {
+    return null;
+  }
+
   const qrCodeArray = code.split(summit.qr_registry_field_delimiter);
 
   if (
-    qrCodeArray.length > BADGE_QR_MINIMUN_EXPECTED_FIELDS &&
+    qrCodeArray.length >= BADGE_QR_MINIMUM_EXPECTED_FIELDS &&
     qrCodeArray[0] === summit.badge_qr_prefix
   ) {
     return {
       badgePrefix: qrCodeArray[0],
       ticketNumber: qrCodeArray[1],
       email: qrCodeArray[2] || "",
       fullName: qrCodeArray[3] || ""
     };
   }
 
   return null;
 };
🧹 Nitpick comments (1)
src/pages/attendees/badge-checkin-page.js (1)

34-43: Consider validating badge format before check-in API call.

The current flow calls checkInBadge(data) first, then validates the badge format with formatBadgeQR. If the badge format is invalid, the user sees an error message even though the server-side check-in may have succeeded (if the server has different validation rules).

Consider validating the badge format before making the API call to fail fast and provide clearer error messages:

🔎 Proposed refactor to validate before API call
   const handleCheckIn = (data) => {
     if (data && !scanning) {
+      const badgeData = formatBadgeQR(data, currentSummit);
+
+      if (!badgeData) {
+        Swal.fire(
+          T.translate("general.error"),
+          T.translate("badge_checkin.error_invalid_qr"),
+          "warning"
+        );
+        return;
+      }
+
       setScanning(true);
       checkInBadge(data)
         .then(() => {
-          const badgeData = formatBadgeQR(data, currentSummit);
-
-          if (!badgeData) {
-            Swal.fire(
-              T.translate("general.error"),
-              T.translate("badge_checkin.error_invalid_qr"),
-              "warning"
-            );
-            return;
-          }
-
           Swal.fire(
             T.translate("badge_checkin.checked_in"),
             `${badgeData.fullName} (${badgeData.email}) checked in!`,
             "success"
           );
         })
         .finally(() => {
           setScanning(false);
         });
     }
   };

Note: Only apply this refactor if the server-side validation in checkInBadge and client-side validation in formatBadgeQR are meant to be identical. If the server accepts a broader set of QR formats, keep the current flow but fix the validation logic in formatBadgeQR.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 12aad02 and aa64ee8.

📒 Files selected for processing (3)
  • src/pages/attendees/badge-checkin-page.js
  • src/utils/constants.js
  • src/utils/methods.js
🧰 Additional context used
🧬 Code graph analysis (2)
src/utils/methods.js (3)
src/reducers/tickets/ticket-list-reducer.js (1)
  • summit (51-51)
src/reducers/tickets/ticket-reducer.js (1)
  • summit (73-73)
src/utils/constants.js (2)
  • BADGE_QR_MINIMUN_EXPECTED_FIELDS (228-228)
  • BADGE_QR_MINIMUN_EXPECTED_FIELDS (228-228)
src/pages/attendees/badge-checkin-page.js (1)
src/utils/methods.js (2)
  • formatBadgeQR (509-525)
  • formatBadgeQR (509-525)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: build
  • GitHub Check: build
  • GitHub Check: build
  • GitHub Check: build
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (2)
src/pages/attendees/badge-checkin-page.js (2)

59-60: Good use of internationalization for error messages.

Replacing hardcoded error text with translated strings improves maintainability and i18n support.


92-92: Good addition of explicit button type.

Adding type="button" prevents accidental form submission behavior, which is a best practice for buttons that don't submit forms.

Signed-off-by: Tomás Castillo <tcastilloboireau@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Fix all issues with AI Agents 🤖
In @src/utils/constants.js:
- Line 228: The constant BADGE_QR_MINIMUM_EXPECTED_FIELDS is set to 3 but
formatBadgeQR reads qrCodeArray[0..3]; update BADGE_QR_MINIMUM_EXPECTED_FIELDS
to 4 so the validation (using BADGE_QR_MINIMUM_EXPECTED_FIELDS) guarantees
indices 0 through 3 exist before formatBadgeQR accesses them, ensuring
consistent validation for the fourth field.

In @src/utils/methods.js:
- Around line 509-525: formatBadgeQR currently assumes inputs exist and accesses
qrCodeArray[3] while only checking for BADGE_QR_MINIMUM_EXPECTED_FIELDS (should
be 4); update the function to first validate that `code` and `summit` are
defined and that `summit.qr_registry_field_delimiter` and
`summit.badge_qr_prefix` are non-empty strings, then split using the delimiter
and check that qrCodeArray.length >= BADGE_QR_MINIMUM_EXPECTED_FIELDS (ensure
BADGE_QR_MINIMUM_EXPECTED_FIELDS is set to 4) before indexing; when building the
return object, trim string fields and validate that `ticketNumber` and `email`
are non-empty (return null or a clear error result if required) so no
out-of-bounds or empty critical fields propagate downstream.
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aa64ee8 and 61ad8e3.

📒 Files selected for processing (3)
  • src/pages/attendees/badge-checkin-page.js
  • src/utils/constants.js
  • src/utils/methods.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/pages/attendees/badge-checkin-page.js
🧰 Additional context used
🧬 Code graph analysis (1)
src/utils/methods.js (1)
src/utils/constants.js (2)
  • BADGE_QR_MINIMUM_EXPECTED_FIELDS (228-228)
  • BADGE_QR_MINIMUM_EXPECTED_FIELDS (228-228)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: build
  • GitHub Check: build
  • GitHub Check: build
  • GitHub Check: build
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (1)
src/utils/methods.js (1)

33-34: LGTM!

The import statement correctly includes the new constant.

"OVERFLOW"
];

export const BADGE_QR_MINIMUM_EXPECTED_FIELDS = 3;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, find and examine the constant definition
cat -n src/utils/constants.js | grep -A 2 -B 2 "BADGE_QR_MINIMUM_EXPECTED_FIELDS"

Repository: fntechgit/summit-admin

Length of output: 141


🏁 Script executed:

# Search for all usages of BADGE_QR_MINIMUM_EXPECTED_FIELDS
rg "BADGE_QR_MINIMUM_EXPECTED_FIELDS" -n -B 3 -A 3

Repository: fntechgit/summit-admin

Length of output: 969


🏁 Script executed:

# Find and examine the formatBadgeQR function
rg "formatBadgeQR" -n -A 20 src/utils/methods.js

Repository: fntechgit/summit-admin

Length of output: 560


Constant value doesn't align with array access pattern in formatBadgeQR.

The constant is set to 3, but formatBadgeQR in src/utils/methods.js accesses qrCodeArray[0], qrCodeArray[1], qrCodeArray[2], and qrCodeArray[3] (lines 517-520). The validation check at line 513 only guarantees qrCodeArray.length >= 3, which ensures indices 0-2 exist. Accessing qrCodeArray[3] without validating it first creates an inconsistency—the || "" fallback prevents crashes but doesn't properly validate the 4th field.

Change the constant to 4 to ensure all accessed array indices are validated before use.

-export const BADGE_QR_MINIMUM_EXPECTED_FIELDS = 3;
+export const BADGE_QR_MINIMUM_EXPECTED_FIELDS = 4;
🤖 Prompt for AI Agents
In @src/utils/constants.js around line 228, The constant
BADGE_QR_MINIMUM_EXPECTED_FIELDS is set to 3 but formatBadgeQR reads
qrCodeArray[0..3]; update BADGE_QR_MINIMUM_EXPECTED_FIELDS to 4 so the
validation (using BADGE_QR_MINIMUM_EXPECTED_FIELDS) guarantees indices 0 through
3 exist before formatBadgeQR accesses them, ensuring consistent validation for
the fourth field.

Comment on lines +509 to +525
export const formatBadgeQR = (code, summit) => {
const qrCodeArray = code.split(summit.qr_registry_field_delimiter);

if (
qrCodeArray.length >= BADGE_QR_MINIMUM_EXPECTED_FIELDS &&
qrCodeArray[0] === summit.badge_qr_prefix
) {
return {
badgePrefix: qrCodeArray[0],
ticketNumber: qrCodeArray[1],
email: qrCodeArray[2] || "",
fullName: qrCodeArray[3] || ""
};
}

return null;
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add input validation and ensure array bounds are properly checked.

Several concerns with this function:

  1. Array access mismatch: The function checks qrCodeArray.length >= BADGE_QR_MINIMUM_EXPECTED_FIELDS (which is 3) but accesses qrCodeArray[3]. This doesn't align with the maintainer's previous feedback requesting a check for 4 elements.

  2. Missing null/undefined checks: The function doesn't validate that code, summit.qr_registry_field_delimiter, or summit.badge_qr_prefix are defined before use, which could cause runtime errors.

  3. Empty field validation: Consider validating that critical fields like ticketNumber and email are not empty strings after parsing, as empty values may cause issues downstream when displaying badge data in the SweetAlert popup.

Based on past review comments from smarcet.

🔎 Proposed improvements
 export const formatBadgeQR = (code, summit) => {
+  if (!code || !summit?.qr_registry_field_delimiter || !summit?.badge_qr_prefix) {
+    return null;
+  }
+
   const qrCodeArray = code.split(summit.qr_registry_field_delimiter);
 
   if (
     qrCodeArray.length >= BADGE_QR_MINIMUM_EXPECTED_FIELDS &&
     qrCodeArray[0] === summit.badge_qr_prefix
   ) {
+    const ticketNumber = qrCodeArray[1]?.trim();
+    const email = qrCodeArray[2]?.trim() || "";
+    const fullName = qrCodeArray[3]?.trim() || "";
+
+    // Validate that required fields are not empty
+    if (!ticketNumber) {
+      return null;
+    }
+
     return {
       badgePrefix: qrCodeArray[0],
-      ticketNumber: qrCodeArray[1],
-      email: qrCodeArray[2] || "",
-      fullName: qrCodeArray[3] || ""
+      ticketNumber,
+      email,
+      fullName
     };
   }
 
   return null;
 };

Note: Also ensure BADGE_QR_MINIMUM_EXPECTED_FIELDS is set to 4 as discussed in the constants.js review.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const formatBadgeQR = (code, summit) => {
const qrCodeArray = code.split(summit.qr_registry_field_delimiter);
if (
qrCodeArray.length >= BADGE_QR_MINIMUM_EXPECTED_FIELDS &&
qrCodeArray[0] === summit.badge_qr_prefix
) {
return {
badgePrefix: qrCodeArray[0],
ticketNumber: qrCodeArray[1],
email: qrCodeArray[2] || "",
fullName: qrCodeArray[3] || ""
};
}
return null;
};
export const formatBadgeQR = (code, summit) => {
if (!code || !summit?.qr_registry_field_delimiter || !summit?.badge_qr_prefix) {
return null;
}
const qrCodeArray = code.split(summit.qr_registry_field_delimiter);
if (
qrCodeArray.length >= BADGE_QR_MINIMUM_EXPECTED_FIELDS &&
qrCodeArray[0] === summit.badge_qr_prefix
) {
const ticketNumber = qrCodeArray[1]?.trim();
const email = qrCodeArray[2]?.trim() || "";
const fullName = qrCodeArray[3]?.trim() || "";
// Validate that required fields are not empty
if (!ticketNumber) {
return null;
}
return {
badgePrefix: qrCodeArray[0],
ticketNumber,
email,
fullName
};
}
return null;
};
🤖 Prompt for AI Agents
In @src/utils/methods.js around lines 509-525, formatBadgeQR currently assumes
inputs exist and accesses qrCodeArray[3] while only checking for
BADGE_QR_MINIMUM_EXPECTED_FIELDS (should be 4); update the function to first
validate that `code` and `summit` are defined and that
`summit.qr_registry_field_delimiter` and `summit.badge_qr_prefix` are non-empty
strings, then split using the delimiter and check that qrCodeArray.length >=
BADGE_QR_MINIMUM_EXPECTED_FIELDS (ensure BADGE_QR_MINIMUM_EXPECTED_FIELDS is set
to 4) before indexing; when building the return object, trim string fields and
validate that `ticketNumber` and `email` are non-empty (return null or a clear
error result if required) so no out-of-bounds or empty critical fields propagate
downstream.

@smarcet smarcet merged commit e32a4a4 into master Jan 5, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants