2025-05-28 15:36:51 -07:00

181 lines
4.1 KiB
TypeScript

import { createSelector } from "reselect";
import { DefaultCharacterName } from "~/constants";
import config from "../../config";
import {
AppData,
CharacterData,
QueryResponseData,
ShortCharacterContract,
SortTypeEnum,
} from "../../types";
const BASE_PATHNAME = config.basePathname;
export const getCharacter = (state: CharacterData) => state || {};
export const getId = createSelector([getCharacter], ({ id }) => id);
// Username is added by MyCharactersListing since it comes from the JWT, not the API
export const getUsername = createSelector(
[getCharacter],
({ userName }) => userName
);
export const getName = createSelector(
[getCharacter],
({ name }) => name || DefaultCharacterName
);
export const getLevel = createSelector([getCharacter], ({ level }) => level);
export const getStatus = createSelector([getCharacter], ({ status }) => status);
export const getStatusSlug = createSelector(
[getCharacter],
({ statusSlug }) => statusSlug
);
export const getClassDescription = createSelector(
[getCharacter],
({ classDescription }) => classDescription
);
export const getRaceName = createSelector(
[getCharacter],
({ raceName }) => raceName
);
export const getSecondaryInfo = createSelector(
[getCharacter],
({ characterSecondaryInfo }) => characterSecondaryInfo
);
export const getAvatarUrl = createSelector(
[getCharacter],
({ avatarUrl }) => avatarUrl
);
export const getBackdropUrl = createSelector(
[getCharacter],
({ backdropUrl }) => backdropUrl
);
export const getCoverImageUrl = createSelector(
[getCharacter],
({ coverImageUrl }) => coverImageUrl
);
export const getCreatedDate = createSelector(
[getCharacter],
({ createdDate }) => createdDate
);
export const getLastModifiedDate = createSelector(
[getCharacter],
({ lastModifiedDate }) => lastModifiedDate
);
export const getIsAssigned = createSelector(
[getCharacter],
({ isAssigned }) => isAssigned
);
export const getCampaignId = createSelector(
[getCharacter],
({ campaignId }) => campaignId
);
export const isInCampaign = createSelector([getCampaignId], Boolean);
export const getCampaignName = createSelector(
[getCharacter],
({ campaignName }) => campaignName
);
export const getCampaignDetailsLink = createSelector(
[getCampaignId],
(id) => `${config.ddbBaseUrl}/campaigns/${id}`
);
export const getDetailsLink = createSelector(
[getUsername, getId],
(username, id) => `${BASE_PATHNAME}/${id}`
);
export const getEditLink = createSelector(
[getUsername, getId],
(username, id) => `${BASE_PATHNAME}/${id}/builder/home/basic`
);
export const getSearchableTerms = createSelector(
[
isInCampaign,
getLevel,
getName,
getClassDescription,
getRaceName,
getCampaignName,
],
(isInCampaign, level, name, classDescription, raceName, campaignName) =>
[
isInCampaign && "campaign",
level.toString(),
`level ${level}`,
`lvl ${level}`,
name,
classDescription,
raceName,
campaignName,
].filter(Boolean)
);
// Analytics labels to use if a match is found in getSearchableTerms (by index)
export const getSearchableTermsAnalyticsLabel = createSelector(
[isInCampaign, getLevel],
(isInCampaign, level) =>
[
isInCampaign && "campaign",
"# (level)",
`level #`,
`lvl #`,
"name",
"class description",
"race name",
"campaign name",
].filter(Boolean)
);
export const generateCharacter = (
character: ShortCharacterContract,
userName: string | null
): CharacterData => {
return {
...character,
userName,
};
};
export const generateAppData = (
userName: string | null,
data?: QueryResponseData
): AppData => {
const characters = data?.data?.characters || [];
return {
characters: characters.map((character) =>
generateCharacter(character, userName)
),
maxCharacterSlotsAllowed: data?.data?.characterSlotLimit || null,
hasLockedCharacters: data?.data?.canUnlockCharacters || false,
};
};
export const SortByPropMap = {
[SortTypeEnum.Created]: getCreatedDate,
[SortTypeEnum.Level]: getLevel,
[SortTypeEnum.Modified]: getLastModifiedDate,
[SortTypeEnum.Name]: getName,
};