Skip to content

Commit

Permalink
Implement Euros Feedback (#9710)
Browse files Browse the repository at this point in the history
* Add approval step

* change next function for new step

* formatting changes

* don't do any pointer events on the registration overview

* make button group stackable

* remove icons

* string changes
  • Loading branch information
FinnIckler authored Aug 1, 2024
1 parent 6875140 commit af3b2e6
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import updateRegistration from '../api/registration/patch/update_registration';
import { setMessage } from './RegistrationMessage';
import { useDispatch } from '../../../lib/providers/StoreProvider';
import { useConfirm } from '../../../lib/providers/ConfirmProvider';
import RegistrationStatus from './RegistrationStatus';

function updateRegistrationKey(editsAllowed, deadlinePassed) {
if (!editsAllowed && !deadlinePassed) {
Expand Down Expand Up @@ -76,6 +77,7 @@ export default function RegistrationOverview({

return (
<>
<RegistrationStatus registration={registration} competitionInfo={competitionInfo} />
{ !editsAllowed && (
<Message info>
{i18n.t(updateRegistrationKey(editsAllowed, hasRegistrationEditDeadlinePassed))}
Expand All @@ -97,7 +99,7 @@ export default function RegistrationOverview({
{ /* Make sure to keep WCA Event order */}
{events.official
.filter((e) => registration.competing.event_ids.includes(e.id))
.map((e) => (<EventIcon key={e.id} id={e.id} style={{ cursor: 'unset' }} />))}
.map((e) => (<EventIcon key={e.id} id={e.id} hoverable={false} />))}
</FormField>
<FormField />
<FormField>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React from 'react';
import { Checkbox, Icon, Message } from 'semantic-ui-react';
import { Icon, Message } from 'semantic-ui-react';
import i18n from '../../../lib/i18n';
import useCheckboxState from '../../../lib/hooks/useCheckboxState';

function registrationIconByStatus(registrationStatus) {
switch (registrationStatus) {
Expand All @@ -22,12 +21,15 @@ function registrationIconByStatus(registrationStatus) {
// If we add these strings to en.yml immediately, translators will get a notification asking them
// to translate these strings during our test mode deployment. But we aren't even sure whether
// we want to keep these strings. So we hard-code them "for now" (when did that ever go wrong?)
function canIBookPlaneTickets(registrationStatus) {
function canIBookPlaneTickets(registrationStatus, paymentStatus, competitionInfo) {
switch (registrationStatus) {
case 'pending':
return "Don't book your flights and hotel just yet - the organizers still have to manually approve your registration. This can take time.";
if (competitionInfo['using_payment_integrations?'] && paymentStatus !== 'succeeded') {
return 'Your registration will not be approved until you pay for your registration, unless you have a special arrangement with the organizers or you paid through an alternative method.';
}
return "Don't book your flights or hotel just yet - the organizers still have to manually approve your registration. This can take time.";
case 'accepted':
return 'Pack your bags and book your flights - you have a spot at the competition!';
return 'Book your flights and pack your bags - you have a spot at the competition!';
case 'cancelled':
return 'Your registration has been deleted and you will not be competing.';
case 'waiting_list':
Expand All @@ -37,7 +39,7 @@ function canIBookPlaneTickets(registrationStatus) {
}
}

function RegistrationStatusMessage({ registration, showAlternativeDescription }) {
function RegistrationStatusMessage({ registration, competitionInfo }) {
return (
<Message
info={registration.competing.registration_status === 'pending'}
Expand All @@ -56,27 +58,23 @@ function RegistrationStatusMessage({ registration, showAlternativeDescription })
},
)}
</Message.Header>
{showAlternativeDescription && (
<p>
{canIBookPlaneTickets(registration.competing.registration_status)}
</p>
)}
<p>
{canIBookPlaneTickets(
registration.competing.registration_status,
registration.payment?.payment_status,
competitionInfo,
)}
</p>
</Message.Content>
</Message>
);
}

export default function RegistrationStatus({ registration }) {
const [showAlternativeToggle, setAlternativeToggle] = useCheckboxState(true);

export default function RegistrationStatus({ registration, competitionInfo }) {
return (
<>
<Checkbox toggle checked={showAlternativeToggle} onChange={setAlternativeToggle} label="Show alternative status description" />

<RegistrationStatusMessage
registration={registration}
showAlternativeDescription={showAlternativeToggle}
/>
</>
<RegistrationStatusMessage
registration={registration}
competitionInfo={competitionInfo}
/>
);
}
68 changes: 47 additions & 21 deletions app/webpacker/components/RegistrationsV2/Register/StepPanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,37 @@ import RegistrationRequirements from './RegistrationRequirements';
import StripeWrapper from './StripeWrapper';
import i18n from '../../../lib/i18n';
import RegistrationOverview from './RegistrationOverview';
import RegistrationStatus from './RegistrationStatus';
import { hasPassed } from '../../../lib/utils/dates';

const requirementsStepConfig = {
key: 'requirements',
description: 'Accept competition terms',
i18nKey: 'competitions.registration_v2.requirements.title',
component: RegistrationRequirements,
};

const competingStepConfig = {
key: 'competing',
i18nKey: 'competitions.nav.menu.register',
description: 'Choose your events',
component: CompetingStep,
};

const paymentStepConfig = {
key: 'payment',
description: 'Enter billing information',
i18nKey: 'registrations.payment_form.labels.payment_information',
component: StripeWrapper,
};

const registrationOverviewConfig = {
index: 100,
key: 'approval',
description: 'By organization team',
i18nKey: 'competitions.registration_v2.register.approval',
component: RegistrationOverview,
};

const shouldShowCompleted = (isRegistered, hasPaid, key, index) => {
const shouldShowCompleted = (isRegistered, hasPaid, isAccepted, key, index) => {
if (key === paymentStepConfig.key) {
return hasPaid;
}
Expand All @@ -38,20 +45,23 @@ const shouldShowCompleted = (isRegistered, hasPaid, key, index) => {
if (key === requirementsStepConfig.key) {
return index > 0;
}
if (key === registrationOverviewConfig.key) {
return isAccepted;
}
};

const shouldBeDisabled = (isRegistered, key, activeIndex, index, competitionInfo) => {
const shouldBeDisabled = (hasPaid, key, activeIndex, index, competitionInfo) => {
const hasRegistrationEditDeadlinePassed = hasPassed(
competitionInfo.event_change_deadline_date ?? competitionInfo.start_date,
);
const editsAllowed = competitionInfo.allow_registration_edits
&& !hasRegistrationEditDeadlinePassed;

if (key === paymentStepConfig.key) {
return !isRegistered && index > activeIndex;
return !hasPaid && index > activeIndex;
}
if (key === competingStepConfig.key) {
return index > activeIndex && !editsAllowed;
return index > activeIndex || !editsAllowed;
}
if (key === requirementsStepConfig.key) {
return activeIndex !== 0;
Expand All @@ -68,22 +78,28 @@ export default function StepPanel({
connectedAccountId,
}) {
const isRegistered = Boolean(registration) && registration.competing.registration_status !== 'cancelled';
const registrationSucceeded = isRegistered && registration.competing.registration_status === 'accepted';
const isAccepted = isRegistered && registration.competing.registration_status === 'accepted';
const hasPaid = registration?.payment.payment_status === 'succeeded';
const registrationFinished = hasPaid || (isRegistered && !competitionInfo['using_payment_integrations?']);

const steps = useMemo(() => {
const stepList = [requirementsStepConfig, competingStepConfig];
if (competitionInfo['using_payment_integrations?']) {
return [requirementsStepConfig, competingStepConfig, paymentStepConfig];
stepList.push(paymentStepConfig);
}

return [requirementsStepConfig, competingStepConfig];
}, [competitionInfo]);
if (isRegistered) {
stepList.push(registrationOverviewConfig);
}
return stepList;
}, [competitionInfo, isRegistered]);

const [activeIndex, setActiveIndex] = useState(() => {
// Don't show payment panel if a user was accepted (for people with waived payment)
if (registrationFinished || registrationSucceeded) {
return registrationOverviewConfig.index;
if (registrationFinished || isAccepted) {
return steps.findIndex(
(step) => step === (registrationOverviewConfig),
);
}
// If the user has not paid but refreshes the page, we want to display the paymentStep again
return steps.findIndex(
Expand All @@ -94,20 +110,30 @@ export default function StepPanel({
? RegistrationOverview : steps[activeIndex].component;
return (
<>
{ isRegistered && (
<RegistrationStatus registration={registration} />
)}
<Step.Group fluid ordered stackable="tablet">
{steps.map((stepConfig, index) => (
<Step
key={stepConfig.key}
active={activeIndex === index}
completed={shouldShowCompleted(isRegistered, hasPaid, stepConfig.key, activeIndex)}
disabled={shouldBeDisabled(isRegistered, stepConfig.key, activeIndex, index, competitionInfo)}
completed={shouldShowCompleted(
isRegistered,
hasPaid,
isAccepted,
stepConfig.key,
activeIndex,
)}
disabled={shouldBeDisabled(
hasPaid,
stepConfig.key,
activeIndex,
index,
competitionInfo,
)}
onClick={() => setActiveIndex(index)}
>
<Step.Content>
<Step.Title>{i18n.t(stepConfig.i18nKey)}</Step.Title>
<Step.Description>{stepConfig.description}</Step.Description>
</Step.Content>
</Step>
))}
Expand All @@ -131,10 +157,10 @@ export default function StepPanel({
if (overwrites?.goBack) {
return oldActiveIndex - 1;
}
if (oldActiveIndex === steps.length - 1) {
return registrationOverviewConfig.index;
}
if (oldActiveIndex === registrationOverviewConfig.index) {
const registrationOverviewIndex = steps.findIndex(
(step) => step === registrationOverviewConfig,
);
if (oldActiveIndex === registrationOverviewIndex) {
return steps.findIndex(
(step) => step === competingStepConfig,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export default function RegistrationActions({
};

return (
<Button.Group>
<Button.Group className="stackable">
<Button
onClick={() => {
csvExport(
Expand All @@ -108,7 +108,6 @@ export default function RegistrationActions({
href={`mailto:?bcc=${selectedEmails}`}
id="email-selected"
target="_blank"
className="btn btn-info selected-registrations-actions"
rel="noreferrer"
>
<Icon name="envelope" />
Expand Down
5 changes: 3 additions & 2 deletions app/webpacker/components/wca/EventIcon.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import classnames from 'classnames';

/* eslint react/jsx-props-no-spreading: "off" */
function EventIcon({
id, className, size = undefined, ...other
id, className, size = undefined, hoverable = true, ...other
}) {
const resetHoverable = hoverable ? {} : { pointerEvents: 'none' };
return (
<span
{...other}
className={classnames('cubing-icon', `event-${id}`, className)}
style={{ fontSize: size }}
style={{ fontSize: size, ...resetHoverable }}
/>
);
}
Expand Down
1 change: 1 addition & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1826,6 +1826,7 @@ en:
comment: "Additional comments to the organizers"
until: "You can update your registration until %{date}"
passed: "You can no longer update your registration"
approval: "Approval"
view_registration: "View Registration"
editing_disabled: "Registration editing is disabled for this competition"
registration_status:
Expand Down

0 comments on commit af3b2e6

Please sign in to comment.