Skip to content
Open
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
11 changes: 9 additions & 2 deletions src/components/atoms/dropdown/dropdownHeader/DropdownHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,21 @@ interface Props extends React.HtmlHTMLAttributes<HTMLDivElement> {
title: string;
}

const DropdownHeader: React.FC<Props> = ({ title, children, ...rest }) => {
const DropdownHeader: React.FC<Props> = ({
title,
children,
className,
...rest
}) => {
const [expanded, setExpanded] = useState(false);

const onExpand = () => setExpanded(!expanded);

return (
<div className={styles.container}>
<div className={styles.box} {...rest}>
<div
className={className ? `${styles.box} ${className}` : styles.box}
{...rest}>
<div className={styles.base} onClick={onExpand}>
<div className={styles.item2}>
<p>{title}</p>
Expand Down
9 changes: 8 additions & 1 deletion src/components/atoms/textfield/Textfield.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,19 @@ const TextField: React.FC<Props> = ({
value,
defaultValue,
type,
placeholder,
...rest
}) => {
const [isFocused, setIsFocused] = useState(false);
const [defaultInput, setDefaultInput] = useState(defaultValue);
const styleLabel = () => {
return (
value || defaultInput || isFocused || type === 'date' || type === 'time'
value ||
defaultInput ||
isFocused ||
type === 'date' ||
type === 'time' ||
placeholder
);
};

Expand Down Expand Up @@ -60,6 +66,7 @@ const TextField: React.FC<Props> = ({
defaultValue={defaultValue}
value={value}
type={type}
placeholder={placeholder}
onFocus={(e) => {
setIsFocused(true);
onFocus && onFocus(e);
Expand Down
173 changes: 155 additions & 18 deletions src/components/molecules/event/eventBody/EventBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ import ToggleButton from 'components/atoms/toggleButton/ToggleButton';
import { Text } from '@chakra-ui/react';
import { ListItem, List, ListIcon } from '@chakra-ui/react';
import { MdCheckCircle, MdBlock } from 'react-icons/md';
import { getJoinedParticipants, updateEvent, uploadEventPicture } from 'api';
import {
getJoinedParticipants,
updateEvent,
uploadEventPicture,
getMemberAssociatedWithToken,
} from 'api';
import {
addressValidator,
dateValidator,
Expand Down Expand Up @@ -49,6 +54,10 @@ export const EditEvent: React.FC<{ event: Event; setEdit: () => void }> = ({
const [file, setFile] = useState<File | undefined>();
const { addToast } = useToast();

const prioritizedRegistrationTimeDate = event.prioritizedRegistrationDate
? new Date(event.prioritizedRegistrationDate)
: undefined;

const initalValue = {
title: event.title,
description: event.description,
Expand All @@ -62,6 +71,14 @@ export const EditEvent: React.FC<{ event: Event; setEdit: () => void }> = ({
':' +
registrationTimeDate.getMinutes()
: '',
prioritizedRegisterDate:
event.prioritizedRegistrationDate?.split('T')[0] ?? '',
prioritizedRegisterTime: prioritizedRegistrationTimeDate
? prioritizedRegistrationTimeDate.getHours() +
':' +
prioritizedRegistrationTimeDate.getMinutes()
: '',
prioritizedYears: event.prioritizedYears?.join(',') ?? '',
// maxParticipants is set to "" when event does not have maxParticipants
// since "" is the init value for fields["maxParticipants"]
maxParticipants: event.maxParticipants?.toString() ?? '',
Expand Down Expand Up @@ -115,6 +132,29 @@ export const EditEvent: React.FC<{ event: Event; setEdit: () => void }> = ({
? null
: fields['registerDate'].value + ' ' + fields['registerTime'].value,
}),
...(fields['prioritizedRegisterDate']?.value +
'T' +
fields['prioritizedRegisterTime']?.value !==
initalValue.prioritizedRegisterDate +
'T' +
initalValue.prioritizedRegisterTime && {
prioritizedRegistrationDate:
fields['prioritizedRegisterDate'].value === ''
? null
: fields['prioritizedRegisterDate'].value +
' ' +
fields['prioritizedRegisterTime'].value,
}),
...(fields['prioritizedYears']?.value !==
initalValue.prioritizedYears && {
prioritizedYears:
fields['prioritizedYears'].value === ''
? null
: fields['prioritizedYears'].value
.split(',')
.map((year: string) => parseInt(year.trim()))
.filter((year: number) => !isNaN(year)),
}),
...(toggleFood !== event.food && {
food: toggleFood,
}),
Expand Down Expand Up @@ -289,6 +329,28 @@ export const EditEvent: React.FC<{ event: Event; setEdit: () => void }> = ({
value={fields['registerTime'].value ?? ''}
onChange={onFieldChange}
/>
<Text>Prioritert registrering åpner:</Text>
<TextField
name={'prioritizedRegisterDate'}
label={'Dato'}
type={'date'}
value={fields['prioritizedRegisterDate']?.value ?? ''}
onChange={onFieldChange}
/>
<TextField
name={'prioritizedRegisterTime'}
label={'Tid'}
type={'time'}
value={fields['prioritizedRegisterTime']?.value ?? ''}
onChange={onFieldChange}
/>
<TextField
name={'prioritizedYears'}
label={'Prioriterte årskull (kommaseparert)'}
placeholder={'2022,2023,2024'}
value={fields['prioritizedYears']?.value ?? ''}
onChange={onFieldChange}
/>
<div className={styles.toggleWrapper}>
<ToggleButton
initValue={toggleFood}
Expand Down Expand Up @@ -337,16 +399,37 @@ export const EditEvent: React.FC<{ event: Event; setEdit: () => void }> = ({
);
};

const validJoin = (role: RoleOptions, eventRegString: string | undefined) => {
if (eventRegString === undefined) {
return false;
}
const validJoin = (role: RoleOptions, event: Event, userClassof?: string) => {
if (role === Roles.admin) {
return true;
}

const now = new Date();
const openingDate = new Date(eventRegString);
return now >= openingDate;

// Check if user is eligible for prioritized registration
if (
userClassof &&
event.prioritizedRegistrationDate &&
event.prioritizedYears
) {
const userYear = parseInt(userClassof);
const isPrioritizedUser = event.prioritizedYears.includes(userYear);

if (isPrioritizedUser) {
const prioritizedDate = new Date(event.prioritizedRegistrationDate);
if (now >= prioritizedDate) {
return true;
}
}
}

// Check regular registration date
if (event.registrationOpeningDate) {
const regularDate = new Date(event.registrationOpeningDate);
return now >= regularDate;
}

return false;
};

export const EventInfo: React.FC<{ event: Event; role: RoleOptions }> = ({
Expand All @@ -355,8 +438,9 @@ export const EventInfo: React.FC<{ event: Event; role: RoleOptions }> = ({
}) => {
const [participantsHeader, setParticipantHeader] = useState('');
const [participantsText, setParticipantText] = useState('');
const canJoinEvent = validJoin(role, event.registrationOpeningDate);
const [userClassof, setUserClassof] = useState<string | undefined>();
const { authenticated } = useContext(AuthenticateContext);
const canJoinEvent = validJoin(role, event, userClassof);

// sets correct header and text based on what the user should see
function getParticipantsText(
Expand Down Expand Up @@ -398,6 +482,22 @@ export const EventInfo: React.FC<{ event: Event; role: RoleOptions }> = ({
}
}, [event.eid, event?.maxParticipants]);

useEffect(() => {
const fetchUserInfo = async () => {
if (authenticated && role !== Roles.admin) {
try {
const userInfo = await getMemberAssociatedWithToken();
setUserClassof(userInfo.classof);
} catch (error) {
// If we can't get user info, user will see regular registration logic
setUserClassof(undefined);
}
}
};

fetchUserInfo();
}, [authenticated, role]);

useEffect(() => {
// only fetch participants list when the list is actually used
// the list/number of participants should only be displayed for admins and events with no cap
Expand Down Expand Up @@ -425,21 +525,58 @@ export const EventInfo: React.FC<{ event: Event; role: RoleOptions }> = ({
<EventButton id={event.eid} onClick={getNumberOfParticipants} />
) : (
<div>
{event.registrationOpeningDate ? (
<p style={{ fontWeight: 'lighter' }}>
{' '}
{transformDate(new Date(event.registrationOpeningDate))}
</p>
{event.registrationOpeningDate ||
event.prioritizedRegistrationDate ? (
<div>
{/* Show prioritized registration date if user is eligible */}
{userClassof &&
event.prioritizedRegistrationDate &&
event.prioritizedYears?.includes(parseInt(userClassof)) ? (
<div>
{event.registrationOpeningDate && (
<p className={styles.registrationDate}>
{transformDate(
new Date(event.registrationOpeningDate)
)}
</p>
)}
<Text
fontSize="0.75rem"
className={styles.prioritizedInfo}>
For årskull {event.prioritizedYears.join(', ')}:{' '}
{transformDate(
new Date(event.prioritizedRegistrationDate)
)}
</Text>
</div>
) : event.registrationOpeningDate ? (
<p className={styles.registrationDate}>
{transformDate(new Date(event.registrationOpeningDate))}
</p>
) : (
<p> Påmelding kommer </p>
)}
</div>
) : (
<p> Påmelding kommer </p>
)}
</div>
)}
{role === 'admin' && event.registrationOpeningDate && (
<Text fontSize="0.75rem" style={{ fontStyle: 'italic' }}>
Åpner for alle{' '}
{transformDate(new Date(event.registrationOpeningDate))}
</Text>
{role === 'admin' && (
<div>
{event.prioritizedRegistrationDate && event.prioritizedYears && (
<Text fontSize="0.75rem" className={styles.prioritizedInfo}>
Åpner for årskull {event.prioritizedYears.join(', ')}{' '}
{transformDate(new Date(event.prioritizedRegistrationDate))}
</Text>
)}
{event.registrationOpeningDate && (
<Text fontSize="0.75rem" className={styles.adminInfo}>
Åpner for alle{' '}
{transformDate(new Date(event.registrationOpeningDate))}
</Text>
)}
</div>
)}
<p>Sted</p>
{event.address}
Expand Down
13 changes: 13 additions & 0 deletions src/components/molecules/event/eventBody/eventBody.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,19 @@ input[type='time']::-webkit-calendar-picker-indicator {
gap: 0.25rem;
}

.registrationDate {
font-weight: lighter;
}

.prioritizedInfo {
font-style: italic;
color: #4caf50;
}

.adminInfo {
font-style: italic;
}

@mixin mobile_base {
.contentContainer {
display: inline;
Expand Down
Loading