Skip to content
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

Include registration statuses to event items #5230

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions app/components/EventItem/RegistrationStatusTag.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { Flex, Icon } from '@webkom/lego-bricks';
import { AlarmClock } from 'lucide-react';
import Tag from 'app/components/Tags/Tag';
import Time from 'app/components/Time';
import { useIsLoggedIn } from 'app/reducers/auth';
import { EventStatusType } from 'app/store/models/Event';
import utilities from 'app/styles/utilities.css';
import type { ListEvent } from 'app/store/models/Event';

type Props = {
event: ListEvent;
isRegistrationOpen: boolean;
isRegistrationSameYear: boolean;
};

const RegistrationStatusTag = ({
event,
isRegistrationOpen,
isRegistrationSameYear,
}: Props) => {
const loggedIn = useIsLoggedIn();

const getRegistrationStatus = () => {
if (
event.eventStatusType === EventStatusType.OPEN ||
event.eventStatusType === EventStatusType.INFINITE
) {
return 'Åpent for alle';
}

if (event.isAdmitted) {
return 'Du er påmeldt';
}

if (event.userReg && event.eventStatusType === EventStatusType.NORMAL) {
return 'Du er på venteliste';
}

if (!!event.activationTime) {
return (
<Flex alignItems="center" gap="var(--spacing-xs)">
<Icon
iconNode={<AlarmClock />}
size={14}
className={utilities.hiddenOnMobile}
/>
<span>
Påmelding {isRegistrationOpen ? 'åpnet' : 'åpner'}{' '}
<Time
time={event.activationTime}
format={isRegistrationSameYear ? 'D. MMM HH:mm' : 'll HH:mm'}
/>
</span>
</Flex>
);
}

return 'Påmelding er ikke bestemt';
};

const getTagColor = () => {
if (event.isAdmitted) {
return 'green';
}

if (event.userReg && event.eventStatusType === EventStatusType.NORMAL) {
return 'orange';
}

if (
event.eventStatusType === EventStatusType.OPEN ||
event.eventStatusType === EventStatusType.INFINITE
) {
return 'red';
}

return isRegistrationOpen ? 'red' : 'gray';
};

if (!loggedIn) {
return null;
}

return <Tag tag={getRegistrationStatus()} color={getTagColor()} />;
};

export default RegistrationStatusTag;
95 changes: 53 additions & 42 deletions app/components/EventItem/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Flex, Icon, Image } from '@webkom/lego-bricks';
import {
AlarmClock,
Calendar,
CalendarClock,
CircleAlert,
CircleCheckBig,
Clock,
Timer,
} from 'lucide-react';
import moment from 'moment-timezone';
import { Link } from 'react-router-dom';
import Pill from 'app/components/Pill';
import Tag from 'app/components/Tags/Tag';
Expand All @@ -16,6 +16,7 @@ import Tooltip from 'app/components/Tooltip';
import { colorForEventType } from 'app/routes/events/utils';
import { EventStatusType } from 'app/store/models/Event';
import { eventAttendanceAbsolute } from 'app/utils/eventStatus';
import RegistrationStatusTag from './RegistrationStatusTag';
import styles from './styles.module.css';
import type { CompleteEvent, ListEvent } from 'app/store/models/Event';
import type { ReactNode } from 'react';
Expand All @@ -33,27 +34,34 @@ const getRegistrationIconOptions = (
): RegistrationIconOptions => {
const { isAdmitted, eventStatusType } = event;

if (isAdmitted) {
return {
icon: <CircleCheckBig />,
color: 'var(--success-color)',
tooltip: 'Du er påmeldt',
};
}

switch (eventStatusType) {
case EventStatusType.NORMAL:
case EventStatusType.INFINITE:
if (isAdmitted) {
return {
icon: <CircleCheckBig />,
color: 'var(--success-color)',
tooltip: 'Du er påmeldt',
} satisfies RegistrationIconOptions;
}
return {
icon: <Timer />,
color: 'var(--color-orange-6)',
tooltip: 'Du er på ventelisten',
} satisfies RegistrationIconOptions;
};
case EventStatusType.OPEN:
return {
icon: <CircleCheckBig />,
color: 'var(--success-color)',
tooltip: 'Åpent for alle',
};
default:
return {
icon: <CircleAlert />,
color: 'var(--danger-color)',
tooltip: 'Det har oppstått en feil',
} satisfies RegistrationIconOptions;
};
}
};

Expand Down Expand Up @@ -85,24 +93,6 @@ const TimeStamp = ({ event }: TimeStampProps) => {
);
};

const TimeStartAndRegistration = ({ event }: TimeStampProps) => (
<>
<Flex alignItems="center" gap="var(--spacing-sm)">
<Icon iconNode={<CalendarClock />} size={18} />
<Time time={event.startTime} format="ll HH:mm" />
</Flex>

{!!event.activationTime && (
<Flex alignItems="center" gap="var(--spacing-sm)">
<Tooltip content="Påmelding åpner">
<Icon iconNode={<AlarmClock />} size={18} />
</Tooltip>
<Time time={event.activationTime} format="ll HH:mm" />
</Flex>
)}
</>
);

const RegistrationIcon = ({ event }: TimeStampProps) => {
const registrationIconOptions = getRegistrationIconOptions(event);
return (
Expand All @@ -127,6 +117,12 @@ const EventItem = ({
showTags = true,
eventStyle,
}: EventItemProps): ReactNode => {
const isRegistrationOpen = moment(event.activationTime).isBefore(moment());
// No need to show the year if it is the same year
const isRegistrationSameYear =
moment().year() === moment(event.activationTime).year();
const isEventSameYear = moment().year() === moment(event.startTime).year();

switch (eventStyle) {
case 'extra-compact':
return (
Expand Down Expand Up @@ -205,12 +201,20 @@ const EventItem = ({
}}
className={styles.eventItem}
>
<Flex column gap="var(--spacing-xs)" className="secondaryFontColor">
<div>
<h3 className={styles.eventItemTitle}>{event.title}</h3>
{event.totalCapacity > 0 && <Attendance event={event} />}
</div>
<TimeStartAndRegistration event={event} />
<Flex column gap="var(--spacing-sm)" className="secondaryFontColor">
<h3 className={styles.eventItemTitle}>{event.title}</h3>
{event.totalCapacity != null && event.totalCapacity > 0 && (
norbye marked this conversation as resolved.
Show resolved Hide resolved
<div>
<Attendance event={event} />
</div>
)}
<Flex alignItems="center" gap="var(--spacing-sm)">
<Icon iconNode={<CalendarClock />} size={16} />
<Time
time={event.startTime}
format={isEventSameYear ? 'D. MMM HH:mm' : 'll HH:mm'}
/>
</Flex>
{showTags && (
<Flex wrap>
{event.tags.map((tag, index) => (
Expand All @@ -220,14 +224,21 @@ const EventItem = ({
)}
</Flex>

<Flex className={styles.companyLogo}>
{event.cover && (
<Image
alt="Forsidebilde"
src={event.cover}
placeholder={event.coverPlaceholder}
/>
)}
<Flex column alignItems="flex-end" gap="var(--spacing-sm)">
<Flex className={styles.companyLogo}>
{event.cover && (
<Image
alt="Forsidebilde"
src={event.cover}
placeholder={event.coverPlaceholder}
/>
)}
</Flex>
<RegistrationStatusTag
event={event}
isRegistrationOpen={isRegistrationOpen}
isRegistrationSameYear={isRegistrationSameYear}
/>
</Flex>
</Link>
);
Expand Down
12 changes: 6 additions & 6 deletions app/components/EventItem/styles.module.css
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
.eventItem {
min-height: 50px;
padding: var(--spacing-xs);
padding-left: var(--spacing-md);
padding: var(--spacing-sm) var(--spacing-md);
border-left: 4px solid transparent;
display: flex;
justify-content: space-between;
align-items: center;
gap: var(--spacing-md);
line-height: 1.3;
border-top-right-radius: var(--border-radius-lg);
border-bottom-right-radius: var(--border-radius-lg);
color: var(--lego-font-color);
transition: background-color var(--easing-fast);

&:hover {
Expand All @@ -30,15 +32,14 @@
color: var(--lego-font-color);
margin: 0;
word-break: break-word;
margin-bottom: var(--spacing-sm);
}

.eventTime {
color: var(--secondary-font-color);
}

.companyLogo {
width: 120px;
width: 140px;
display: flex;
justify-content: center;
align-items: center;
Expand All @@ -51,11 +52,10 @@
}

.companyLogo img {
min-width: 120px;
min-width: 140px;
max-height: 80px;
object-fit: contain;
background: white;
margin: var(--spacing-sm) var(--spacing-md) var(--spacing-sm) 0;
}

.companyLogoCompact img {
Expand Down
3 changes: 2 additions & 1 deletion app/components/Tags/Tag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Flex, Icon } from '@webkom/lego-bricks';
import cx from 'classnames';
import { Link } from 'react-router-dom';
import styles from './Tag.module.css';
import type { ReactNode } from 'react';

const tagColors = [
'red',
Expand All @@ -18,7 +19,7 @@ const tagColors = [
export type TagColors = (typeof tagColors)[number];

type Props = {
tag: string;
tag: string | ReactNode;
icon?: string;
iconSize?: number;
color?: TagColors;
Expand Down
5 changes: 3 additions & 2 deletions app/routes/events/components/EventList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import EmptyState from 'app/components/EmptyState';
import EventItem from 'app/components/EventItem';
import { CheckBox, SelectInput } from 'app/components/Form/';
import { EventTime } from 'app/models';
import { useCurrentUser } from 'app/reducers/auth';
import { useCurrentUser, useIsLoggedIn } from 'app/reducers/auth';
import { selectAllEvents } from 'app/reducers/events';
import { selectPaginationNext } from 'app/reducers/selectors';
import { useAppDispatch, useAppSelector } from 'app/store/hooks';
Expand Down Expand Up @@ -134,6 +134,7 @@ const EventList = () => {
);

const icalToken = useCurrentUser()?.icalToken;
const loggedIn = useIsLoggedIn();

const fetchQuery = {
date_after: moment().format('YYYY-MM-DD'),
Expand Down Expand Up @@ -162,7 +163,7 @@ const EventList = () => {
query: fetchQuery,
}),
),
[],
[loggedIn],
);

const fetchMore = () =>
Expand Down
6 changes: 3 additions & 3 deletions app/routes/users/components/UserProfile/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import { GroupMemberships } from './GroupMemberships';
import Penalties from './Penalties';
import PhotoConsents from './PhotoConsents';
import styles from './UserProfile.module.css';
import type { ListEventWithUserRegistration } from 'app/store/models/Event';
import type { ListEvent } from 'app/store/models/Event';
import type { PublicGroup } from 'app/store/models/Group';
import type { CurrentUser, PublicUserWithGroups } from 'app/store/models/User';
import type { ExclusifyUnion } from 'app/types';
Expand Down Expand Up @@ -74,7 +74,7 @@ const UserProfile = () => {
}),
);
const upcomingEvents = useAppSelector((state) =>
selectAllEvents<ListEventWithUserRegistration>(state, {
selectAllEvents<ListEvent>(state, {
pagination: upcomingEventsPagination,
}),
);
Expand All @@ -87,7 +87,7 @@ const UserProfile = () => {
}),
);
const previousEvents = useAppSelector((state) =>
selectAllEvents<ListEventWithUserRegistration>(state, {
selectAllEvents<ListEvent>(state, {
pagination: previousEventsPagination,
}),
).filter((e) => e.userReg);
Expand Down
Loading
Loading