Skip to content

Commit

Permalink
Introduce "too late" presence option to event attendees
Browse files Browse the repository at this point in the history
Neither ion-icons or font-awesome had a turtle icon, so I extracted one
from Lucide (which we're planning on migrating to). I'm very open to
design suggestions, as I'm not sure what I feel about this. The padding
feels a bit much, so I might refactor the Icon component - but that will
probably have to wait.
  • Loading branch information
ivarnakken committed Mar 7, 2024
1 parent a5098cc commit b999072
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 45 deletions.
8 changes: 7 additions & 1 deletion app/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,13 @@ type EventBase = {
};

export type Permission = string;
export type EventRegistrationPresence = 'PRESENT' | 'NOT_PRESENT' | 'UNKNOWN';

export type EventRegistrationPresence =
| 'PRESENT'
| 'TOO_LATE'
| 'NOT_PRESENT'
| 'UNKNOWN';

export type LEGACY_EventRegistrationPhotoConsent =
| 'PHOTO_NOT_CONSENT'
| 'PHOTO_CONSENT'
Expand Down
39 changes: 22 additions & 17 deletions app/routes/events/components/EventAdministrate/Administrate.css
Original file line number Diff line number Diff line change
Expand Up @@ -62,40 +62,45 @@
color: var(--color-green-7);
}

.greenIcon {
font-size: 1.4em;
color: var(--success-color);

&:hover {
color: var(--color-green-7);
}
}

.orangePill {
background-color: var(--color-orange-2);
color: var(--color-orange-7);
}

.questionIcon {
font-size: 1.4em;
.bluePill {
background-color: var(--color-blue-2);
color: var(--color-blue-6);
}

.greenIcon {
color: var(--success-color);

ion-icon {
color: var(--success-color);
}
}

.tooLateIcon {
width: 34px;
height: 34px;
padding: 0.375rem;
cursor: pointer;
border-radius: 50%;

&:hover {
color: var(--color-blue-7);
background-color: var(--additive-background);
}
}

.bluePill {
background-color: var(--color-blue-2);
.questionIcon ion-icon {
color: var(--color-blue-6);
}

.redIcon {
font-size: 1.4em;
color: var(--danger-color);

&:hover {
color: var(--color-red-7);
ion-icon {
color: var(--danger-color);
}
}

Expand Down
98 changes: 73 additions & 25 deletions app/routes/events/components/EventAdministrate/AttendeeElements.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type TooltipIconProps = {
onClick?: (arg0: React.SyntheticEvent<any>) => unknown;
content: string;
transparent?: boolean;
iconName?: string;
iconClass: string;
disabled?: boolean;
};
Expand All @@ -45,18 +46,27 @@ export const TooltipIcon = ({
onClick,
content,
transparent,
iconName,
iconClass,
disabled = false,
}: TooltipIconProps) => {
const classNames = cx(iconClass, transparent && styles.transparent);

return (
<Tooltip content={content}>
<button
className={cx(transparent && styles.transparent)}
onClick={onClick}
disabled={disabled}
>
<i className={iconClass} />
</button>
<Tooltip content={content} className={styles.presenceIcon}>
{iconName ? (
<Icon
name={iconName}
className={classNames}
onClick={onClick}
disabled={disabled}
size={22}
/>
) : (
<button onClick={onClick} disabled={disabled}>
<i className={classNames} />
</button>
)}
</Tooltip>
);
};
Expand All @@ -66,28 +76,63 @@ export const PresenceIcons = ({ presence, registrationId }: PresenceProps) => {
const dispatch = useAppDispatch();

return (
<Flex justifyContent="center">
<Flex alignItems="center" justifyContent="center">
<TooltipIcon
content="Til stede"
iconClass={cx('fa fa-check', styles.greenIcon)}
iconName="checkmark"
iconClass={styles.greenIcon}
transparent={presence !== 'PRESENT'}
onClick={() =>
eventId &&
dispatch(updatePresence(eventId, registrationId, 'PRESENT'))
}
/>
<Tooltip content="For sent til stede">
<div
className={cx(
styles.tooLateIcon,
presence !== 'TOO_LATE' && styles.transparent
)}
onClick={() => {
eventId &&
dispatch(updatePresence(eventId, registrationId, 'TOO_LATE'));
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="22"
height="22"
viewBox="0 0 24 24"
fill="none"
stroke="var(--color-orange-6)"
strokeWidth="1.4"
strokeLinecap="round"
strokeLinejoin="round"
>
<path d="m12 10 2 4v3a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1v-3a8 8 0 1 0-16 0v3a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1v-3l2-4h4Z" />
<path d="M4.82 7.9 8 10" />
<path d="M15.18 7.9 12 10" />
<path d="M16.93 10H20a2 2 0 0 1 0 4H2" />
</svg>
</div>
</Tooltip>
<TooltipIcon
content="Ukjent"
iconClass={cx('fa fa-question-circle', styles.questionIcon)}
iconClass={styles.questionIcon}
iconName="help-outline"
transparent={presence !== 'UNKNOWN'}
onClick={() =>
eventId &&
dispatch(updatePresence(eventId, registrationId, 'UNKNOWN'))
}
/>
<TooltipIcon
content="Ikke til stede"
iconClass={cx('fa fa-times', styles.redIcon)}
iconClass={styles.redIcon}
iconName="close-outline"
transparent={presence !== 'NOT_PRESENT'}
onClick={() =>
eventId &&
dispatch(updatePresence(eventId, registrationId, 'NOT_PRESENT'))
}
/>
Expand All @@ -103,27 +148,29 @@ export const StripeStatus = ({
const dispatch = useAppDispatch();

return (
<Flex justifyContent="center">
<Flex alignItems="center" justifyContent="center">
<TooltipIcon
content="Betalt via Stripe"
iconClass={cx('fa fa-cc-stripe', styles.greenIcon)}
iconClass={cx('fa fa-cc-stripe', styles.greenIcon, styles.stripeIcon)}
transparent={paymentStatus !== 'succeeded'}
disabled
/>
<TooltipIcon
content="Betalt manuelt"
transparent={paymentStatus !== 'manual'}
iconClass={cx('fa fa-money', styles.greenIcon)}
iconName="cash-outline"
iconClass={styles.greenIcon}
onClick={() =>
dispatch(updatePayment(eventId, registrationId, 'manual'))
eventId && dispatch(updatePayment(eventId, registrationId, 'manual'))
}
/>
<TooltipIcon
content="Ikke betalt"
transparent={['manual', 'succeeded'].includes(paymentStatus)}
iconClass={cx('fa fa-times', styles.redIcon)}
iconName="close-outline"
iconClass={styles.redIcon}
onClick={() =>
dispatch(updatePayment(eventId, registrationId, 'failed'))
eventId && dispatch(updatePayment(eventId, registrationId, 'failed'))
}
/>
</Flex>
Expand All @@ -143,13 +190,14 @@ export const Unregister = ({ fetching, registration }: UnregisterProps) => {
title="Bekreft avregistrering"
message={`Er du sikker på at du vil melde av "${registration.user.fullName}"?`}
onConfirm={() => {
dispatch(
unregister({
eventId,
registrationId: registration.id,
admin: true,
})
);
eventId &&
dispatch(
unregister({
eventId,
registrationId: registration.id,
admin: true,
})
);
}}
closeOnConfirm
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ const ConsentIcons = ({
photoConsents
);
return (
<Flex justifyContent="center" gap={5}>
<Flex alignItems="center" justifyContent="center">
<TooltipIcon
content={consentMessage(webConsent)}
iconClass={iconClass(webConsent)}
Expand Down Expand Up @@ -254,7 +254,7 @@ export const RegisteredTable = ({
},
},
{
title: 'Til stede',
title: 'Oppmøte',
dataIndex: 'presence',
visible: showPresence,
render: (presence, registration) => {
Expand Down

0 comments on commit b999072

Please sign in to comment.