Skip to content

Commit

Permalink
Fix crashing caused by missing data (#105)
Browse files Browse the repository at this point in the history
  • Loading branch information
MikaKattainen authored Jul 15, 2022
1 parent 932b0a6 commit 6cccc3d
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 90 deletions.
16 changes: 14 additions & 2 deletions src/components/LoadingSpinner.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,18 @@ const Loader = styled.div`
`} 1s linear infinite;
`

const Spinner = () => <Loader />
const CenteredContainer = styled.div`
display: flex;
align-items: center;
justify-content: center;
`

export const Spinner = () => <Loader />

export const CenteredSpinner = () => (
<CenteredContainer>
<Spinner />
</CenteredContainer>
)

export default Spinner
export default CenteredSpinner
12 changes: 2 additions & 10 deletions src/views/AcceptTasks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { acceptGroupMemberTasks, postTaskGroupEntry } from '../../api'
import { COMPLETION_STATUS, TASK_GROUP_STATUS } from 'consts'
import { useDispatch } from 'react-redux'
import { useParams } from 'react-router-dom'
import LoadingSpinner from '../../components/LoadingSpinner'
import CenteredSpinner from '../../components/LoadingSpinner'

const AcceptTasksAction = styled.div`
position: fixed;
Expand All @@ -36,12 +36,6 @@ const AcceptTasksAction = styled.div`
`} 200ms linear;
`

const SpinnerContainer = styled.div`
display: flex;
align-items: center;
justify-content: center;
`

const ActivityItem = styled.div`
display: flex;
align-items: center;
Expand Down Expand Up @@ -210,9 +204,7 @@ const AcceptTasks = () => {
})}
{isLoading ? (
<AcceptTasksAction>
<SpinnerContainer>
<LoadingSpinner />
</SpinnerContainer>
<CenteredSpinner />
</AcceptTasksAction>
) : item.type === 'TASK' ? (
<AcceptTasksAction onClick={handleSubmit}>
Expand Down
158 changes: 80 additions & 78 deletions src/views/Member/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import {
import { actionTypes } from 'components/Actions'
import CompletedTasks from '../Profile/CompletedTasks'
import { getTaskGroupsWithChildTaskGroups } from '../../helpers/groupTasks'
import MemberTaskListItem, { LIST_ITEM_TYPES } from './taskListItems'
import CenteredSpinner from '../../components/LoadingSpinner'

const Background = styled.div`
min-height: 100vh;
Expand Down Expand Up @@ -172,6 +174,83 @@ const Member = () => {
.filter((guid) => !parentTaskGroupGuids.includes(guid))
.map((id) => itemsByGuid[id])

const Lists = () => {
/* If the user navigates to this page too fast or reloads the page all the data is not available.
* The initial download only fetches age groups which means the tasks and task groups are not available
* so we should show a spinner while we wait for them to load.
*/
return Object.keys(itemsByGuid).length < 25 ? (
<CenteredSpinner />
) : (
<>
<h4>{getTermInLanguage(translations, 'odottaa-hyvaksyntaa')}</h4>
<TaskList>
{completionRequestedTasks.map((taskGuid, index) => (
<MemberTaskListItem
key={index}
itemsByGuid={itemsByGuid}
taskGuid={taskGuid}
activityGroups={activityGroups}
language={language}
type={LIST_ITEM_TYPES.COMPLETION_REQUEST_LIST_ITEM}
groupId={groupId}
memberId={memberId}
/>
))}
</TaskList>
<h4>{getTermInLanguage(translations, 'tyon-alla')}</h4>
<TaskList>
{activeTasks.map((taskGuid, index) => (
<MemberTaskListItem
key={index}
itemsByGuid={itemsByGuid}
taskGuid={taskGuid}
activityGroups={activityGroups}
language={language}
type={LIST_ITEM_TYPES.ACTIVE_LIST_ITEM}
/>
))}
</TaskList>
<h4>{getTermInLanguage(translations, 'suoritetut')}</h4>
<TaskList>
{taskGroupsWithChildTaskGroups && (
<CompletedTasks
language={language}
itemsByGuid={itemsByGuid}
taskGroupsWithChildTaskGroups={taskGroupsWithChildTaskGroups}
groupMember={{ groupId, memberId }}
actionsComponent={actionTypes.groupLeaderActions}
userGuid={Number(memberId)}
groupGuid={group.id}
parentTaskGroupGuids={parentTaskGroupGuids}
completedTaskGroupsGuids={completedTaskGroupsGuids}
/>
)}
{taskGroupsMarkedCompleted &&
taskGroupsMarkedCompleted.map((taskGroup) => {
if (!taskGroup) return null
return (
<ListItem
key={taskGroup.id}
guid={getItemId(taskGroup.item)}
ageGroupGuid={taskGroup.ageGroupGuid}
title={taskGroup.item.title}
subTitle={getTermInLanguage(
translations,
'kokonaisuus-valmis'
)}
icon={getActivityGroupIcon(taskGroup.item)}
language={language}
itemType={ITEM_TYPES.TASK_GROUP}
showActions
/>
)
})}
</TaskList>
</>
)
}

return (
<Background ageGroupGuid={ageGroupGuid}>
<Content>
Expand All @@ -189,84 +268,7 @@ const Member = () => {
</HeadingContent>
<BodyContent>
<h4>{getTermInLanguage(translations, 'aktiviteetit')}</h4>
<h4>{getTermInLanguage(translations, 'odottaa-hyvaksyntaa')}</h4>
<TaskList>
{completionRequestedTasks.map((taskGuid) => {
const task = itemsByGuid[taskGuid]
if (!task) return null
const parent = activityGroups[task.item.activity_group]
if (task.item.locale !== language) return null
return (
<ListItem
key={getItemId(task.item)}
guid={task.id}
groupGuid={Number(groupId)}
userGuid={Number(memberId)}
title={task.item.title}
icon={getActivityGroupIcon(parent)}
subTitle={parent.title}
itemType={ITEM_TYPES.TASK}
actionsComponent={actionTypes.groupLeaderActions}
showActions
/>
)
})}
</TaskList>
<h4>{getTermInLanguage(translations, 'tyon-alla')}</h4>
<TaskList>
{activeTasks.map((taskGuid) => {
const task = itemsByGuid[taskGuid]
const parent = activityGroups[task.item.activity_group]
if (task.item.locale !== language) return null
return (
<ListItem
key={getItemId(task.item)}
guid={task.id}
title={task.item.title}
subTitle={parent.title}
icon={getActivityGroupIcon(parent)}
itemType={ITEM_TYPES.TASK}
actionsComponent={actionTypes.groupLeaderActions}
/>
)
})}
</TaskList>
<h4>{getTermInLanguage(translations, 'suoritetut')}</h4>
<TaskList>
{taskGroupsWithChildTaskGroups && (
<CompletedTasks
language={language}
itemsByGuid={itemsByGuid}
taskGroupsWithChildTaskGroups={taskGroupsWithChildTaskGroups}
groupMember={{ groupId, memberId }}
actionsComponent={actionTypes.groupLeaderActions}
userGuid={Number(memberId)}
groupGuid={group.id}
parentTaskGroupGuids={parentTaskGroupGuids}
completedTaskGroupsGuids={completedTaskGroupsGuids}
/>
)}
{taskGroupsMarkedCompleted &&
taskGroupsMarkedCompleted.map((taskGroup) => {
if (!taskGroup) return null
return (
<ListItem
key={taskGroup.id}
guid={getItemId(taskGroup.item)}
ageGroupGuid={taskGroup.ageGroupGuid}
title={taskGroup.item.title}
subTitle={getTermInLanguage(
translations,
'kokonaisuus-valmis'
)}
icon={getActivityGroupIcon(taskGroup.item)}
language={language}
itemType={ITEM_TYPES.TASK_GROUP}
showActions
/>
)
})}
</TaskList>
<Lists />
</BodyContent>
</Content>
</Background>
Expand Down
65 changes: 65 additions & 0 deletions src/views/Member/taskListItems.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React from 'react'

import ListItem from 'components/ListItem'
import { actionTypes } from 'components/Actions'
import { ITEM_TYPES } from '../../consts'
import { getActivityGroupIcon, getItemId } from '../../helpers'

export const LIST_ITEM_TYPES = {
ACTIVE_LIST_ITEM: 'activeListItem',
COMPLETION_REQUEST_LIST_ITEM: 'completionRequestItem',
}

const ActiveListItem = ({ task, parent }) => (
<ListItem
key={getItemId(task.item)}
guid={task.id}
title={task.item.title}
subTitle={parent.title}
icon={getActivityGroupIcon(parent)}
itemType={ITEM_TYPES.TASK}
actionsComponent={actionTypes.groupLeaderActions}
/>
)

const CompletionRequestedItem = ({ task, parent, groupId, memberId }) => (
<ListItem
key={getItemId(task.item)}
guid={task.id}
groupGuid={Number(groupId)}
userGuid={Number(memberId)}
title={task.item.title}
icon={getActivityGroupIcon(parent)}
subTitle={parent.title}
itemType={ITEM_TYPES.TASK}
actionsComponent={actionTypes.groupLeaderActions}
showActions
/>
)

const LIST_ITEMS = {
[LIST_ITEM_TYPES.ACTIVE_LIST_ITEM]: ActiveListItem,
[LIST_ITEM_TYPES.COMPLETION_REQUEST_LIST_ITEM]: CompletionRequestedItem,
}

const MemberTaskListItem = ({
itemsByGuid,
taskGuid,
activityGroups,
language,
type,
...props
}) => {
const task = itemsByGuid[taskGuid]

if (!task || !task.item || task.item.locale !== language) return null

const parent = activityGroups[task.item.activity_group]
if (!parent) return null

const Component = LIST_ITEMS[type]

return Component ? <Component {...props} task={task} parent={parent} /> : null
}

export default MemberTaskListItem

0 comments on commit 6cccc3d

Please sign in to comment.