Fetch profile details from ComposeDB during [username] page SSR

This commit is contained in:
Alec LaLonde
2023-02-14 14:23:25 -07:00
committed by Alec LaLonde
parent a12d7234b3
commit 250ff75bd3
5 changed files with 67 additions and 31 deletions

View File

@@ -1,4 +1,5 @@
import { Values } from './extendedProfileTypes';
import { maskFor } from './colorHelpers.js';
import { Values } from './extendedProfileTypes.js';
export const composeDBProfileFieldName = 'name';
export const composeDBProfileFieldDescription = 'description';
@@ -89,3 +90,36 @@ export type ComposeDBProfile = {
};
export type ComposeDBPayloadValue = Values<ComposeDBProfile>;
export const composeDBImageFields = [
composeDBProfileFieldAvatar,
composeDBProfileFieldBackgroundImage,
];
export const composeDBToHasuraProfile = (
composeDBProfile: ComposeDBProfile,
) => {
// todo we should be able to make this typesafe
const hasuraProfile: Record<string, unknown> = {};
// eslint-disable-next-line no-restricted-syntax
Object.entries(composeDBProfile).forEach(([key, value]) => {
const match = Object.entries(profileMapping).find(
([, composeDBKey]) => composeDBKey === key,
) as [keyof typeof profileMapping, ComposeDBField];
const hasuraKey = match[0];
// Some fields required custom translations
let hasuraValue = value;
if (value && key === composeDBProfileFieldFiveColorDisposition) {
const maskNumber = maskFor(value as string);
if (maskNumber != null) {
hasuraValue = maskNumber;
}
} else if (value && composeDBImageFields.includes(key)) {
hasuraValue = (value as ComposeDBImageMetadata).url;
}
hasuraProfile[hasuraKey] = hasuraValue;
});
return hasuraProfile;
};

View File

@@ -122,9 +122,13 @@ const SetupRolesInput: React.FC<SetupRolesInputProps> = ({
choices,
roles,
}) => {
const { register, setValue: setter, watch } = useFormContext();
const { register, setValue, watch } = useFormContext();
const mobile = useBreakpointValue({ base: true, sm: false }) ?? false;
useEffect(() => {
setValue(field, roles);
}, [roles, setValue]);
const current = watch(field, roles) as Maybe<string[]>;
if (!choices) {
@@ -144,13 +148,13 @@ const SetupRolesInput: React.FC<SetupRolesInputProps> = ({
} else {
out = [...otherRoles, role];
}
setter(field, out);
setValue(field, out);
};
const remove = ({ role }: PlayerRole) => {
if (current) {
const out = current.filter((r) => r !== role);
setter(field, out);
setValue(field, out);
}
};

View File

@@ -1,18 +1,12 @@
import {
composeDBImageFields,
composeDBImageMetadataFields,
composeDBProfileFieldAvatar,
composeDBProfileFieldBackgroundImage,
profileMapping,
} from '@metafam/utils';
export const queryPlayerProfile = (profileNodeId: string) => {
const fields = Object.values(profileMapping).map((f) => {
if (
[
composeDBProfileFieldAvatar,
composeDBProfileFieldBackgroundImage,
].includes(f)
) {
if (composeDBImageFields.includes(f)) {
return `${f} {
${composeDBImageMetadataFields.join('\n')}
}\n`;

View File

@@ -1,4 +1,8 @@
import { Maybe } from '@metafam/utils';
import {
ComposeDBProfile,
composeDBToHasuraProfile,
Maybe,
} from '@metafam/utils';
import { useComposeDB } from 'contexts/ComposeDBContext';
import { Player, PlayerProfileFragment } from 'graphql/autogen/types';
import { queryPlayerProfile } from 'graphql/composeDB/queries/profile';
@@ -57,18 +61,18 @@ export const useGetPlayerProfileFromComposeDB = (
export const hydratePlayerProfile = (
player: Player,
profileData: PlayerProfileFragment,
profileData: ComposeDBProfile,
) => {
const hasComposeDBData = Object.values(profileData).some((value) => !!value);
if (hasComposeDBData) {
// eslint-disable-next-line no-param-reassign
const hasuraProfile = composeDBToHasuraProfile(profileData);
return {
...player,
profile: {
id: 'dummy',
player,
playerId: player.id,
...profileData,
...hasuraProfile,
},
};
}

View File

@@ -1,5 +1,6 @@
import { ComposeClient } from '@composedb/client';
import { Box, Flex, LoadingState } from '@metafam/ds';
import { composeDBDefinition } from '@metafam/utils';
import { PageContainer } from 'components/Container';
import { EditableGridLayout } from 'components/EditableGridLayout';
import { PlayerSection } from 'components/Player/PlayerSection';
@@ -13,18 +14,15 @@ import {
Player,
useUpdatePlayerProfileLayoutMutation as useUpdateLayout,
} from 'graphql/autogen/types';
import { definition } from 'graphql/composeDB/autogen/definition';
import { queryPlayerProfile } from 'graphql/composeDB/queries/profile';
import { getPlayer } from 'graphql/getPlayer';
import { getTopPlayerUsernames } from 'graphql/getPlayers';
import { ComposeDBProfileQueryResult } from 'graphql/types';
import { useProfileField, useUser } from 'lib/hooks';
import { usePlayerName } from 'lib/hooks/player/usePlayerName';
import { usePlayerURL } from 'lib/hooks/player/usePlayerURL';
import { useGetPlayerProfileFromComposeDB } from 'lib/hooks/ceramic/useGetPlayerProfileFromComposeDB';
import {
hydratePlayerProfile,
parseComposeDBProfileQueryResponse,
} from 'lib/hooks/ceramic/useGetPlayerProfileFromComposeDB';
import { hydratePlayerProfile } from 'lib/hooks/ceramic/useGetPlayerProfileFromComposeDB';
import { GetStaticPaths, GetStaticPropsContext } from 'next';
import { useRouter } from 'next/router';
import Page404 from 'pages/404';
@@ -274,26 +272,28 @@ export const getStaticProps = async (
}
const player = await getPlayer(username);
let hydratedPlayer;
if (player?.ceramicProfileId) {
const composeDBClient = new ComposeClient({
ceramic: CONFIG.ceramicURL,
definition,
definition: composeDBDefinition,
});
const query = queryPlayerProfile(player.ceramicProfileId);
composeDBClient.executeQuery(query).then((response) => {
if (response.data != null) {
const composeDBProfileData = parseComposeDBProfileQueryResponse(
response.data,
);
hydratePlayerProfile(player, composeDBProfileData);
}
});
const response = await composeDBClient.executeQuery(query);
if (response.data != null) {
const composeDBProfileData = (
response.data as ComposeDBProfileQueryResult
).node;
hydratedPlayer = hydratePlayerProfile(player, composeDBProfileData);
} else if (response.errors) {
console.error(response.errors);
}
}
return {
props: {
player: player ?? null, // must be serializable.
player: hydratedPlayer ?? player ?? null, // must be serializable
key: username.toLowerCase(),
hideTopMenu: false,
},