Skip to content

feat: move show dashboard to mui#967

Open
priscila-moneo wants to merge 2 commits into
masterfrom
feature/move-show-dashboard-mui
Open

feat: move show dashboard to mui#967
priscila-moneo wants to merge 2 commits into
masterfrom
feature/move-show-dashboard-mui

Conversation

@priscila-moneo

@priscila-moneo priscila-moneo commented Jun 9, 2026

Copy link
Copy Markdown

ref: https://app.clickup.com/t/9014802374/86babejhm

image

Summary by CodeRabbit

  • New Features

    • Enhanced summit dashboard with improved date range display and registration statistics (orders, active tickets)
  • Refactor

    • Updated dashboard to modern Material-UI layout and component architecture
  • Style

    • Added light gray background color option to theme palette

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR modernizes the summit dashboard by converting it from a legacy class component to a functional MUI-based layout, adding reusable dashboard components, extending the theme with a new background color, and inserting dashboard section localization strings.

Changes

Dashboard UI Redesign

Layer / File(s) Summary
Theme background color and style overrides
src/components/CustomTheme.js
Adds palette.background.light_gray (#eaeaea) and updates MUI style override callback parameters to use local theme alias t for typography.subtitle2 and components.MuiAlert.standardInfo color references.
Reusable dashboard UI components
src/pages/summits/components/dashboard-section.js, src/pages/summits/components/summit-dashboard-stat.js, src/pages/summits/components/dashboard-stat-section.js, src/pages/summits/components/summit-dashboard-date-range.js
Introduces four new dashboard components: DashboardSection (card/box container), SummitDashboardStat (labeled stat display), DashboardStatSection (grouped stat grid), and SummitDashboardDateRange (timezone-formatted date range formatter). Each includes propTypes and defaultProps validation.
SummitDashboardPage: functional conversion and Redux integration
src/pages/summits/summit-dashboard-page.js
Converts SummitDashboardPage from class-based to functional component with useEffect hook for registration data fetching; renders MUI breadcrumb, tabs, and date-range/stat sections; updates propTypes to require getRegistrationData and add totalOrders/totalActiveTickets; updates Redux mapStateToProps to supply registration totals and the connected action.
Dashboard localization strings
src/i18n/en.json
Adds eight dashboard section translation keys for new dashboard labels and section titles.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • martinquiroga-exo
  • smarcet

Poem

🐰 A dashboard reborn with hooks and MUI grace,
New components compose the dashboard's place,
From class to function, a theme so light-gray,
With stats and date ranges in elegant display,
Summit admin shines brighter every day!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat: move show dashboard to mui' directly and accurately describes the main change—converting the summit dashboard from its previous implementation to Material-UI components.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/move-show-dashboard-mui

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed due to a network error.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/pages/summits/summit-dashboard-page.js`:
- Around line 54-58: The useEffect currently calls fetchRegistrationData()
unconditionally on mount causing premature requests before summit context is
ready; update the useEffect (the hook that calls fetchRegistrationData) to only
invoke fetchRegistrationData when currentSummit.id and
currentSummit.time_zone?.name are present—either by adding those values to the
effect dependency array and checking them inside the effect or by gating the
call with an early return inside the effect (referencing useEffect,
fetchRegistrationData, and currentSummit).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3dbeee96-9399-43d7-b662-a19ca0afc281

📥 Commits

Reviewing files that changed from the base of the PR and between 8a7aee3 and 74702da.

📒 Files selected for processing (7)
  • src/components/CustomTheme.js
  • src/i18n/en.json
  • src/pages/summits/components/summit-dashboard-date-range.js
  • src/pages/summits/components/summit-dashboard-section-header.js
  • src/pages/summits/components/summit-dashboard-stat.js
  • src/pages/summits/summit-dashboard-page.js
  • src/styles/summit-dashboard-page.less
💤 Files with no reviewable changes (1)
  • src/styles/summit-dashboard-page.less

Comment thread src/pages/summits/summit-dashboard-page.js Outdated
Comment thread src/components/CustomTheme.js Outdated
background: {
light: "#F7F7F9"
light: "#F7F7F9",
secondary: "#eaeaea"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

these two colors are almost exactly the same, are we sure we want this distinction ?

Image

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

in case we do want the two, name it something more meaningful like for example "light_gray"

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The new color added to pallete (secondary) is for this headers
image

The other one (light) is for pages background
image

I will improve the name.

import RemoveIcon from "@mui/icons-material/Remove";
import moment from "moment-timezone";

function formatDate(ts, tzName) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

please use the method in utils/methods.js

import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";

function SummitDashboardSectionHeader({ children }) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This component should be named DashboardSection - since its already inside summit dir , and take two props: title and children , then group everything inside a Box .

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Not addressed

<Card elevation={0}>
<CardHeader title={T.translate("dashboard.dates")} />
<Divider />
<SummitDashboardSectionHeader>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

so this would be a DashboardSection

tzName={tz}
/>
{currentSummit.selection_plans.map((sp) => (
<Box key={`sp_${sp.id}`}>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

These would be DashboardSections

</div>
);
}
<Card elevation={0}>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

These cards repeat a lot, can we put them in a separate component that takes an array of touples {title, stat} ?

Signed-off-by: Priscila Moneo <priscila_moneo@hotmail.com.ar>
@priscila-moneo priscila-moneo force-pushed the feature/move-show-dashboard-mui branch from 74702da to 0d70957 Compare June 10, 2026 20:20

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/pages/summits/components/summit-dashboard-date-range.js (1)

8-8: 💤 Low value

Verify the double space in DATE_FORMAT is intentional.

The format string has two spaces between the date and time components: "YYYY/MM/DD hh:mm A". If this is unintentional, it should be corrected for consistency.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/summits/components/summit-dashboard-date-range.js` at line 8, The
DATE_FORMAT constant currently reads "YYYY/MM/DD  hh:mm A" and contains a double
space between the date and time; verify whether the double space is intentional
and if not, change the constant DATE_FORMAT to use a single space ("YYYY/MM/DD
hh:mm A") so formatting is consistent across usages (search for DATE_FORMAT in
summit-dashboard-date-range.js and update its value accordingly).
src/pages/summits/components/dashboard-section.js (1)

20-27: ⚡ Quick win

Consider reusing SummitDashboardSectionHeader to avoid duplication.

Lines 22-24 duplicate the exact header implementation from SummitDashboardSectionHeader (Box with background.gray, padding, and Typography). Consider importing and using that component here instead of reimplementing it.

♻️ Proposed refactor to reuse existing component
+import SummitDashboardSectionHeader from "./summit-dashboard-section-header";

 function DashboardSection({ title, children, variant }) {
   if (variant === "card") {
     return (
       <Card elevation={0}>
         <CardHeader title={title} />
         <Divider />
         {children}
       </Card>
     );
   }

   return (
     <Box>
-      <Box sx={{ bgcolor: "background.gray", px: 2, py: 2 }}>
-        <Typography variant="body2">{title}</Typography>
-      </Box>
+      <SummitDashboardSectionHeader>{title}</SummitDashboardSectionHeader>
       {children}
     </Box>
   );
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/summits/components/dashboard-section.js` around lines 20 - 27, The
header Box in dashboard-section.js duplicates SummitDashboardSectionHeader;
import SummitDashboardSectionHeader and replace the manual Box block (the Box
with sx={{ bgcolor: "background.gray", px: 2, py: 2 }} and inner Typography)
with <SummitDashboardSectionHeader title={title} /> (or the component's expected
prop) so the section uses the shared SummitDashboardSectionHeader component and
removes duplicated markup.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/pages/summits/components/dashboard-section.js`:
- Around line 30-38: DashboardSection.propTypes currently restricts variant to
oneOf(["card"]) while DashboardSection.defaultProps sets variant to undefined,
causing PropTypes warnings; update the prop-type definition for variant to allow
both "card" and undefined (e.g., include null/undefined or make it optional) or
remove the oneOf restriction so runtime behavior matches validation, and ensure
DashboardSection.defaultProps still defines variant as undefined if you want the
non-card default.

In `@src/pages/summits/components/dashboard-stat-section.js`:
- Around line 13-28: The code assumes each group has items which can cause
runtime errors and invalid grid sizes for empty or non-dividing lengths; update
the rows.map callback to skip empty groups (if (group.length === 0) return
null), compute a safe integer column size with something like const size =
Math.max(1, Math.floor(GRID_COLUMNS / group.length)), and derive a robust key
for the fragment using a fallback (e.g., const key = group[0]?.title ||
`group-${i}`) so SummitDashboardStat/Grid2 rendering won't throw or produce
Infinity/non-integer sizes.

---

Nitpick comments:
In `@src/pages/summits/components/dashboard-section.js`:
- Around line 20-27: The header Box in dashboard-section.js duplicates
SummitDashboardSectionHeader; import SummitDashboardSectionHeader and replace
the manual Box block (the Box with sx={{ bgcolor: "background.gray", px: 2, py:
2 }} and inner Typography) with <SummitDashboardSectionHeader title={title} />
(or the component's expected prop) so the section uses the shared
SummitDashboardSectionHeader component and removes duplicated markup.

In `@src/pages/summits/components/summit-dashboard-date-range.js`:
- Line 8: The DATE_FORMAT constant currently reads "YYYY/MM/DD  hh:mm A" and
contains a double space between the date and time; verify whether the double
space is intentional and if not, change the constant DATE_FORMAT to use a single
space ("YYYY/MM/DD hh:mm A") so formatting is consistent across usages (search
for DATE_FORMAT in summit-dashboard-date-range.js and update its value
accordingly).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 59f218f7-3df4-4e70-849c-f2fd109b2b1e

📥 Commits

Reviewing files that changed from the base of the PR and between 74702da and 0d70957.

📒 Files selected for processing (9)
  • src/components/CustomTheme.js
  • src/i18n/en.json
  • src/pages/summits/components/dashboard-section.js
  • src/pages/summits/components/dashboard-stat-section.js
  • src/pages/summits/components/summit-dashboard-date-range.js
  • src/pages/summits/components/summit-dashboard-section-header.js
  • src/pages/summits/components/summit-dashboard-stat.js
  • src/pages/summits/summit-dashboard-page.js
  • src/styles/summit-dashboard-page.less
💤 Files with no reviewable changes (1)
  • src/styles/summit-dashboard-page.less
✅ Files skipped from review due to trivial changes (1)
  • src/i18n/en.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/pages/summits/components/summit-dashboard-section-header.js
  • src/pages/summits/components/summit-dashboard-stat.js
  • src/pages/summits/summit-dashboard-page.js

Comment on lines +30 to +38
DashboardSection.propTypes = {
title: PropTypes.string.isRequired,
children: PropTypes.node.isRequired,
variant: PropTypes.oneOf(["card"])
};

DashboardSection.defaultProps = {
variant: undefined
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix PropTypes inconsistency for variant.

Line 33 restricts variant to oneOf(["card"]), but Line 37 defaults it to undefined. This creates a PropTypes validation warning since undefined is not in the allowed values. The component logic (Line 10) correctly handles undefined by rendering the non-card variant.

🐛 Proposed fix

Option 1: Remove the oneOf restriction if only "card" is needed as an explicit signal:

 DashboardSection.propTypes = {
   title: PropTypes.string.isRequired,
   children: PropTypes.node.isRequired,
-  variant: PropTypes.oneOf(["card"])
+  variant: PropTypes.string
 };

Option 2: Make the PropTypes match the runtime behavior by allowing both "card" and undefined:

 DashboardSection.propTypes = {
   title: PropTypes.string.isRequired,
   children: PropTypes.node.isRequired,
-  variant: PropTypes.oneOf(["card"])
+  variant: PropTypes.oneOf(["card", undefined])
 };
📝 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
DashboardSection.propTypes = {
title: PropTypes.string.isRequired,
children: PropTypes.node.isRequired,
variant: PropTypes.oneOf(["card"])
};
DashboardSection.defaultProps = {
variant: undefined
};
DashboardSection.propTypes = {
title: PropTypes.string.isRequired,
children: PropTypes.node.isRequired,
variant: PropTypes.string
};
DashboardSection.defaultProps = {
variant: undefined
};
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/summits/components/dashboard-section.js` around lines 30 - 38,
DashboardSection.propTypes currently restricts variant to oneOf(["card"]) while
DashboardSection.defaultProps sets variant to undefined, causing PropTypes
warnings; update the prop-type definition for variant to allow both "card" and
undefined (e.g., include null/undefined or make it optional) or remove the oneOf
restriction so runtime behavior matches validation, and ensure
DashboardSection.defaultProps still defines variant as undefined if you want the
non-card default.

Comment thread src/pages/summits/components/dashboard-stat-section.js
Comment thread src/components/CustomTheme.js Outdated
background: {
light: "#F7F7F9"
light: "#F7F7F9",
gray: "#eaeaea"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@priscila-moneo please rename this to the proposed name "light_gray"

import RemoveIcon from "@mui/icons-material/Remove";
import { parseAndFormat } from "../../../utils/methods";

const DATE_FORMAT = "YYYY/MM/DD hh:mm A";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

this is not standard US date format, and constants should go in constants.js

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Ok, format is following Figma design:
image

import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";

function SummitDashboardSectionHeader({ children }) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Not addressed

};
this.onCollapseChange = this.onCollapseChange.bind(this);
}
if (!currentSummit.id || !currentSummit.time_zone?.name) return null;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

So if timezone is not set you won't show the entire dashboard? seems too harsh

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Also check on currentSummit.id is redundant since its already guarded in SummitIdLayout

Signed-off-by: Priscila Moneo <priscila_moneo@hotmail.com.ar>
@priscila-moneo priscila-moneo force-pushed the feature/move-show-dashboard-mui branch from 0d70957 to 2a28aa4 Compare June 11, 2026 16:54

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/pages/summits/components/summit-dashboard-date-range.js`:
- Around line 27-31: The component calls parseAndFormat(String(startTs), "X",
DATETIME_FORMAT, "UTC", tzName) with tzName possibly undefined which causes
moment-timezone to treat .tz(undefined) as a getter; update the call site in the
SummitDashboardDateRange component (or alternatively inside parseAndFormat) to
normalize tzName to "UTC" when it is missing but not coerce valid falsy values
like 0 — e.g. compute a safeTz = (tzName === undefined ? "UTC" : tzName) and
pass safeTz to parseAndFormat so moment-timezone receives an explicit timezone
string.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 038d3385-2170-4db2-b78a-0e701bdf29cf

📥 Commits

Reviewing files that changed from the base of the PR and between 0d70957 and 2a28aa4.

📒 Files selected for processing (5)
  • src/components/CustomTheme.js
  • src/pages/summits/components/dashboard-section.js
  • src/pages/summits/components/dashboard-stat-section.js
  • src/pages/summits/components/summit-dashboard-date-range.js
  • src/pages/summits/summit-dashboard-page.js
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/pages/summits/components/dashboard-stat-section.js
  • src/components/CustomTheme.js
  • src/pages/summits/summit-dashboard-page.js
  • src/pages/summits/components/dashboard-section.js

Comment on lines +27 to +31
{parseAndFormat(String(startTs), "X", DATETIME_FORMAT, "UTC", tzName)}
</Typography>
<RemoveIcon sx={{ mx: 2, fontSize: 16 }} />
<Typography variant="body1">
{parseAndFormat(String(endTs), "X", DATETIME_FORMAT, "UTC", tzName)}

Copy link
Copy Markdown

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

🌐 Web query:

In moment-timezone 0.5.33, what is the behavior of momentObj.tz(undefined)? Does it return a moment instance or act like the getter overload?

💡 Result:

In moment-timezone 0.5.33, calling momentObj.tz(undefined) acts as the getter for the timezone [1][2]. It does not return a new moment instance; instead, it returns the timezone name (a string) assigned to the moment instance, or undefined if no timezone has been set [1][2][3]. When the.tz method is called with no arguments or with undefined, it functions as a getter, allowing you to retrieve the current timezone associated with that specific moment object [1][2][3]. This is distinct from the setter behavior, which occurs when a string (timezone name) is passed as the first argument, in which case the method returns the moment instance itself to allow for method chaining [1][4].

Citations:


Fix timezone handling when tzName is omitted

tzName defaults to undefined, but parseAndFormat is still called with it. In moment-timezone, momentObj.tz(undefined) uses the getter overload (returns a timezone name / undefined) rather than setting a timezone, so this can lead to incorrect formatting and potential runtime issues depending on how parseAndFormat uses the result.

Update the component (or parseAndFormat) to normalize tzName to "UTC" when it’s missing (and keep the guard from treating 0 as “empty”).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/summits/components/summit-dashboard-date-range.js` around lines 27
- 31, The component calls parseAndFormat(String(startTs), "X", DATETIME_FORMAT,
"UTC", tzName) with tzName possibly undefined which causes moment-timezone to
treat .tz(undefined) as a getter; update the call site in the
SummitDashboardDateRange component (or alternatively inside parseAndFormat) to
normalize tzName to "UTC" when it is missing but not coerce valid falsy values
like 0 — e.g. compute a safeTz = (tzName === undefined ? "UTC" : tzName) and
pass safeTz to parseAndFormat so moment-timezone receives an explicit timezone
string.

<Typography variant="body2">{label}</Typography>
</Box>
<Typography variant="body1">
{parseAndFormat(String(startTs), "X", DATETIME_FORMAT, "UTC", tzName)}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

this method is intended to be used with a string date like "12/12/1983" , you have a number that is epoch . You should be using something like formatDate in utils/methods or epochToMomentTimezone in uicore

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