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

Fix participant homepage loading state #889

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
136 changes: 67 additions & 69 deletions src/pages/HomeParticipant.vue
Original file line number Diff line number Diff line change
@@ -1,81 +1,79 @@
<template>
<div>
<div v-if="isFetching" class="loading-container py-8">
<div v-if="!initialized || isLoading || isFetching" class="loading-container py-8">
<AppSpinner style="margin-bottom: 1rem" />
<span>{{ $t('homeParticipant.loadingAssignments') }}</span>
</div>

<div v-else-if="!hasAssignments">
<div class="col-full text-center py-8">
<h1>{{ $t('homeParticipant.noAssignments') }}</h1>
<p class="text-center">{{ $t('homeParticipant.contactAdministrator') }}</p>

<PvButton
:label="$t('navBar.signOut')"
class="no-underline bg-primary border-none border-round p-2 text-white hover:bg-red-900"
icon="pi pi-sign-out"
@click="signOut"
/>
</div>
</div>

<div v-else>
<div v-if="!hasAssignments">
<div class="col-full text-center py-8">
<h1>{{ $t('homeParticipant.noAssignments') }}</h1>
<p class="text-center">{{ $t('homeParticipant.contactAdministrator') }}</p>

<PvButton
:label="$t('navBar.signOut')"
class="no-underline bg-primary border-none border-round p-2 text-white hover:bg-red-900"
icon="pi pi-sign-out"
@click="signOut"
<h2 v-if="userAssignments?.length == 1" class="p-float-label dropdown-container">
{{ userAssignments.at(0).publicName || userAssignments.at(0).name }}
</h2>
<div class="flex flex-row-reverse align-items-end gap-2 justify-content-between">
<div
v-if="optionalAssessments.length !== 0"
class="switch-container flex flex-row align-items-center justify-content-end mr-6 gap-2"
>
<PvInputSwitch
v-model="showOptionalAssessments"
input-id="switch-optional"
data-cy="switch-show-optional-assessments"
/>
<label for="switch-optional" class="mr-2 text-gray-500">{{
$t('homeParticipant.showOptionalAssignments')
}}</label>
</div>
</div>

<div v-else>
<h2 v-if="userAssignments?.length == 1" class="p-float-label dropdown-container">
{{ userAssignments.at(0).publicName || userAssignments.at(0).name }}
</h2>
<div class="flex flex-row-reverse align-items-end gap-2 justify-content-between">
<div
v-if="optionalAssessments.length !== 0"
class="switch-container flex flex-row align-items-center justify-content-end mr-6 gap-2"
>
<PvInputSwitch
v-model="showOptionalAssessments"
input-id="switch-optional"
data-cy="switch-show-optional-assessments"
/>
<label for="switch-optional" class="mr-2 text-gray-500">{{
$t('homeParticipant.showOptionalAssignments')
}}</label>
</div>
<div
v-if="userAssignments?.length > 0"
class="flex flex-row justify-center align-items-center p-float-label dropdown-container gap-4 w-full"
>
<div class="assignment-select-container flex flex-row justify-content-between justify-content-start">
<div class="flex flex-column align-content-start justify-content-start w-3">
<PvDropdown
v-model="selectedAdmin"
:options="sortedUserAdministrations ?? []"
:option-label="
userAssignments.every((administration) => administration.publicName) ? 'publicName' : 'name'
"
input-id="dd-assignment"
data-cy="dropdown-select-administration"
@change="toggleShowOptionalAssessments"
/>
<label for="dd-assignment">{{ $t('homeParticipant.selectAssignment') }}</label>
</div>
<div
v-if="userAssignments?.length > 0"
class="flex flex-row justify-center align-items-center p-float-label dropdown-container gap-4 w-full"
>
<div class="assignment-select-container flex flex-row justify-content-between justify-content-start">
<div class="flex flex-column align-content-start justify-content-start w-3">
<PvDropdown
v-model="selectedAdmin"
:options="sortedUserAdministrations ?? []"
:option-label="
userAssignments.every((administration) => administration.publicName) ? 'publicName' : 'name'
"
input-id="dd-assignment"
data-cy="dropdown-select-administration"
@change="toggleShowOptionalAssessments"
/>
<label for="dd-assignment">{{ $t('homeParticipant.selectAssignment') }}</label>
</div>
</div>
</div>
<div class="tabs-container">
<ParticipantSidebar :total-games="totalGames" :completed-games="completeGames" :student-info="studentInfo" />
<Transition name="fade" mode="out-in">
<GameTabs
v-if="showOptionalAssessments && userData"
:games="optionalAssessments"
:sequential="isSequential"
:user-data="userData"
/>
<GameTabs
v-else-if="requiredAssessments && userData"
:games="requiredAssessments"
:sequential="isSequential"
:user-data="userData"
/>
</Transition>
</div>
</div>
<div class="tabs-container">
<ParticipantSidebar :total-games="totalGames" :completed-games="completeGames" :student-info="studentInfo" />
<Transition name="fade" mode="out-in">
<GameTabs
v-if="showOptionalAssessments && userData"
:games="optionalAssessments"
:sequential="isSequential"
:user-data="userData"
/>
<GameTabs
v-else-if="requiredAssessments && userData"
:games="requiredAssessments"
:sequential="isSequential"
:user-data="userData"
/>
</Transition>
</div>
</div>
</div>
Expand Down Expand Up @@ -184,8 +182,8 @@ const isFetching = computed(() => {
});

const hasAssignments = computed(() => {
if (isFetching.value || isLoading.value) return false;
return assessments.value.length !== 0;
if (isLoading.value || isFetching.value) return false;
return assessments.value.length > 0;
});

async function checkConsent() {
Expand Down Expand Up @@ -371,7 +369,7 @@ watch(
[userData, selectedAdmin, userAssignments],
async ([newUserData, isSelectedAdminChanged]) => {
// If the assignments are still loading, abort.
if (isLoadingAssignments.value || isFetchingAssignments.value || !userAssignments.value.length) return;
if (isLoadingAssignments.value || isFetchingAssignments.value || !userAssignments.value?.length) return;

// If the selected admin changed, ensure consent was given before proceeding.
if (!_isEmpty(newUserData) && isSelectedAdminChanged) {
Expand Down
7 changes: 6 additions & 1 deletion src/pages/HomeSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,12 @@ const { isLoading: isLoadingClaims, data: userClaims } = useUserClaimsQuery({
const { isAdmin, isSuperAdmin, isParticipant } = useUserType(userClaims);

const isAdminUser = computed(() => isAdmin.value || isSuperAdmin.value);
const isLoading = computed(() => isLoadingClaims.value || isLoadingUserData.value);
const isLoading = computed(() => {
// @NOTE: In addition to the loading states, we also check if user data and user claims are loaded as due to the
// current application initialization flow, the userData and userClaims queries initially reset. Once this is improved
// these additional checks can be removed.
return !initialized || isLoadingUserData.value || isLoadingClaims.value || !userData.value || !userClaims.value;
});

const showConsent = ref(false);
const consentType = computed(() => {
Expand Down