diff --git a/packages/utils/src/composeDBProfileFields.ts b/packages/utils/src/composeDBProfileFields.ts index 350c65d5..ccdb3f1a 100644 --- a/packages/utils/src/composeDBProfileFields.ts +++ b/packages/utils/src/composeDBProfileFields.ts @@ -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; + +export const composeDBImageFields = [ + composeDBProfileFieldAvatar, + composeDBProfileFieldBackgroundImage, +]; + +export const composeDBToHasuraProfile = ( + composeDBProfile: ComposeDBProfile, +) => { + // todo we should be able to make this typesafe + const hasuraProfile: Record = {}; + // 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; +}; diff --git a/packages/web/components/Setup/SetupRoles.tsx b/packages/web/components/Setup/SetupRoles.tsx index a3166cc8..00b70840 100644 --- a/packages/web/components/Setup/SetupRoles.tsx +++ b/packages/web/components/Setup/SetupRoles.tsx @@ -122,9 +122,13 @@ const SetupRolesInput: React.FC = ({ 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; if (!choices) { @@ -144,13 +148,13 @@ const SetupRolesInput: React.FC = ({ } 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); } }; diff --git a/packages/web/graphql/composeDB/queries/profile.ts b/packages/web/graphql/composeDB/queries/profile.ts index 06bda89f..4566bd73 100644 --- a/packages/web/graphql/composeDB/queries/profile.ts +++ b/packages/web/graphql/composeDB/queries/profile.ts @@ -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`; diff --git a/packages/web/lib/hooks/ceramic/useGetPlayerProfileFromComposeDB.ts b/packages/web/lib/hooks/ceramic/useGetPlayerProfileFromComposeDB.ts index 42271498..1156f74b 100644 --- a/packages/web/lib/hooks/ceramic/useGetPlayerProfileFromComposeDB.ts +++ b/packages/web/lib/hooks/ceramic/useGetPlayerProfileFromComposeDB.ts @@ -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, }, }; } diff --git a/packages/web/pages/player/[username].tsx b/packages/web/pages/player/[username].tsx index 4b50ca6b..a7688f0f 100644 --- a/packages/web/pages/player/[username].tsx +++ b/packages/web/pages/player/[username].tsx @@ -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, },