Skip to content

Commit

Permalink
src/stores: load registration options data to registerChallenge store (
Browse files Browse the repository at this point in the history
…#806)

* refactor loading organizations from FormSelectOrganization

* refactor saving teams into the store

* update new team order in list (first)

* refactor saving merch items into the registerChallenge store

* update docs

* consolidate mapTeamToOption function

---------

Co-authored-by: Šimon Macek <[email protected]>
  • Loading branch information
maceksimon and Šimon Macek authored Dec 26, 2024
1 parent da8c2b0 commit 38420c6
Show file tree
Hide file tree
Showing 7 changed files with 165 additions and 65 deletions.
4 changes: 2 additions & 2 deletions src/components/__tests__/FormFieldSelectTable.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ describe('<FormFieldSelectTable>', () => {
...apiGetTeamsResponseNext.results,
];
// map teams to options
const { mapTeamsToOptions } = useApiGetTeams();
optionsTeams = mapTeamsToOptions(teams);
const { mapTeamToOption } = useApiGetTeams();
optionsTeams = teams.map(mapTeamToOption);
});
});
});
Expand Down
44 changes: 30 additions & 14 deletions src/components/form/FormFieldListMerch.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,11 @@ import FormFieldRadioRequired from '../form/FormFieldRadioRequired.vue';
import SliderMerch from './SliderMerch.vue';
// composables
import { useApiGetMerchandise } from '../../composables/useApiGetMerchandise';
import { i18n } from '../../boot/i18n';
// stores
import { useRegisterChallengeStore } from 'src/stores/registerChallenge';
// enums
import { Gender } from '../types/Profile';
Expand All @@ -77,16 +79,10 @@ export default defineComponent({
// selected options
const selectedGender = ref<string>(Gender.female);
const selectedSize = ref<number | null>(null);
const selectedOption = computed<MerchandiseItem | null>(
(): MerchandiseItem | null => {
return (
merchandiseItems.value.find(
(item) => item.id === selectedSize.value,
) || null
);
},
);
const selectedSize = computed<number | null>({
get: () => registerChallengeStore.getMerchId,
set: (value: number | null) => registerChallengeStore.setMerchId(value),
});
const phone = ref<string>('');
const trackDelivery = ref<boolean>(false);
const newsletter = ref<boolean>(false);
Expand All @@ -98,14 +94,34 @@ export default defineComponent({
// get merchandise data
const logger = inject('vuejs3-logger') as Logger | null;
const { merchandiseCards, merchandiseItems, loadMerchandise, isLoading } =
useApiGetMerchandise(logger);
const registerChallengeStore = useRegisterChallengeStore();
// load merchandise on mount
onMounted(async () => {
await loadMerchandise();
await registerChallengeStore.loadMerchandiseToStore(logger);
});
const merchandiseItems = computed(
() => registerChallengeStore.getMerchandiseItems,
);
const merchandiseCards = computed(
() => registerChallengeStore.getMerchandiseCards,
);
const isLoading = computed(
() => registerChallengeStore.isLoadingMerchandise,
);
const selectedOption = computed<MerchandiseItem | null>(
(): MerchandiseItem | null => {
if (!merchandiseItems.value) return null;
return (
merchandiseItems.value.find(
(item) => item.id === selectedSize.value,
) || null
);
},
);
// computed properties for gender-specific options
const optionsFemale = computed((): MerchandiseCard[] => {
return Object.values(merchandiseCards.value[Gender.female] || {});
Expand Down
44 changes: 23 additions & 21 deletions src/components/form/FormSelectOrganization.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,20 @@ import { defineComponent, computed, inject, watch, ref } from 'vue';
import FormFieldSelectTable from '../form/FormFieldSelectTable.vue';
import FormFieldCompanyAddress from '../form/FormFieldCompanyAddress.vue';
// composables
import { useApiGetOrganizations } from 'src/composables/useApiGetOrganizations';
// enums
import { OrganizationLevel, OrganizationType } from '../types/Organization';
// types
import type { FormSelectOption } from '../types/Form';
import type { Logger } from '../types/Logger';
import type { OrganizationOption } from '../types/Organization';
import type { PostOrganizationResponse } from '../types/apiOrganization';
// stores
import { useRegisterChallengeStore } from 'src/stores/registerChallenge';
// composables
import { useApiGetOrganizations } from 'src/composables/useApiGetOrganizations';
export default defineComponent({
name: 'FormSelectOrganization',
components: {
Expand All @@ -51,11 +50,8 @@ export default defineComponent({
null,
);
const opts = ref<FormSelectOption[]>([]);
const { options, organizations, isLoading, loadOrganizations } =
useApiGetOrganizations(logger);
const registerChallengeStore = useRegisterChallengeStore();
const { mapOrganizationToOption } = useApiGetOrganizations(logger);
const organizationType = computed(
(): OrganizationType => registerChallengeStore.getOrganizationType,
Expand All @@ -76,16 +72,23 @@ export default defineComponent({
registerChallengeStore.setSubsidiaryId(value),
});
const isLoading = computed(
() => registerChallengeStore.isLoadingOrganizations,
);
const organizations = computed(
() => registerChallengeStore.getOrganizations,
);
const options = computed<FormSelectOption[]>(() =>
organizations.value.map(mapOrganizationToOption),
);
watch(
organizationType,
(newValue: OrganizationType) => {
async (newValue: OrganizationType) => {
logger?.debug(`Organization type updated to <${newValue}>`);
if (newValue) {
loadOrganizations(newValue).then(() => {
logger?.info('All organizations data was loaded from the API.');
// Lazy loading
opts.value = options.value;
});
await registerChallengeStore.loadOrganizationsToStore(logger);
logger?.info('All organizations data was loaded from the API.');
}
},
{ immediate: true },
Expand All @@ -104,23 +107,22 @@ export default defineComponent({
* @param {PostOrganizationResponse} data - The new organization data.
*/
const onCreateOption = (data: PostOrganizationResponse) => {
const newOrganization: OrganizationOption = data;
const newOrganization = data;
logger?.debug(
`Add new organization to organizations options <${JSON.stringify(newOrganization, null, 2)}>.`,
);
organizations.value.unshift(newOrganization);
const updatedOrganizations = [newOrganization, ...organizations.value];
registerChallengeStore.setOrganizations(updatedOrganizations);
logger?.debug(
`Organizations options updated to <${JSON.stringify(organizations.value, null, 2)}>.`,
`Organizations options updated to <${JSON.stringify(updatedOrganizations, null, 2)}>.`,
);
// lazy load options array with prepended new organization
opts.value = options.value;
};
return {
formFieldSelectTableRef,
isLoading,
organizationId,
opts,
options,
subsidiaryId,
OrganizationLevel,
organizationType,
Expand All @@ -137,7 +139,7 @@ export default defineComponent({
ref="formFieldSelectTableRef"
v-model="organizationId"
:loading="isLoading"
:options="opts"
:options="options"
:organization-level="OrganizationLevel.organization"
:organization-type="organizationType"
:data-organization-type="organizationType"
Expand Down
29 changes: 16 additions & 13 deletions src/components/form/FormSelectTeam.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*/
// libraries
import { computed, defineComponent, inject, watch, ref } from 'vue';
import { computed, defineComponent, inject, watch } from 'vue';
// components
import FormFieldSelectTable from './FormFieldSelectTable.vue';
Expand All @@ -34,6 +34,7 @@ import { useRegisterChallengeStore } from 'src/stores/registerChallenge';
import type { Logger } from '../types/Logger';
import type { OrganizationTeam } from '../types/Organization';
import type { TeamPostApiResponse } from '../types/ApiTeam';
import type { FormSelectTableOption } from '../types/Form';
export default defineComponent({
name: 'FormSelectTeam',
Expand All @@ -42,8 +43,8 @@ export default defineComponent({
},
setup() {
const logger = inject('vuejs3-logger') as Logger | null;
const registerChallengeStore = useRegisterChallengeStore();
const { mapTeamToOption } = useApiGetTeams(logger);
const team = computed({
get: () => {
Expand All @@ -54,21 +55,22 @@ export default defineComponent({
},
});
const { options, isLoading, teams, loadTeams } = useApiGetTeams(logger);
const opts = ref([]);
const isLoading = computed(() => registerChallengeStore.isLoadingTeams);
const teams = computed(() => registerChallengeStore.getTeams);
const options = computed<FormSelectTableOption[]>(() =>
teams.value.map(mapTeamToOption),
);
// load teams when subsidiary ID changes
watch(
() => registerChallengeStore.getSubsidiaryId,
(newValue: number | null) => {
async (newValue: number | null) => {
logger?.debug(
`Register challenge store subsidiary ID changed to <${newValue}>.`,
);
if (newValue) {
logger?.info('Loading teams.');
// Lazy loading
loadTeams(newValue).then(() => {
opts.value = options;
});
await registerChallengeStore.loadTeamsToStore(logger);
}
},
{ immediate: true },
Expand All @@ -77,7 +79,7 @@ export default defineComponent({
/**
* Handle option created event
* When option is created in the child component, push the result into
* the `teams` array (options are computed from `teams` array).
* the `teams` array in the `registerChallenge` store.
* @param {TeamPostApiResponse} data - Team data
* @returns {void}
*/
Expand All @@ -88,12 +90,13 @@ export default defineComponent({
subsidiary: registerChallengeStore.getSubsidiaryId as number,
members: [],
};
teams.value.push(newTeam);
const updatedTeams = [newTeam, ...teams.value];
registerChallengeStore.setTeams(updatedTeams);
};
return {
isLoading,
opts,
options,
team,
OrganizationLevel,
onOptionCreated,
Expand All @@ -112,7 +115,7 @@ export default defineComponent({
<form-field-select-table
v-model="team"
:organization-level="OrganizationLevel.team"
:options="opts.value"
:options="options"
:loading="isLoading"
@create:option="onOptionCreated"
data-cy="form-select-table-team"
Expand Down
2 changes: 1 addition & 1 deletion src/components/types/Organization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,5 +87,5 @@ export type useApiGetTeamsReturn = {
options: Ref<FormSelectTableOption[]>;
isLoading: Ref<boolean>;
loadTeams: (subsidiaryId: number) => Promise<void>;
mapTeamsToOptions: (teams: OrganizationTeam[]) => FormSelectTableOption[];
mapTeamToOption: (team: OrganizationTeam) => FormSelectTableOption;
};
22 changes: 9 additions & 13 deletions src/composables/useApiGetTeams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,27 +115,23 @@ export const useApiGetTeams = (logger: Logger | null): useApiGetTeamsReturn => {

// Push results to options
const options = computed<FormSelectTableOption[]>(() => {
return mapTeamsToOptions(teams.value);
return teams.value.map(mapTeamToOption);
});

const mapTeamsToOptions = (
teams: OrganizationTeam[],
): FormSelectTableOption[] => {
return teams.map((team: OrganizationTeam): FormSelectTableOption => {
return {
label: team.name,
value: team.id,
members: team.members,
maxMembers: challengeStore.getMaxTeamMembers,
};
});
const mapTeamToOption = (team: OrganizationTeam): FormSelectTableOption => {
return {
label: team.name,
value: team.id,
members: team.members,
maxMembers: challengeStore.getMaxTeamMembers,
};
};

return {
teams,
options,
isLoading,
loadTeams,
mapTeamsToOptions,
mapTeamToOption,
};
};
Loading

0 comments on commit 38420c6

Please sign in to comment.