From e40c67719dda5a989f0498a62c27bc72454aa9d2 Mon Sep 17 00:00:00 2001 From: FinnIckler Date: Sun, 29 Oct 2023 10:00:36 -0400 Subject: [PATCH] Move custom components to Semantic (#294) * Move Competition Box to Semantic * Make PermissionsMessage more flexible * Move RegistrationRequirements to Semantic * Move Home Info Box to Semantic * Move registration requirements to accordion * Add periods to Registration Requirements * Delete unncessary css * Make text slightly bigger * Move Processing to Modal * Make Tabs not overflow * Extract Logo out of Information and put it in the corner --- Frontend/src/api/auth/get_permissions.ts | 4 - Frontend/src/api/types.d.ts | 1 + Frontend/src/pages/home/index.jsx | 205 +++++++++--------- Frontend/src/pages/home/index.module.scss | 63 +----- .../register/components/CompetingStep.jsx | 2 +- .../pages/register/components/Processing.jsx | 15 +- .../components/RegistrationRequirements.jsx | 201 +++++++++++++---- .../register/components/panel.module.scss | 4 - .../components/processing.module.scss | 5 - .../components/requirements.module.scss | 15 +- Frontend/src/pages/register/index.jsx | 16 +- Frontend/src/pages/register/index.module.scss | 20 -- .../registration_administration/index.jsx | 5 +- .../src/pages/registration_edit/index.jsx | 5 +- Frontend/src/ui/Competition.jsx | 161 ++++++++------ Frontend/src/ui/Tabs.jsx | 1 + Frontend/src/ui/competition.module.scss | 8 - .../src/ui/messages/permissionMessage.jsx | 7 +- Frontend/src/ui/tabs.module.scss | 3 + 19 files changed, 384 insertions(+), 357 deletions(-) diff --git a/Frontend/src/api/auth/get_permissions.ts b/Frontend/src/api/auth/get_permissions.ts index 6ad032cd..7bd423e9 100644 --- a/Frontend/src/api/auth/get_permissions.ts +++ b/Frontend/src/api/auth/get_permissions.ts @@ -15,7 +15,3 @@ export async function getPermissions(): Promise { } return getPermissionsMock() } - -// TODO: move these to I18n -export const CAN_ADMINISTER_COMPETITIONS = 'Can Administer Competitions' -export const CAN_ATTEND_COMPETITIONS = 'Can attend Competitions' diff --git a/Frontend/src/api/types.d.ts b/Frontend/src/api/types.d.ts index e41c36df..d8e1fa7e 100644 --- a/Frontend/src/api/types.d.ts +++ b/Frontend/src/api/types.d.ts @@ -29,6 +29,7 @@ interface CompetitionInfo { 'on_the_spot_registration': boolean 'on_the_spot_entry_fee_lowest_denomination': string 'extra_registration_requirements': string + 'guests_entry_fee_lowest_denomination': number 'url': string 'website': string 'short_name': string diff --git a/Frontend/src/pages/home/index.jsx b/Frontend/src/pages/home/index.jsx index cb15bdc8..d3a3865d 100644 --- a/Frontend/src/pages/home/index.jsx +++ b/Frontend/src/pages/home/index.jsx @@ -1,41 +1,33 @@ import { UiIcon } from '@thewca/wca-components' import { marked } from 'marked' import moment from 'moment' -import React, { useContext, useState } from 'react' -import { Button } from 'semantic-ui-react' +import React, { useContext } from 'react' +import { Container, Grid, Header, Segment } from 'semantic-ui-react' import { CompetitionContext } from '../../api/helper/context/competition_context' import RegistrationRequirements from '../register/components/RegistrationRequirements' import styles from './index.module.scss' export default function HomePage() { const { competitionInfo } = useContext(CompetitionContext) - const [showAllRequirements, setShowAllRequirements] = useState(false) return ( -
-
-
Registration Requirements:
-
[INSERT ORGANIZER MESSAGE REGARDING REQUIREMENTS]
- {showAllRequirements && } -
- -
+ +
+
{competitionInfo.information && ( -
-
Information:
+
+
Information:
)} -
-
Registration Period:
-
+
+ Registration Period: + {new Date(competitionInfo.registration_open) < new Date() ? `Registration opened ${moment( competitionInfo.registration_open @@ -45,98 +37,101 @@ export default function HomePage() { : `Registration will open ${moment( competitionInfo.registration_open ).calendar()}`} -
-
-
-
- Date: - {moment(competitionInfo.start_date).format('ll')} -
-
- Start Time: - XX:XX PM -
-
- City: - {competitionInfo.city}, {competitionInfo.country_iso2} -
-
- Venue: - -
    -
  • - Address: - {competitionInfo.venue_address} -
  • + + + + + +
    Date
    +
    City
    +
    Venue
    +
    Address
    {competitionInfo.venue_details && ( -
  • - Details: - {competitionInfo.venue_details} -
  • +
    Details
    )} -
-
-
- Competitor Limit: - {competitionInfo.competitor_limit} -
-
- Contact: - {competitionInfo.contact ? ( - - ) : ( - - Organization Team - - )} -
-
- Organizers: - {competitionInfo.organizers.map((organizer) => ( - - {organizer.name} - - ))} -
-
- Delegates: - {competitionInfo.delegates.map((delegate) => ( +
Competitor Limit
+
Contact
+
Organizers
+
Delegates
+ + +
+ {competitionInfo.start_date === competitionInfo.end_date + ? `${moment(competitionInfo.start_date).format('ll')}` + : `${moment(competitionInfo.start_date).format( + 'll' + )} to ${moment(competitionInfo.end_date).format('ll')}`} +
+
+ {competitionInfo.city}, {competitionInfo.country_iso2} +
+
+

+

+
{competitionInfo.venue_address}
+ {competitionInfo.venue_details && ( +
{competitionInfo.venue_details}
+ )} +
{competitionInfo.competitor_limit}
+
+ {competitionInfo.contact ? ( + + ) : ( + + Organization Team + + )} +
+
+ {competitionInfo.organizers.map((organizer, index) => ( + + {organizer.name} + {index !== competitionInfo.organizers.length - 1 ? ', ' : ''} + + ))} +
+
+ {competitionInfo.delegates.map((delegate, index) => ( + + {delegate.name} + {index !== competitionInfo.delegates.length - 1 ? ', ' : ''} + + ))} +
+
+ +
+ + + Download all of the competitions details as a PDF{' '} - {delegate.name} + here - ))} -
-
- Download all of the competitions details as a - PDF{' '} - - here - -
-
-
+ + + +
The Competition has been bookmarked{' '} {competitionInfo.number_of_bookmarks} times -
-
+ + ) } diff --git a/Frontend/src/pages/home/index.module.scss b/Frontend/src/pages/home/index.module.scss index 29dda75d..8aab3b8f 100644 --- a/Frontend/src/pages/home/index.module.scss +++ b/Frontend/src/pages/home/index.module.scss @@ -1,61 +1,6 @@ -@import '../../style/font-sizes'; -@import '../../style/margins'; -@import '../../style/colors'; .information{ - font-size: $sub-header-size; - line-height: 1.3em; - padding: 30px; - .information-header{ - margin-bottom: $double-margin; - font-weight: bold; + font-size: 1.1em; + img{ + display: none; } -} -.home-container{ - padding: 20px; -} -.registration-period{ - font-size: $sub-header-size; - line-height: 1.3em; - padding: 0 30px 30px; - .registration-header{ - margin-bottom: $double-margin; - font-weight: bold; - } -} -.bookmarked{ - text-align: center; - font-size: $sub-header-size; - margin-top: $double-margin; -} -.requirements{ - font-weight: 500; - font-size: $sub-header-size; - background-color: $requirements-red; - border-radius: 28px; - padding: 30px; - width: 90%; - line-height: 3em; -} -.details{ - font-size: $sub-header-size; - line-height: $header-size; - background-color: #EBEBEB; - margin-top: $triple-margin; - border-radius: 28px; - padding: 30px; - ul{ - margin: 0; - } - .detailHeader{ - font-weight: bold; - } - p{ - display: inline; - } - .delegateLink{ - margin-right: $single-margin; - &::after{ - content: ','; - } - } -} +} \ No newline at end of file diff --git a/Frontend/src/pages/register/components/CompetingStep.jsx b/Frontend/src/pages/register/components/CompetingStep.jsx index 9dc71afc..f643e625 100644 --- a/Frontend/src/pages/register/components/CompetingStep.jsx +++ b/Frontend/src/pages/register/components/CompetingStep.jsx @@ -99,7 +99,7 @@ export default function CompetingStep({ nextStep }) { />
)} -
+
{registration.registration_status ? ( <>
diff --git a/Frontend/src/pages/register/components/Processing.jsx b/Frontend/src/pages/register/components/Processing.jsx index b415dbb2..4f4113ae 100644 --- a/Frontend/src/pages/register/components/Processing.jsx +++ b/Frontend/src/pages/register/components/Processing.jsx @@ -1,6 +1,6 @@ import { useQuery } from '@tanstack/react-query' import React, { useContext, useEffect, useState } from 'react' -import { Message } from 'semantic-ui-react' +import { Message, Modal } from 'semantic-ui-react' import { CompetitionContext } from '../../../api/helper/context/competition_context' import { UserContext } from '../../../api/helper/context/user_context' import { pollRegistrations } from '../../../api/registration/get/poll_registrations' @@ -29,23 +29,20 @@ export default function Processing({ onProcessingComplete }) { } }, [data, onProcessingComplete]) return ( -
-
Your registration is processing...
-
{data && `Registration status: ${data.status.competing}`}
-
+ + Your registration is processing... + {pollCounter > 3 && ( Processing is taking longer than usual, don't go away! )} -
-
{data && data.queueCount > 500 && ( Lots of Registrations being processed, hang tight! )} -
-
+ + ) } diff --git a/Frontend/src/pages/register/components/RegistrationRequirements.jsx b/Frontend/src/pages/register/components/RegistrationRequirements.jsx index f4dea369..7b1c1184 100644 --- a/Frontend/src/pages/register/components/RegistrationRequirements.jsx +++ b/Frontend/src/pages/register/components/RegistrationRequirements.jsx @@ -1,64 +1,169 @@ +import * as currencies from '@dinero.js/currencies' import { UiIcon } from '@thewca/wca-components' +import { dinero, toDecimal } from 'dinero.js' +import { marked } from 'marked' import moment from 'moment/moment' -import React, { useContext } from 'react' -import { Popup } from 'semantic-ui-react' +import React, { useContext, useState } from 'react' +import { Accordion, Header, Segment } from 'semantic-ui-react' import { CompetitionContext } from '../../../api/helper/context/competition_context' import styles from './requirements.module.scss' export default function RegistrationRequirements() { const { competitionInfo } = useContext(CompetitionContext) + const [activeIndex, setActiveIndex] = useState(-1) + const handleClick = (e, titleProps) => { + const { index } = titleProps + setActiveIndex(activeIndex === index ? -1 : index) + } return ( -
- - WCA Account Required - - } - /> -
- - {competitionInfo.competitor_limit} Competitor Limit{' '} - - - } - /> -
- - Full Refund before{' '} - {moment( - competitionInfo.refund_policy_limit_date ?? - competitionInfo.start_date - ).format('ll')} - - - } - /> -
- +
+
+ Registration Requirements + + [INSERT ORGANIZER MESSAGE REGARDING REQUIREMENTS] + +
+ + + + + WCA Account Required + + +

+ You need a WCA Account to register, click{' '} + here to create one. +

+
+ + + {competitionInfo.competitor_limit} person Competitor Limit + + +

+ Once the competitor Limit has been reached you will be put onto + the waiting list. +

+
+ + + {competitionInfo.refund_policy_percent === 0 + ? 'No refunds' + : `${ + competitionInfo.refund_policy_percent + }% Refund before ${moment( + competitionInfo.refund_policy_limit_date ?? + competitionInfo.start_date + ).format('ll')}`} + + +

+ {competitionInfo.refund_policy_percent === 0 + ? "Registration fees won't be refunded under any circumstance." + : `You will get a ${competitionInfo.refund_policy_percent}% refund + before this date.`} +

+
+ + Edit Registration until{' '} {moment( competitionInfo.event_change_deadline_date ?? competitionInfo.end_date ).format('ll')} - - - } - /> + + +

You can edit your registration until this date.

+
+ + + {competitionInfo.base_entry_fee_lowest_denomination + ? `${toDecimal( + dinero({ + amount: competitionInfo.base_entry_fee_lowest_denomination, + currency: currencies[competitionInfo.currency_code], + }), + ({ value, currency }) => `${currency.code} ${value}` + )} registration fee` + : 'No registration fee'} + + +

+ {competitionInfo.base_entry_fee_lowest_denomination + ? // eslint-disable-next-line unicorn/no-nested-ternary + competitionInfo['using_stripe_payments?'] + ? 'You will have to pay the registration fee on stripe after registering.' + : 'Check the Additional Registration Requirements about how to pay.' + : 'This competition is free'} +

+
+ + + {competitionInfo.guests_entry_fee_lowest_denomination + ? `${toDecimal( + dinero({ + amount: + competitionInfo.guests_entry_fee_lowest_denomination, + currency: currencies[competitionInfo.currency_code], + }), + ({ value, currency }) => `${currency.code} ${value}` + )} fee for attending guests` + : 'No guest fee'} + + +

+ {competitionInfo.guests_entry_fee_lowest_denomination + ? 'Guests have to pay this amount to attend.' + : 'Guests attend for free.'} +

+
+ {competitionInfo.extra_registration_requirements && ( + <> + + + Additional Registration Requirements + + +

+ + + )} + +

) } diff --git a/Frontend/src/pages/register/components/panel.module.scss b/Frontend/src/pages/register/components/panel.module.scss index 426e0621..61a1c329 100644 --- a/Frontend/src/pages/register/components/panel.module.scss +++ b/Frontend/src/pages/register/components/panel.module.scss @@ -3,10 +3,6 @@ .panel{ margin-top: $single-margin; } -.panel-processing{ - margin-top: $single-margin; - filter: blur(8px); -} .registration-greeting{ text-align: center; font-size: $sub-header-size; diff --git a/Frontend/src/pages/register/components/processing.module.scss b/Frontend/src/pages/register/components/processing.module.scss index 0e35e177..e69de29b 100644 --- a/Frontend/src/pages/register/components/processing.module.scss +++ b/Frontend/src/pages/register/components/processing.module.scss @@ -1,5 +0,0 @@ -@import '../../../style/font-sizes'; - -.processing-header{ - font-size: $sub-header-size; -} diff --git a/Frontend/src/pages/register/components/requirements.module.scss b/Frontend/src/pages/register/components/requirements.module.scss index b73ee3a3..eb489df1 100644 --- a/Frontend/src/pages/register/components/requirements.module.scss +++ b/Frontend/src/pages/register/components/requirements.module.scss @@ -1,15 +1,6 @@ -@import '../../../style/font-sizes'; @import '../../../style/margins'; -@import '../../../style/colors'; -.requirementText{ - margin-top: $triple-margin; - font-weight: 500; - font-size: $sub-header-size; - background-color: $requirements-red; - border-radius: 28px; - margin-left: 5%; - padding: 30px; - width: 90%; - line-height: 3em; +.requirements{ + margin-top: $double-margin; + margin-bottom: $double-margin; } \ No newline at end of file diff --git a/Frontend/src/pages/register/index.jsx b/Frontend/src/pages/register/index.jsx index 92ed0e84..d1b24ea7 100644 --- a/Frontend/src/pages/register/index.jsx +++ b/Frontend/src/pages/register/index.jsx @@ -1,7 +1,6 @@ import moment from 'moment' import React, { useContext } from 'react' import { Message } from 'semantic-ui-react' -import { CAN_ATTEND_COMPETITIONS } from '../../api/auth/get_permissions' import { CompetitionContext } from '../../api/helper/context/competition_context' import { PermissionsContext } from '../../api/helper/context/permission_context' import { UserContext } from '../../api/helper/context/user_context' @@ -17,22 +16,23 @@ export default function Register() { const loggedIn = user !== null return (
-
-
- Registration Requirements -
+
{!loggedIn ? ( -

You have to log in to Register for a Competition

+ + You need to log in to Register for a competition + ) : // eslint-disable-next-line unicorn/no-nested-ternary competitionInfo['registration_opened?'] ? (
-
Hi, {user.name}
{canAttendCompetition ? ( ) : ( - + + You are not allowed to Register for a competition, make sure your + profile is complete and you are not banned + )}
) : ( diff --git a/Frontend/src/pages/register/index.module.scss b/Frontend/src/pages/register/index.module.scss index 92371bb9..86898a4b 100644 --- a/Frontend/src/pages/register/index.module.scss +++ b/Frontend/src/pages/register/index.module.scss @@ -1,24 +1,4 @@ @import '../../style/font-sizes'; -@import '../../style/margins'; -@import '../../style/colors'; -.registration-header{ - margin-top: $single-margin; - margin-bottom: $double-margin; - text-align: center; - font-size: $sub-header-size; - font-weight: 700; - line-height: normal; -} -.requirements{ - margin-top: $single-margin; - margin-bottom: $double-margin; - .requirements-header{ - font-size: $header-size; - text-align: center; - margin-top: $triple-margin; - font-weight: 700; - } -} .competition-not-open{ font-size: $sub-header-size; padding: 30px; diff --git a/Frontend/src/pages/registration_administration/index.jsx b/Frontend/src/pages/registration_administration/index.jsx index f22e74d4..b483bb38 100644 --- a/Frontend/src/pages/registration_administration/index.jsx +++ b/Frontend/src/pages/registration_administration/index.jsx @@ -1,5 +1,4 @@ import React, { useContext } from 'react' -import { CAN_ADMINISTER_COMPETITIONS } from '../../api/auth/get_permissions' import { PermissionsContext } from '../../api/helper/context/permission_context' import PermissionMessage from '../../ui/messages/permissionMessage' import RegistrationAdministrationList from './components/RegistrationAdministrationList' @@ -11,7 +10,9 @@ export default function RegistrationAdministration() { {canAdminCompetition ? ( ) : ( - + + You are not allowed to administrate this competition + )}
) diff --git a/Frontend/src/pages/registration_edit/index.jsx b/Frontend/src/pages/registration_edit/index.jsx index e3c51f70..6494e201 100644 --- a/Frontend/src/pages/registration_edit/index.jsx +++ b/Frontend/src/pages/registration_edit/index.jsx @@ -1,5 +1,4 @@ import React, { useContext } from 'react' -import { CAN_ADMINISTER_COMPETITIONS } from '../../api/auth/get_permissions' import { PermissionsContext } from '../../api/helper/context/permission_context' import PermissionMessage from '../../ui/messages/permissionMessage' import RegistrationEditor from './components/RegistrationEditor' @@ -12,7 +11,9 @@ export default function RegistrationEdit() { {canAdminCompetition ? ( ) : ( - + + You are not allowed to administrate this competition + )}
) diff --git a/Frontend/src/ui/Competition.jsx b/Frontend/src/ui/Competition.jsx index cac87df5..de315483 100644 --- a/Frontend/src/ui/Competition.jsx +++ b/Frontend/src/ui/Competition.jsx @@ -2,13 +2,23 @@ import * as currencies from '@dinero.js/currencies' import { useQuery } from '@tanstack/react-query' import { CubingIcon, UiIcon } from '@thewca/wca-components' import { dinero, toDecimal } from 'dinero.js' +import { marked } from 'marked' import moment from 'moment' -import React from 'react' +import React, { useMemo } from 'react' import { useNavigate, useParams } from 'react-router-dom' -import { Button, Image } from 'semantic-ui-react' +import { + Button, + Container, + Grid, + Header, + Image, + Label, + Segment, +} from 'semantic-ui-react' import getCompetitionInfo from '../api/competition/get/get_competition_info' import { CompetitionContext } from '../api/helper/context/competition_context' import { BASE_ROUTE } from '../routes' +import logo from '../static/wca2020.svg' import styles from './competition.module.scss' import LoadingMessage from './messages/loadingMessage' @@ -19,6 +29,15 @@ export default function Competition({ children }) { queryKey: [competition_id], queryFn: () => getCompetitionInfo(competition_id), }) + // Hack before we have an image Icon field in the DB + const src = useMemo(() => { + if (competitionInfo) { + const div = document.createElement('DIV') + div.innerHTML = marked(competitionInfo.information) + return div.querySelector('img')?.src ?? logo + } + return '' + }, [competitionInfo]) return ( ) : ( <> -
-
-
-
- {competitionInfo.name} |{' '} - {competitionInfo['registration_opened?'] ? ( - Open - ) : ( - Close - )} -
-
- {competitionInfo.venue_address} -
-
- {moment(competitionInfo.start_date).format('LL')},{' '} - - Add to Google Calendar - -
-
- *Insert Potential organizer announcement or memo for users to - view before hitting register* -
- - - Registration Fee:{' '} - {toDecimal( - dinero({ - amount: - competitionInfo.base_entry_fee_lowest_denomination, - currency: currencies[competitionInfo.currency_code], - }), - ({ value, currency }) => `${currency.code} ${value}` - ) ?? 'No Entry Fee'} - -
-
- -
-
+ }} + > + Register + + + + + + + +
Events: @@ -110,7 +139,7 @@ export default function Competition({ children }) {
-
+ {children} )} diff --git a/Frontend/src/ui/Tabs.jsx b/Frontend/src/ui/Tabs.jsx index 95600f76..8cf1973f 100644 --- a/Frontend/src/ui/Tabs.jsx +++ b/Frontend/src/ui/Tabs.jsx @@ -176,6 +176,7 @@ export default function PageTabs() { return ( + Unauthorized - You need '{permissionLevel}' Permissions to access this content. + {children} ) diff --git a/Frontend/src/ui/tabs.module.scss b/Frontend/src/ui/tabs.module.scss index 3cb13392..01d147a1 100644 --- a/Frontend/src/ui/tabs.module.scss +++ b/Frontend/src/ui/tabs.module.scss @@ -3,3 +3,6 @@ .tab-item{ font-size: $menu-size; } +.tabs{ + overflow-x: auto; +} \ No newline at end of file