Skip to content

Commit

Permalink
Introduce useFamilyQuery composable
Browse files Browse the repository at this point in the history
  • Loading branch information
maximilianoertel committed Sep 12, 2024
1 parent 7957c1f commit df9d503
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 14 deletions.
30 changes: 30 additions & 0 deletions src/composables/queries/useFamilyQuery.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useQuery } from '@tanstack/vue-query';
import _isEmpty from 'lodash/isEmpty';
import { computeQueryOverrides } from '@/helpers/computeQueryOverrides';
import { fetchDocById } from '@/helpers/query/utils';
import { FAMILY_QUERY_KEY } from '@/constants/queryKeys';
import { FIRESTORE_COLLECTIONS } from '@/constants/firebase';

/**
* Family Query
*
* Query designed to fetch a single family record by its ID.
*
* @param {String} familyId – The ID of the family to fetch.
* @param {QueryOptions|undefined} queryOptions – Optional TanStack query options.
* @returns {UseQueryResult} The TanStack query result.
*/
const useFamilyQuery = (familyId, queryOptions = undefined) => {
// Ensure all necessary data is loaded before enabling the query.
const conditions = [() => !_isEmpty(familyId)];
const { isQueryEnabled, options } = computeQueryOverrides(conditions, queryOptions);

return useQuery({
queryKey: [FAMILY_QUERY_KEY, familyId],
queryFn: () => fetchDocById(FIRESTORE_COLLECTIONS.FAMILIES, familyId),
enabled: isQueryEnabled,
...options,
});
};

export default useFamilyQuery;
69 changes: 69 additions & 0 deletions src/composables/queries/useFamilyQuery.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import * as VueQuery from '@tanstack/vue-query';
import { nanoid } from 'nanoid';
import { withSetup } from '@/test-support/withSetup.js';
import { fetchDocById } from '@/helpers/query/utils';
import useFamilyQuery from './useFamilyQuery';

vi.mock('@/helpers/query/utils', () => ({
fetchDocById: vi.fn().mockImplementation(() => []),
}));

vi.mock('@tanstack/vue-query', async (getModule) => {
const original = await getModule();
return {
...original,
useQuery: vi.fn().mockImplementation(original.useQuery),
};
});

describe('useFamilyQuery', () => {
let queryClient;

beforeEach(() => {
queryClient = new VueQuery.QueryClient();
});

afterEach(() => {
queryClient?.clear();
});

it('should call query with correct parameters when fetching a specific family', () => {
const familyId = nanoid();

vi.spyOn(VueQuery, 'useQuery');

withSetup(() => useFamilyQuery(familyId), {
plugins: [[VueQuery.VueQueryPlugin, { queryClient }]],
});

expect(VueQuery.useQuery).toHaveBeenCalledWith({
queryKey: ['family', familyId],
queryFn: expect.any(Function),
enabled: expect.objectContaining({
_value: true,
}),
});

expect(fetchDocById).toHaveBeenCalledWith('families', familyId);
});

it('should allow the query to be disabled via the passed query options', () => {
const familyId = nanoid();
const queryOptions = { enabled: false };

vi.spyOn(VueQuery, 'useQuery');

withSetup(() => useFamilyQuery(familyId, queryOptions), {
plugins: [[VueQuery.VueQueryPlugin, { queryClient }]],
});

expect(VueQuery.useQuery).toHaveBeenCalledWith({
queryKey: ['family', familyId],
queryFn: expect.any(Function),
enabled: expect.objectContaining({
_value: false,
}),
});
});
});
1 change: 1 addition & 0 deletions src/constants/queryKeys.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const DISTRICT_QUERY_KEY = 'district';
export const DISTRICTS_QUERY_KEY = 'districts';
export const DISTRICT_SCHOOLS_QUERY_KEY = 'district-schools';
export const DSGF_ORGS_QUERY_KEY = 'dsgf-orgs';
export const FAMILY_QUERY_KEY = 'family';
export const GROUP_QUERY_KEY = 'group';
export const GROUPS_QUERY_KEY = 'groups';
export const LEGAL_DOCS_QUERY_KEY = 'legal-docs';
Expand Down
28 changes: 14 additions & 14 deletions src/pages/ScoreReport.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@
<section class="main-body">
<div>
<div class="">
<div v-if="isLoadingOrgInfo" class="loading-wrapper">
<div v-if="isLoadingOrgData" class="loading-wrapper">
<AppSpinner style="margin: 0.3rem 0rem" />
<div class="uppercase text-sm text-gray-600 font-light">Loading Org Info</div>
</div>

<div v-if="orgInfo && administrationData" id="at-a-glance-charts">
<div v-if="orgData && administrationData" id="at-a-glance-charts">
<div class="flex justify-content-between align-items-center">
<div class="flex flex-column align-items-start gap-2">
<div>
<div class="uppercase font-light text-gray-500 text-xs">{{ props.orgType }} Score Report</div>
<div class="report-title">
{{ _toUpper(orgInfo?.name) }}
{{ _toUpper(orgData?.name) }}
</div>
</div>
<div>
Expand Down Expand Up @@ -234,7 +234,7 @@
:runs="computeAssignmentAndRunData.runsByTaskId[taskId]"
:org-type="orgType"
:org-id="orgId"
:org-info="orgInfo"
:org-info="orgData"
:administration-info="administrationData"
/>
</div>
Expand Down Expand Up @@ -302,12 +302,14 @@ import { useAuthStore } from '@/store/auth';
import { getGrade } from '@bdelab/roar-utils';
import { exportCsv } from '@/helpers/query/utils';
import { getTitle } from '@/helpers/query/administrations';
import useUserType from '@/composables/useUserType';
import useUserClaimsQuery from '@/composables/queries/useUserClaimsQuery';
import useAdministrationsQuery from '@/composables/queries/useAdministrationsQuery';
import useDistrictQuery from '@/composables/queries/useDistrictQuery';
import useSchoolQuery from '@/composables/queries/useSchoolQuery';
import useClassQuery from '@/composables/queries/useClassQuery';
import useGroupQuery from '@/composables/queries/useGroupQuery';
import useFamilyQuery from '@/composables/queries/useFamilyQuery';
import useDistrictSchoolsQuery from '@/composables/queries/useDistrictSchoolsQuery';
import useAdministrationAssignmentsQuery from '@/composables/queries/useAdministrationAssignmentsQuery';
import {
Expand Down Expand Up @@ -416,7 +418,7 @@ const handleExportToPdf = async () => {
}
doc.save(
`roar-scores-${_kebabCase(getTitle(administrationData.value, isSuperAdmin.value))}-${_kebabCase(
orgInfo.value.name,
orgData.value.name,
)}.pdf`,
);
exportLoading.value = false;
Expand Down Expand Up @@ -447,12 +449,11 @@ const filterSchools = ref([]);
const filterGrades = ref([]);
const pageLimit = ref(10);

const { isLoading: isLoadingClaims, data: userClaims } = useUserClaimsQuery({
const { data: userClaims } = useUserClaimsQuery({
enabled: initialized,
});

const claimsLoaded = computed(() => !isLoadingClaims.value);
const isSuperAdmin = computed(() => Boolean(userClaims.value?.claims?.super_admin));
const { isSuperAdmin } = useUserType(userClaims);

const { data: administrationData } = useAdministrationsQuery([props.administrationId], {
enabled: initialized,
Expand All @@ -475,14 +476,13 @@ const orgQuery = computed(() => {
case SINGULAR_ORG_TYPES.GROUPS:
return useGroupQuery(props.orgId, queryOptions);
case SINGULAR_ORG_TYPES.FAMILIES:
throw new Error('Families are not yet supported in this report.');
// return useFamiliesQuery(props.orgId, queryOptions)
return useFamilyQuery(props.orgId, queryOptions);
default:
return null;
throw new Error(`Unsupported org type: ${props.orgType}`);
}
});

const { data: orgInfo, isLoading: isLoadingOrgInfo } = orgQuery.value;
const { data: orgData, isLoading: isLoadingOrgData } = orgQuery.value;

const {
isLoading: isLoadingAssignments,
Expand Down Expand Up @@ -944,7 +944,7 @@ const exportSelected = (selectedRows) => {
exportCsv(
computedExportData,
`roar-scores-${_kebabCase(getTitle(administrationData.value, isSuperAdmin.value))}-${_kebabCase(
orgInfo.value.name,
orgData.value.name,
)}-selected.csv`,
);
return;
Expand Down Expand Up @@ -1018,7 +1018,7 @@ const exportAll = async () => {
exportCsv(
computedExportData,
`roar-scores-${_kebabCase(getTitle(administrationData.value, isSuperAdmin.value))}-${_kebabCase(
orgInfo.value.name,
orgData.value.name,
)}.csv`,
);
return;
Expand Down

0 comments on commit df9d503

Please sign in to comment.