diff --git a/backend/modules/team/controller.js b/backend/modules/team/controller.js index 6b457b8b..ed38262c 100644 --- a/backend/modules/team/controller.js +++ b/backend/modules/team/controller.js @@ -491,23 +491,32 @@ controller.attachUserApplicant = (teams, userId) => { controller.getTeamsForEvent = async (eventId, userId, page, size, filter) => { let eventTeams = [] - const query = { event: eventId } - - if (filter) { - query.challenge = filter - } - - const teamCount = await Team.countDocuments(query) - + let teamCount = 0 if (page && size) { - eventTeams = await Team.find(query) - .sort({ createdAt: 'desc' }) - .skip(parseInt(size * page)) - .limit(parseInt(size)) + if (filter) { + eventTeams = await Team.find({ + event: eventId, + challenge: filter, + }) + .sort({ createdAt: 'desc' }) + .skip(parseInt(size * page)) + .limit(parseInt(size)) + teamCount = await eventTeams.length + } else { + eventTeams = await Team.find({ + event: eventId, + }) + .sort({ createdAt: 'desc' }) + .skip(parseInt(size * page)) + .limit(parseInt(size)) + teamCount = await eventTeams.length + } } else { - eventTeams = await Team.find(query).sort({ createdAt: 'desc' }) + eventTeams = await Team.find({ + event: eventId, + }).sort({ createdAt: 'desc' }) + teamCount = await eventTeams.length } - const teamsWithoutTeamCode = convertToObjectAndStripProperties(eventTeams, [ 'code', ]) diff --git a/frontend/src/assets/images/venueMap2023/LayoutMap-venue-01.jpg b/frontend/src/assets/images/venueMap2023/LayoutMap-venue-01.jpg new file mode 100644 index 00000000..eee48867 Binary files /dev/null and b/frontend/src/assets/images/venueMap2023/LayoutMap-venue-01.jpg differ diff --git a/frontend/src/assets/images/venueMap2023/LayoutMap-venue-02.jpg b/frontend/src/assets/images/venueMap2023/LayoutMap-venue-02.jpg new file mode 100644 index 00000000..68e47a41 Binary files /dev/null and b/frontend/src/assets/images/venueMap2023/LayoutMap-venue-02.jpg differ diff --git a/frontend/src/assets/images/venueMap2023/LayoutMap-venue-03.jpg b/frontend/src/assets/images/venueMap2023/LayoutMap-venue-03.jpg new file mode 100644 index 00000000..175c46fd Binary files /dev/null and b/frontend/src/assets/images/venueMap2023/LayoutMap-venue-03.jpg differ diff --git a/frontend/src/components/Team/AdminTeamEdit/index.js b/frontend/src/components/Team/AdminTeamEdit/index.js index fbeef63d..90035057 100644 --- a/frontend/src/components/Team/AdminTeamEdit/index.js +++ b/frontend/src/components/Team/AdminTeamEdit/index.js @@ -53,53 +53,53 @@ export default ({ // console.log("delete") // } - // const handleRemove = useEffect(() => { - // console.log('delete', slug, teamData?.code, teamMemberToRemove) - // setLoading(true) - // dispatch( - // DashboardActions.organiserRemoveMemberFromTeam( - // slug, - // teamData.code, - // teamMemberToRemove, - // ), - // ) - // .then(team => { - // console.log('removed succesfully.', team) - // dispatch(OrganiserActions.updateTeamsForEvent(slug)) - // }) - // .then(() => { - // console.log( - // 'teams updated', - // teamMembersArr.filter( - // t => t.profile.userId !== teamMemberToRemove, - // ), - // ) - // setTeamMembersArr( - // teamMembersArr.filter( - // t => t.profile.userId !== teamMemberToRemove, - // ), - // ) - // dispatch( - // SnackbarActions.success( - // 'removed ' + - // teamMemberToRemove + - // ' from team ' + - // teamData?.code, - // ), - // ) - // }) - // .catch(() => { - // dispatch( - // SnackbarActions.error( - // 'Something went wrong... please try again.', - // ), - // ) - // }) - // .finally(() => { - // setTeamMemberToRemove('') - // setLoading(false) - // }) - // }, [teamMemberToRemove, slug, teamData?.code, dispatch]) + const handleRemove = useEffect(() => { + console.log('delete', slug, teamData?.code, teamMemberToRemove) + setLoading(true) + dispatch( + DashboardActions.organiserRemoveMemberFromTeam( + slug, + teamData.code, + teamMemberToRemove, + ), + ) + .then(team => { + console.log('removed succesfully.', team) + dispatch(OrganiserActions.updateTeamsForEvent(slug)) + }) + .then(() => { + console.log( + 'teams updated', + teamMembersArr.filter( + t => t.profile.userId !== teamMemberToRemove, + ), + ) + setTeamMembersArr( + teamMembersArr.filter( + t => t.profile.userId !== teamMemberToRemove, + ), + ) + dispatch( + SnackbarActions.success( + 'removed ' + + teamMemberToRemove + + ' from team ' + + teamData?.code, + ), + ) + }) + .catch(() => { + dispatch( + SnackbarActions.error( + 'Something went wrong... please try again.', + ), + ) + }) + .finally(() => { + setTeamMemberToRemove('') + setLoading(false) + }) + }, [teamMemberToRemove, slug, teamData?.code, dispatch]) const classes = junctionStyle() return ( diff --git a/frontend/src/components/Team/TeamHeader/index.js b/frontend/src/components/Team/TeamHeader/index.js index be78a46f..1f6ebb6d 100644 --- a/frontend/src/components/Team/TeamHeader/index.js +++ b/frontend/src/components/Team/TeamHeader/index.js @@ -21,8 +21,10 @@ export default ({ let challengeName = null let event = useSelector(DashboardSelectors.event) if (event === null) { + console.log('from organiser') event = useSelector(OrganiserSelectors.event) } + console.log('event', event) if (teamChallenge && typeof teamChallenge === 'string') { const challengeDetails = event.challenges.find( challenge => challenge._id === teamChallenge, diff --git a/frontend/src/components/projects/ProjectDetail/ProjectTeam.js b/frontend/src/components/projects/ProjectDetail/ProjectTeam.js index f9b28bfd..228ea9a7 100644 --- a/frontend/src/components/projects/ProjectDetail/ProjectTeam.js +++ b/frontend/src/components/projects/ProjectDetail/ProjectTeam.js @@ -70,7 +70,7 @@ const ProjectTeam = React.memo(({ hiddenUsers, teamId, showFullTeam }) => { useEffect(() => { fetchTeamMembers() - }, []) + }, [fetchTeamMembers]) if (loading) { return ( diff --git a/frontend/src/components/projects/ProjectDetail/index.js b/frontend/src/components/projects/ProjectDetail/index.js index 1abea06e..b902e888 100644 --- a/frontend/src/components/projects/ProjectDetail/index.js +++ b/frontend/src/components/projects/ProjectDetail/index.js @@ -114,8 +114,30 @@ const ProjectDetail = ({ const classes = useStyles() const [index, setIndex] = useState(0) const [pause, setPause] = useState(true) + const dispatch = useDispatch() if (!project) return null + const downloadFile = async fileDataString => { + const parsedValue = JSON.parse(fileDataString) + await dispatch( + DashboardActions.getFileForProject( + parsedValue.id, + parsedValue.filename, + ), + ) + } + + const extractFileDetails = (fileDataString, toExtract) => { + const parsedValue = JSON.parse(fileDataString) + switch (toExtract) { + case 'filename': + return parsedValue.filename + case 'id': + return parsedValue.id + default: + return parsedValue.filename + } + } const renderTrack = () => { const value = find(event.tracks, t => t.slug === project.track) @@ -128,7 +150,7 @@ const ProjectDetail = ({ return {value.name} } - const renderChallenges = () => { + const renderChallenges = challenges => { const values = filter( event.challenges, c => project.challenges.indexOf(c.slug) !== -1, @@ -373,8 +395,7 @@ const ProjectDetail = ({ {answer.fieldType === 'boolean' - ? answer.value === - 'true' + ? answer.value ? 'Yes' : 'No' : answer.value} diff --git a/frontend/src/components/projects/ProjectsGrid/index.js b/frontend/src/components/projects/ProjectsGrid/index.js index 6f91f720..69e18a7d 100644 --- a/frontend/src/components/projects/ProjectsGrid/index.js +++ b/frontend/src/components/projects/ProjectsGrid/index.js @@ -48,7 +48,6 @@ const ProjectsGrid = ({ } const fetchData = useCallback(async () => { // TODO add loading indicator - //TODO find a way to get if a project has been reviewed by partner in a more efficient manner so it doesnt run for all project fetched const projectScoreData = await Promise.allSettled( projects.map(async project => { return projectScoreLogic(project) diff --git a/frontend/src/pages/_dashboard/renderDashboard/generalPages/default/Blocks/RegistrationStatusBlock.js b/frontend/src/pages/_dashboard/renderDashboard/generalPages/default/Blocks/RegistrationStatusBlock.js index 0ca1f4e4..69d6c54f 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/generalPages/default/Blocks/RegistrationStatusBlock.js +++ b/frontend/src/pages/_dashboard/renderDashboard/generalPages/default/Blocks/RegistrationStatusBlock.js @@ -82,7 +82,7 @@ export default () => { return 'error' } case RegistrationStatuses.asObject.accepted.id: { - return 'theme_purple' + return 'success' } case RegistrationStatuses.asObject.acceptedToHub.id: { return 'success' @@ -207,7 +207,7 @@ export default () => { return ( - window.open(`${config.BASE_URL}/home`, '_blank') + window.open(config.CALENDAR_URL, '_blank') } color="theme_white" variant="contained" diff --git a/frontend/src/pages/_dashboard/renderDashboard/generalPages/map/index.js b/frontend/src/pages/_dashboard/renderDashboard/generalPages/map/index.js index dd773953..f4bbfeef 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/generalPages/map/index.js +++ b/frontend/src/pages/_dashboard/renderDashboard/generalPages/map/index.js @@ -1,48 +1,93 @@ -import React from 'react' +import React, { useEffect, useRef } from 'react' import { useRouteMatch, useLocation } from 'react-router' +import FormControl from '@material-ui/core/FormControl' +import FormGroup from '@material-ui/core/FormGroup' +import FormControlLabel from '@material-ui/core/FormControlLabel' +import Checkbox from '@material-ui/core/Checkbox' +import { useDispatch, useSelector } from 'react-redux' import PageWrapper from 'components/layouts/PageWrapper' import MaterialTabsLayout from 'components/layouts/MaterialTabsLayout' import PageHeader from 'components/generic/PageHeader' +import Image from 'components/generic/Image' import GradientBox from 'components/generic/GradientBox' -import { Box, Link, Typography } from '@material-ui/core' +import LayoutMap1 from 'assets/images/venueMap2023/LayoutMap-venue-01.jpg' +import LayoutMap2 from 'assets/images/venueMap2023/LayoutMap-venue-02.jpg' +import LayoutMap3 from 'assets/images/venueMap2023/LayoutMap-venue-03.jpg' +import { Grid, Typography } from '@material-ui/core' export default () => { const match = useRouteMatch() const location = useLocation() - const mapFloorNeg1 = - 'https://res.cloudinary.com/hackjunction/image/upload/v1731052748/event-specific/Junction%202024/Map/basement-floor.png' - const mapFloor1 = - 'https://res.cloudinary.com/hackjunction/image/upload/v1731052754/event-specific/Junction%202024/Map/first-floor.png' - const mapFloor2 = - 'https://res.cloudinary.com/hackjunction/image/upload/v1731052751/event-specific/Junction%202024/Map/second-floor.png' - const FloorMap = ({ mapSrc, altText }) => ( - - - Open on new tab - - - - ) + + const floorNeg1 = () => { + return ( + + + + ) + } + + const floor1 = () => { + return ( + + + + ) + } + + + const floor2 = () => { + return ( + + + + ) + } + + return ( <> + {/* button for DEV to swithc between participant / partner view */} + {/* setIsPartner(!isPartner)} + color="primary" + variant="contained" + > + Switch between participant / partner view (only for dev) + */} + + {/* + Map of dipoli + + */} - Need more help? - - Click here to review the Guidebook - - + { path: '/1', key: '1', label: 'Floor 1', - component: () => ( - - ), + component: () => floorNeg1() + }, + { + path: '/-1', + key: '-1', + label: 'Floor -1', + component: () => floor1() }, { path: '/2', key: '2', label: 'Floor 2', - component: () => ( - - ), - }, - { - path: '/basement', - key: 'basement', - label: 'Basement', - component: () => ( - - ), + component: () => floor2() }, + ]} location={location} baseRoute={match.url} diff --git a/frontend/src/pages/_dashboard/renderDashboard/participant/finalist-voting/index.js b/frontend/src/pages/_dashboard/renderDashboard/participant/finalist-voting/index.js index 3d8d3349..e8511c60 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/participant/finalist-voting/index.js +++ b/frontend/src/pages/_dashboard/renderDashboard/participant/finalist-voting/index.js @@ -1,6 +1,6 @@ import React, { useCallback, useEffect, useState } from 'react' -import { Grid, Box, Button, Dialog, Card, Typography } from '@material-ui/core' +import { Grid, Box, Button, Dialog } from '@material-ui/core' import { useSelector, useDispatch } from 'react-redux' import PageHeader from 'components/generic/PageHeader' @@ -26,15 +26,14 @@ export default () => { const [selected, setSelected] = useState(false) const [projects, setProjects] = useState([]) - const [currentVote, setCurrentVote] = useState(null) - const [hasVoted, setHasVoted] = useState(false) - const [newVote, setNewVote] = useState(null) + const [vote, setVote] = useState(null) + const [hasVoted, setVoted] = useState(false) - const getCurrentVote = async () => { + const getCurrentVote = useCallback(async () => { return WinnerVoteService.getVote(idToken, event.slug) - } + }, [idToken, event]) - const getFinalists = async () => { + const getFinalists = useCallback(async () => { EventsService.getFinalists(idToken, event.slug) .then(finalistProjects => { setProjects(finalistProjects) @@ -46,7 +45,7 @@ export default () => { ), ) }) - } + }, [idToken, event]) useEffect(() => { setLoading(true) @@ -59,13 +58,12 @@ export default () => { } }, []) - const update = async () => { + const update = useCallback(async () => { try { - const currentVoteFetched = await getCurrentVote() - if (currentVoteFetched && currentVoteFetched?.project) { - setCurrentVote(currentVoteFetched.project) - setNewVote(currentVoteFetched.project) - setHasVoted(true) + const vote = await getCurrentVote() + if (vote && vote?.project) { + setVote(vote?.project) + setVoted(true) } } catch (err) { dispatch( @@ -74,7 +72,7 @@ export default () => { ), ) } - } + }, [event, idToken]) const handleSubmit = async () => { try { @@ -82,17 +80,15 @@ export default () => { const result = await WinnerVoteService.submitVote( idToken, event.slug, - newVote, + vote, ) if (result) { - setCurrentVote(newVote) - setHasVoted(true) - dispatch(SnackbarActions.success('vote submitted!')) + dispatch(SnackbarActions.success('Vote submitted!')) } } catch (err) { dispatch( SnackbarActions.error( - `Your vote could not be saved. Error: ${ + `Score could not be saved. Error: ${ err.response.data.message || err.message }`, ), @@ -108,40 +104,33 @@ export default () => { heading="Finalist voting" subheading="Vote for your favorite project of the finalists" /> - - {projects && - currentVote && - projects.find(project => project._id === currentVote) && ( - - - Your current choice is:{' '} - { - projects.find( - project => project._id === currentVote, - ).name - } - - - )} - + + ({ label: project.name, value: project._id, }))} /> + + {hasVoted ? 'Change vote' : 'Submit vote'} - + {projects.map((project, index) => ( diff --git a/frontend/src/pages/_dashboard/renderDashboard/participant/index.js b/frontend/src/pages/_dashboard/renderDashboard/participant/index.js index 6402f113..78678acc 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/participant/index.js +++ b/frontend/src/pages/_dashboard/renderDashboard/participant/index.js @@ -31,7 +31,6 @@ import ChallengesIndex from '../generalPages/challenges' import CalendarPage from './calendar' import MapPage from '../generalPages/map' import ChecklistPage from './checklist' -import sideChallengesPage from './side-challenges' import { useTranslation } from 'react-i18next' @@ -42,7 +41,6 @@ import { LocalAirportRounded, LocalPlayRounded, QuestionAnswerSharp, - Directions, } from '@material-ui/icons' import { Chat } from 'components/messaging/chat' @@ -78,8 +76,6 @@ export default ({ const [alertCount, setAlertCount] = useState(originalAlertCount) const [alerts, setAlerts] = useState(originalAlerts) - let isNotMainEvent = event?.slug !== 'junction-2024' - useEffect(() => { setAlerts(originalAlerts) setAlertCount(originalAlertCount) @@ -129,16 +125,6 @@ export default ({ label: t('Finalist_voting_'), component: FinalistVotingPage, }, - //TODO make re-enable map for all events - { - key: 'map', - hidden: isNotMainEvent, - path: '/map', - exact: false, - icon: , - label: 'Venue map', - component: MapPage, - }, { key: 'team', path: '/team', @@ -198,17 +184,6 @@ export default ({ label: t('Challenges_'), component: ChallengesIndex, }, - //TODO make side-challenges into a full feature - { - key: 'side-challenges', - path: '/side-challenges', - exact: true, - icon: , - hidden: isNotMainEvent, - label: 'Side-challenges', - component: sideChallengesPage, - }, - //TODO fix meeting booking system { key: 'calendar', path: '/calendar', @@ -219,6 +194,15 @@ export default ({ component: CalendarPage, }, // Experimental + { + key: 'map', + hidden: !shownPages.experimental, + path: '/map', + exact: false, + icon: , + label: 'Map', + component: MapPage, + }, { key: 'chat', hidden: !shownPages.experimental, diff --git a/frontend/src/pages/_dashboard/renderDashboard/participant/side-challenges/index.js b/frontend/src/pages/_dashboard/renderDashboard/participant/side-challenges/index.js deleted file mode 100644 index 4e8ab5ec..00000000 --- a/frontend/src/pages/_dashboard/renderDashboard/participant/side-challenges/index.js +++ /dev/null @@ -1,79 +0,0 @@ -import { Box, Typography } from '@material-ui/core' -import Image from 'components/generic/Image' -import Markdown from 'components/generic/Markdown' -import PageHeader from 'components/generic/PageHeader' -import PageWrapper from 'components/layouts/PageWrapper' -import React from 'react' - -export default () => { - return ( - - - - - - Hosted by - - - - - - - - - - - - ) -} diff --git a/frontend/src/pages/_dashboard/renderDashboard/participant/team/index.js b/frontend/src/pages/_dashboard/renderDashboard/participant/team/index.js index fd5a8ad0..3d2d0695 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/participant/team/index.js +++ b/frontend/src/pages/_dashboard/renderDashboard/participant/team/index.js @@ -40,6 +40,7 @@ export default () => { component: CandidatesPage, }) } + // const hasTeam = useSelector(DashboardSelectors.hasTeam) // TODO make tab "my team" and "Team candidates" visible only if user has a team return ( diff --git a/frontend/src/pages/_dashboard/renderDashboard/participant/team/teams/index.js b/frontend/src/pages/_dashboard/renderDashboard/participant/team/teams/index.js index deddcc9f..f2a262ee 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/participant/team/teams/index.js +++ b/frontend/src/pages/_dashboard/renderDashboard/participant/team/teams/index.js @@ -19,7 +19,6 @@ import JoinTeamByCode from 'components/Team/JoinTeamByCode' import { useTranslation } from 'react-i18next' export default () => { - const numberOfTeamsShown = 30 const dispatch = useDispatch() const event = useSelector(DashboardSelectors.event) const { t } = useTranslation() @@ -37,34 +36,44 @@ export default () => { const [currentPage, SetCurrentPage] = useState(0) const totalResults = useSelector(DashboardSelectors.teamsCount) - const totalPages = Math.ceil(totalResults / numberOfTeamsShown) + const totalPages = Math.ceil(totalResults / 25) - const hadleTeamCardClick = async teamId => { - if (teamId) { - setLoading(true) - dispatch(DashboardActions.updateSelectedTeam(slug, teamId)) - .then(team => { - setSelectedTeam(team) - }) - .catch(err => { - console.log(err) - }) - .finally(() => { - setLoading(false) - }) - } - } + const hadleTeamCardClick = useCallback( + async teamId => { + if (teamId) { + setLoading(true) + dispatch(DashboardActions.updateSelectedTeam(slug, teamId)) + .then(team => { + setSelectedTeam(team) + }) + .catch(err => { + console.log(err) + }) + .finally(() => { + setLoading(false) + }) + } + }, + [selectedTeam], + ) useEffect(() => { dispatch( DashboardActions.updateTeams( slug, currentPage, - numberOfTeamsShown, + 25, challengeFilter, ), ) - }, [currentPage, joinByCode, challengeFilter]) + }, [ + currentPage, + applying, + selected, + selectedTeam, + joinByCode, + challengeFilter, + ]) let teamCards = [] if (challengeFilter !== 'All challenges') { @@ -171,7 +180,7 @@ export default () => { )} {!selected && !applying && ( <> - + {!hasTeam ? ( { onClick={() => setJoinByCode(!joinByCode)} > {t('Join_team_using_code_')} + {/* Join team using a code */} ) : ( @@ -189,10 +199,7 @@ export default () => { label: challenge.name, value: challenge._id, }))} - onChange={value => { - SetCurrentPage(0) - setChallengeFilter(value) - }} + onChange={setChallengeFilter} /> {joinByCode && (