diff --git a/hasura/metadata/tables.yaml b/hasura/metadata/tables.yaml index 3a4ba050..1bf8a90f 100644 --- a/hasura/metadata/tables.yaml +++ b/hasura/metadata/tables.yaml @@ -2,6 +2,32 @@ schema: public name: AccountType is_enum: true +- table: + schema: public + name: ColorAspect + array_relationships: + - name: players + using: + foreign_key_constraint_on: + column: color_mask + table: + schema: public + name: player + select_permissions: + - role: player + permission: + columns: + - mask + - name + - description + filter: {} + - role: public + permission: + columns: + - mask + - description + - name + filter: {} - table: schema: public name: EnneagramType @@ -207,6 +233,9 @@ schema: public name: player object_relationships: + - name: ColorAspect + using: + foreign_key_constraint_on: color_mask - name: EnneagramType using: foreign_key_constraint_on: enneagram @@ -291,6 +320,7 @@ permission: columns: - availability_hours + - color_mask - enneagram - ethereum_address - id @@ -298,21 +328,22 @@ - rank - role - sc_identity_id - - total_xp - timezone + - total_xp - username filter: {} - role: public permission: columns: - availability_hours + - color_mask - enneagram - ethereum_address - id - rank - role - - total_xp - timezone + - total_xp - username filter: {} update_permissions: @@ -320,6 +351,7 @@ permission: columns: - availability_hours + - color_mask - enneagram - player_type_id - role diff --git a/hasura/migrations/1616101057636_create-mtg-color-table/down.sql b/hasura/migrations/1616101057636_create-mtg-color-table/down.sql new file mode 100644 index 00000000..8553cce7 --- /dev/null +++ b/hasura/migrations/1616101057636_create-mtg-color-table/down.sql @@ -0,0 +1,9 @@ +ALTER TABLE public.player + DROP CONSTRAINT player_color_mask_fkey +; + +ALTER TABLE public.player + DROP COLUMN color_mask +; + +DROP TABLE public."ColorAspect"; \ No newline at end of file diff --git a/hasura/migrations/1616101057636_create-mtg-color-table/up.sql b/hasura/migrations/1616101057636_create-mtg-color-table/up.sql new file mode 100644 index 00000000..b3a7f15f --- /dev/null +++ b/hasura/migrations/1616101057636_create-mtg-color-table/up.sql @@ -0,0 +1,88 @@ +CREATE TABLE public."ColorAspect" ( + mask integer PRIMARY KEY, + name text UNIQUE NOT NULL, + description text NULL +); + +-- This is the listing of all the possible color combinations. +-- The names come from largely from: +-- https://humanparts.medium.com/the-mtg-color-wheel-c9700a7cf36d +-- The base color names were created as a part of the initial +-- design, and some of the three color ones are adjectives to fit +-- with Sabien's short text desriptions. +-- The original Magic descriptions and pictures are copyprotected. + +INSERT INTO "ColorAspect" (mask, name) VALUES + /*WUBRG*/ + (/*00000*/ 0, 'Colorless'), + (/*00001*/ 'x01'::bit(8)::int, 'Balance'), + (/*00010*/ 'x02'::bit(8)::int, 'Chaos'), + (/*00011*/ 'x03'::bit(8)::int, 'Authenticity'), + (/*00100*/ 'x04'::bit(8)::int, 'Ambition'), + (/*00101*/ 'x05'::bit(8)::int, 'Profanity'), + (/*00110*/ 'x06'::bit(8)::int, 'Independence'), + (/*00111*/ 'x07'::bit(8)::int, 'Realism'), + (/*01000*/ 'x08'::bit(8)::int, 'Wisdom'), + (/*01001*/ 'x09'::bit(8)::int, 'Truth-Seeking'), + (/*01010*/ 'x0A'::bit(8)::int, 'Creativity'), + (/*01011*/ 'x0B'::bit(8)::int, 'Savagery'), + (/*01100*/ 'x0C'::bit(8)::int, 'Growth Mindset'), + (/*01101*/ 'x0D'::bit(8)::int, 'Ruthlessness'), + (/*01110*/ 'x0E'::bit(8)::int, 'Iconoclasm'), + (/*01111*/ 'x0F'::bit(8)::int, 'Turmoil'), + (/*10000*/ 'x10'::bit(8)::int, 'Justice'), + (/*10001*/ 'x11'::bit(8)::int, 'Community'), + (/*10010*/ 'x12'::bit(8)::int, 'Heroism'), + (/*10011*/ 'x13'::bit(8)::int, 'Contentment'), + (/*10100*/ 'x14'::bit(8)::int, 'Tribalism'), + (/*10101*/ 'x15'::bit(8)::int, 'Endurance'), + (/*10110*/ 'x16'::bit(8)::int, 'Speed'), + (/*10111*/ 'x17'::bit(8)::int, 'Aggression'), + (/*11000*/ 'x18'::bit(8)::int, 'Structure'), + (/*11001*/ 'x19'::bit(8)::int, 'Complacence'), + (/*11010*/ 'x1A'::bit(8)::int, 'Cunning'), + (/*11011*/ 'x1B'::bit(8)::int, 'Altruism'), + (/*11100*/ 'x1C'::bit(8)::int, 'Dedication'), + (/*11101*/ 'x1D'::bit(8)::int, 'Growth'), + (/*11110*/ 'x1E'::bit(8)::int, 'Artifice'), + (/*11111*/ 'x1F'::bit(8)::int, 'Wholeness') +; + +-- The descriptions of the five base colors come from +-- Sabien's article. + +UPDATE "ColorAspect" + SET description = 'Harmony through acceptance…' + WHERE name = 'Balance' +; +UPDATE "ColorAspect" + SET description = 'Peace through order…' + WHERE name = 'Justice' +; +UPDATE "ColorAspect" + SET description = 'Perfection through knowledge…' + WHERE name = 'Wisdom' +; +UPDATE "ColorAspect" + SET description = 'Satisfaction through ruthlessness…' + WHERE name = 'Ambition' +; +UPDATE "ColorAspect" + SET description = 'Freedom through action…' + WHERE name = 'Chaos' +; + +-- +-- Add color_mask integer to player and set as a foreign key +-- + +ALTER TABLE public.player + ADD COLUMN color_mask integer +; + +ALTER TABLE public.player + ADD CONSTRAINT player_color_mask_fkey + FOREIGN KEY (color_mask) + REFERENCES public."ColorAspect"(mask) + ON UPDATE restrict ON DELETE restrict +; \ No newline at end of file diff --git a/packages/design-system/src/SVG.tsx b/packages/design-system/src/SVG.tsx new file mode 100644 index 00000000..53e55389 --- /dev/null +++ b/packages/design-system/src/SVG.tsx @@ -0,0 +1,3 @@ +import { chakra } from '@chakra-ui/react'; + +export const SVG = chakra('svg'); diff --git a/packages/design-system/src/index.ts b/packages/design-system/src/index.ts index a509b910..88b2dc30 100644 --- a/packages/design-system/src/index.ts +++ b/packages/design-system/src/index.ts @@ -9,6 +9,7 @@ export { MetaTile, MetaTileBody, MetaTileHeader } from './MetaTile'; export { ResponsiveText } from './ResponsiveText'; export { SelectSearch, selectStyles } from './SelectSearch'; export { SelectTimeZone } from './SelectTimeZone'; +export { SVG } from './SVG' export { theme as MetaTheme } from './theme'; export { H1, P } from './typography'; export { EmailIcon } from '@chakra-ui/icons'; @@ -20,6 +21,7 @@ export { ButtonGroup, ButtonProps, Center, + ChakraProps, ChakraProvider, Container, CSSReset, diff --git a/packages/web/assets/colors/Ambition.svg b/packages/web/assets/colors/Ambition.svg new file mode 100644 index 00000000..9d2e4820 --- /dev/null +++ b/packages/web/assets/colors/Ambition.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/packages/web/assets/colors/Balance.svg b/packages/web/assets/colors/Balance.svg new file mode 100644 index 00000000..4e59e78f --- /dev/null +++ b/packages/web/assets/colors/Balance.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/packages/web/assets/colors/Chaos.svg b/packages/web/assets/colors/Chaos.svg new file mode 100644 index 00000000..0f2b4f10 --- /dev/null +++ b/packages/web/assets/colors/Chaos.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/packages/web/assets/colors/Justice.svg b/packages/web/assets/colors/Justice.svg new file mode 100644 index 00000000..b56fd1fc --- /dev/null +++ b/packages/web/assets/colors/Justice.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/packages/web/assets/colors/Wisdom.svg b/packages/web/assets/colors/Wisdom.svg new file mode 100644 index 00000000..2492feba --- /dev/null +++ b/packages/web/assets/colors/Wisdom.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/packages/web/assets/achiever.png b/packages/web/assets/enneagram/achiever.png similarity index 100% rename from packages/web/assets/achiever.png rename to packages/web/assets/enneagram/achiever.png diff --git a/packages/web/assets/challenger.png b/packages/web/assets/enneagram/challenger.png similarity index 100% rename from packages/web/assets/challenger.png rename to packages/web/assets/enneagram/challenger.png diff --git a/packages/web/assets/enthusiast.png b/packages/web/assets/enneagram/enthusiast.png similarity index 100% rename from packages/web/assets/enthusiast.png rename to packages/web/assets/enneagram/enthusiast.png diff --git a/packages/web/assets/helper.png b/packages/web/assets/enneagram/helper.png similarity index 100% rename from packages/web/assets/helper.png rename to packages/web/assets/enneagram/helper.png diff --git a/packages/web/assets/individualist.png b/packages/web/assets/enneagram/individualist.png similarity index 100% rename from packages/web/assets/individualist.png rename to packages/web/assets/enneagram/individualist.png diff --git a/packages/web/assets/investigator.png b/packages/web/assets/enneagram/investigator.png similarity index 100% rename from packages/web/assets/investigator.png rename to packages/web/assets/enneagram/investigator.png diff --git a/packages/web/assets/loyalist.png b/packages/web/assets/enneagram/loyalist.png similarity index 100% rename from packages/web/assets/loyalist.png rename to packages/web/assets/enneagram/loyalist.png diff --git a/packages/web/assets/peacemaker.png b/packages/web/assets/enneagram/peacemaker.png similarity index 100% rename from packages/web/assets/peacemaker.png rename to packages/web/assets/enneagram/peacemaker.png diff --git a/packages/web/assets/reformer.png b/packages/web/assets/enneagram/reformer.png similarity index 100% rename from packages/web/assets/reformer.png rename to packages/web/assets/enneagram/reformer.png diff --git a/packages/web/components/Player/ColorBar.tsx b/packages/web/components/Player/ColorBar.tsx new file mode 100644 index 00000000..b30606a1 --- /dev/null +++ b/packages/web/components/Player/ColorBar.tsx @@ -0,0 +1,137 @@ +/* eslint no-bitwise: "off" */ + +import { Box, ChakraProps, Flex, SVG } from '@metafam/ds'; +import { FlexContainer } from 'components/Container'; +import { + colors, + getPersonalityInfo, + images, +} from 'graphql/getPersonalityInfo'; +import { PersonalityOption } from 'graphql/types'; +import React, { useEffect, useState } from 'react'; + +// This is just verbose, so I am pulling it out to +// save space in the main template +const maskImageStyle = ( + ({ url }: { url: string }): Record => ({ + maskImage: `url(${url})`, + maskSize: 'contain', + maskPosition: 'center', + maskRepeat: 'no-repeat', + WebkitMaskImage: `url(${url})`, + WebkitMaskSize: 'contain', + WebkitMaskPosition: 'center', + WebkitMaskRepeat: 'no-repeat', + }) +); + +/* The color bar is below the attribute selection screen, + * and shows an equally proportioned set of colors with + * monochrome icons above them and a term for the + * combination below. + */ +export const ColorBar = ( + ( + { mask = 0, ...props }: + ChakraProps & { mask: number | undefined }, + ): JSX.Element => { + const [parts, setParts] = ( + useState>([]) + ); + const [types, setTypes] = ( + useState>({}) + ); + const load = async () => { + const { parts: ps, types: ts } = ( + await getPersonalityInfo() + ) + setParts(ps) + setTypes(ts) + } + + useEffect(() => { load() }, []); + + return ( + + + {parts.map((part) => { + const set = ((mask & part.mask) !== 0) + + return ( + !set // if the bit isn't set + ? ( null ) // return null for map to work + : ( + + + + ) + ) + })} + + + {parts.map((part) => ( + ((mask & part.mask) === 0) + ? ( null ) + : ( + + + + + + + + + + + + + ) + ))} + + + {types?.[mask]?.name} + + + ) + } +); \ No newline at end of file diff --git a/packages/web/components/Player/Section/PlayerHero.tsx b/packages/web/components/Player/Section/PlayerHero.tsx index 6f8fa533..d891d656 100644 --- a/packages/web/components/Player/Section/PlayerHero.tsx +++ b/packages/web/components/Player/Section/PlayerHero.tsx @@ -1,56 +1,73 @@ -import { Avatar, Box, HStack, Image, Text, VStack } from '@metafam/ds'; +import { + Avatar, Box, Flex, HStack, Link, Text, VStack, +} from '@metafam/ds'; import { PlayerFragmentFragment } from 'graphql/autogen/types'; -import React from 'react'; +import { getPersonalityInfo } from 'graphql/getPersonalityInfo'; +import { PersonalityOption } from 'graphql/types'; +import React, { useEffect } from 'react'; import { getPlayerDescription, getPlayerImage, getPlayerName, } from 'utils/playerHelpers'; -import { PersonalityTypes } from '../../../graphql/types'; import { FlexContainer } from '../../Container'; import { ProfileSection } from '../../ProfileSection'; +import { ColorBar } from '../ColorBar'; import { PlayerContacts } from '../PlayerContacts'; import { PlayerBrightId } from './PlayerBrightId'; import { PlayerCollab } from './PlayerCollab'; -const BIO_LENGTH = 240; +const MAX_BIO_LENGTH = 240; type Props = { player: PlayerFragmentFragment }; export const PlayerHero: React.FC = ({ player }) => { + const description = getPlayerDescription(player); const [show, setShow] = React.useState( - getPlayerDescription(player).length < BIO_LENGTH, + description.length <= MAX_BIO_LENGTH, ); + const [types, setTypes] = React.useState<{ + [any: string]: PersonalityOption; + }>(); + const mask = player?.ColorAspect?.mask; + const type = mask && types?.[mask]; + + const loadTypes = async () => { + const { types: list } = await getPersonalityInfo(); + setTypes(list); + }; + useEffect(() => { loadTypes(); }, []); return ( - + {getPlayerName(player)} - {`${getPlayerDescription(player).substring( - 0, - show ? getPlayerDescription(player).length : BIO_LENGTH, - )}${show ? '' : '...'} `} - {getPlayerDescription(player).length > BIO_LENGTH && ( + {show + ? description + : `${description.substring(0, MAX_BIO_LENGTH - 9)}…` + } + {description.length > MAX_BIO_LENGTH && ( setShow(!show)} + onClick={() => setShow(s => !s)} + pl={1} > Read {show ? 'less' : 'more'} @@ -58,38 +75,50 @@ export const PlayerHero: React.FC = ({ player }) => { - + - {player.EnneagramType && ( - - {player.EnneagramType.name} - - - {player.EnneagramType.name} - - {player.EnneagramType.description} - - - )} - {player.playerType?.title ? ( - - - {player.playerType.title.toUpperCase()} + {type && types && ( + + + Color Disposition + + + + + + + + {type.description} + + + )} + {player.playerType?.title && ( + + + {player.playerType.title} + + + {player.playerType.description} - {player.playerType.description} - ) : null} + )} ); -}; +} \ No newline at end of file diff --git a/packages/web/components/Setup/SetupPersonalityType.tsx b/packages/web/components/Setup/SetupPersonalityType.tsx index 53c61e90..324435b6 100644 --- a/packages/web/components/Setup/SetupPersonalityType.tsx +++ b/packages/web/components/Setup/SetupPersonalityType.tsx @@ -1,56 +1,63 @@ +/* eslint no-bitwise: "off" */ + import { - HStack, + Button, + Flex, Image, MetaButton, MetaHeading, - SimpleGrid, Text, useToast, } from '@metafam/ds'; import { FlexContainer } from 'components/Container'; import { MetaLink } from 'components/Link'; +import { ColorBar } from 'components/Player/ColorBar'; import { useSetupFlow } from 'contexts/SetupContext'; import { useUpdateAboutYouMutation } from 'graphql/autogen/types'; -import { PersonalityType } from 'graphql/types'; +import { images as BaseImages } from 'graphql/getPersonalityInfo'; +import { PersonalityOption } from 'graphql/types'; import { useUser } from 'lib/hooks'; -import React, { useState } from 'react'; +import React, { useCallback } from 'react'; export type SetupPersonalityTypeProps = { - personalityTypeChoices: Array; - personalityType: PersonalityType | undefined; - setPersonalityType: React.Dispatch< - React.SetStateAction + // keyed on a bitmask of the format 0bWUBRG + personalityTypes: { [x: number]: PersonalityOption }; + colorMask: number | undefined; + setColorMask: React.Dispatch< + React.SetStateAction >; }; -export const SetupPersonalityType: React.FC = ({ - personalityTypeChoices, - personalityType, - setPersonalityType, +export const SetupPersonalityType: ( + React.FC +) = ({ + personalityTypes, colorMask, setColorMask, }) => { const { onNextPress, nextButtonLabel } = useSetupFlow(); const { user } = useUser({ redirectTo: '/' }); const toast = useToast(); + const [updateAboutYouRes, updateAboutYou] = ( + useUpdateAboutYouMutation() + ); - const [updateAboutYouRes, updateAboutYou] = useUpdateAboutYouMutation(); - const [loading, setLoading] = useState(false); - - const handleNextPress = async () => { + const handleNextPress = useCallback(async () => { if (!user) return; - setLoading(true); - if (user.player?.EnneagramType?.name !== personalityType?.name) { + if (user.player?.ColorAspect?.mask !== colorMask) { const { error } = await updateAboutYou({ playerId: user.id, input: { - enneagram: personalityType?.name, + color_mask: colorMask, }, }); if (error) { + console.warn(error); // eslint-disable-line no-console toast({ title: 'Error', - description: 'Unable to update personality type. The octo is sad 😢', + description: ( + 'Unable to update personality type. The octo is sad. 😢' + ), status: 'error', isClosable: true, }); @@ -60,64 +67,130 @@ export const SetupPersonalityType: React.FC = ({ } onNextPress(); + }, [colorMask, onNextPress, toast, updateAboutYou, user]); + + // mask should always only have at most a single bit set + const toggleMaskElement = (mask = 0): void => { + setColorMask((current = 0) => { + if ((mask & current) > 0) { // if the bit in mask is set + return current & ~mask; // unset it + } + return current | mask; // otherwise set it + }) }; return ( - - - Personality Type - - - {`Please select your personality type below. Not sure what type you are? `} - - Take a quick test. - - - - {personalityTypeChoices.map((p: PersonalityType) => ( - setPersonalityType(p)} - border="2px" - borderColor={ - personalityType && personalityType.id === p.id - ? 'purple.400' - : 'transparent' - } + + + + Person­ality Type + + + Please select your personality components below. + Not sure what type you are? + Take + - {p.name} - - - {p.name} - - {p.description} - - - ))} - + a quick exam + + or + + a longer quiz + + . + + + + {Object.entries(BaseImages) + .reverse().map( + ([orig, image], idx) => { + const option = personalityTypes[parseInt(orig, 10)] + const { mask = 0 } = (option ?? {}) + const selected = (((colorMask ?? 0) & mask) > 0) + + return ( + + ) + }, + ) + } + + + {nextButtonLabel} diff --git a/packages/web/graphql/fragments.ts b/packages/web/graphql/fragments.ts index 91e472ef..778b45fe 100644 --- a/packages/web/graphql/fragments.ts +++ b/packages/web/graphql/fragments.ts @@ -9,9 +9,10 @@ export const PlayerFragment = gql` ethereum_address availability_hours timezone - EnneagramType { - description + ColorAspect { name + description + mask } playerType { description diff --git a/packages/web/graphql/getPersonalityInfo.ts b/packages/web/graphql/getPersonalityInfo.ts new file mode 100644 index 00000000..c354981a --- /dev/null +++ b/packages/web/graphql/getPersonalityInfo.ts @@ -0,0 +1,73 @@ +import AmbitionAltImg from 'assets/colors/Ambition.svg'; +import BalanceAltImg from 'assets/colors/Balance.svg'; +import ChaosAltImg from 'assets/colors/Chaos.svg'; +import JusticeAltImg from 'assets/colors/Justice.svg'; +import WisdomAltImg from 'assets/colors/Wisdom.svg'; +import gql from 'fake-tag'; +import { isPow2 } from 'utils/mathHelper'; + +import { ColorAspect } from './autogen/types'; +import { client } from './client'; +import { PersonalityOption } from './types'; + +const AspectsQuery = gql` + query GetAspects { + ColorAspect { + mask + name + description + } + } +`; + +export const images: { + [x: number]: string +} = { + 0b10000: JusticeAltImg, + 0b01000: WisdomAltImg, + 0b00100: AmbitionAltImg, + 0b00010: ChaosAltImg, + 0b00001: BalanceAltImg, +}; + +export const colors: { + [x: number]: string +} = { + 0b10000: '#c4aab4', + 0b01000: '#0273b2', + 0b00100: '#141a36', + 0b00010: '#b72d5b', + 0b00001: '#36ae60', +}; + +export const getPersonalityInfo = async (): Promise<{ + parts: Array; + types: { [any: string]: PersonalityOption }; +}> => { + const { data, error } = await ( + client + .query(AspectsQuery) + .toPromise() + ); + + if (error) throw error; + if (!data) throw new Error("data isn't set"); + + const parts: Array = []; + const types: { [x: number]: PersonalityOption } = {}; + data.ColorAspect.forEach((aspect: ColorAspect) => { + const option = { + name: aspect.name, + description: aspect.description, + mask: aspect.mask, + }; + types[aspect.mask] = option; + + // pure colors are powers of 2 (only 1 bit set) + if (isPow2(aspect.mask)) { + parts.push(option); + } + }); + + return { parts, types }; +}; \ No newline at end of file diff --git a/packages/web/graphql/getPersonalityTypes.ts b/packages/web/graphql/getPersonalityTypes.ts deleted file mode 100644 index 5d9705c6..00000000 --- a/packages/web/graphql/getPersonalityTypes.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { PersonalityTypes } from 'graphql/types'; - -export const getPersonalityTypes = () => Object.values(PersonalityTypes); diff --git a/packages/web/graphql/types.ts b/packages/web/graphql/types.ts index 1bcc9ec7..f305b8c2 100644 --- a/packages/web/graphql/types.ts +++ b/packages/web/graphql/types.ts @@ -1,15 +1,5 @@ import { MetaTheme } from '@metafam/ds'; -import AchieverImage from 'assets/achiever.png'; -import ChallengerImage from 'assets/challenger.png'; -import EnthusiastImage from 'assets/enthusiast.png'; -import HelperImage from 'assets/helper.png'; -import IndividualistImage from 'assets/individualist.png'; -import InvestigatorImage from 'assets/investigator.png'; -import LoyalistImage from 'assets/loyalist.png'; -import PeacemakerImage from 'assets/peacemaker.png'; -import ReformerImage from 'assets/reformer.png'; import { - EnneagramType_Enum, Me, Member, Moloch, @@ -27,12 +17,10 @@ export type Skill = { category: string; }; -export type PersonalityType = { - id: string; - name: EnneagramType_Enum; - label: string; - description: string; - image: string; +export type PersonalityOption = { + mask: number; + name: string; + description?: string | null | undefined; }; export type Membership = Pick & { @@ -46,74 +34,6 @@ export type MeType = | null | undefined; -export const PersonalityTypes: { - [any: string]: PersonalityType; -} = { - [EnneagramType_Enum.Reformer]: { - id: '1', - name: EnneagramType_Enum.Reformer, - label: 'The Reformer', - description: 'Principled, Purposeful, Self-Controlled, and Perfectionistic', - image: ReformerImage, - }, - [EnneagramType_Enum.Helper]: { - id: '2', - name: EnneagramType_Enum.Helper, - label: 'The Helper', - description: 'Demonstrative, Generous, People-Pleasing, and Possessive', - image: HelperImage, - }, - [EnneagramType_Enum.Achiever]: { - id: '3', - name: EnneagramType_Enum.Achiever, - label: 'The Achiever', - description: 'Adaptive, Excelling, Driven, and Image-Conscious', - image: AchieverImage, - }, - [EnneagramType_Enum.Individualist]: { - id: '4', - name: EnneagramType_Enum.Individualist, - label: 'The Individualist', - description: 'Expressive, Dramatic, Self-Absorbed, and Temperamental', - image: IndividualistImage, - }, - [EnneagramType_Enum.Investigator]: { - id: '5', - name: EnneagramType_Enum.Investigator, - label: 'The Investigator', - description: 'Perceptive, Innovative, Secretive, and Isolated', - image: InvestigatorImage, - }, - [EnneagramType_Enum.Loyalist]: { - id: '6', - name: EnneagramType_Enum.Loyalist, - label: 'The Loyalist', - description: 'Engaging, Responsible, Anxious, and Suspicious', - image: LoyalistImage, - }, - [EnneagramType_Enum.Enthusiast]: { - id: '7', - name: EnneagramType_Enum.Enthusiast, - label: 'The Enthusiast', - description: 'Spontaneous, Versatile, Distractible, and Scattered', - image: EnthusiastImage, - }, - [EnneagramType_Enum.Challenger]: { - id: '8', - name: EnneagramType_Enum.Challenger, - label: 'The Challenger', - description: 'Self-Confident, Decisive, Willful, and Confrontational', - image: ChallengerImage, - }, - [EnneagramType_Enum.Peacemaker]: { - id: '9', - name: EnneagramType_Enum.Peacemaker, - label: 'The Peacemaker', - description: 'Receptive, Reassuring, Agreeable, and Complacent', - image: PeacemakerImage, - }, -}; - export const SkillColors: Record = { [SkillCategory_Enum.Community]: MetaTheme.colors.green['700'], [SkillCategory_Enum.Design]: MetaTheme.colors.pink['700'], diff --git a/packages/web/pages/profile/setup/personalityType.tsx b/packages/web/pages/profile/setup/personalityType.tsx index 6b7b0a9f..8dd6de1a 100644 --- a/packages/web/pages/profile/setup/personalityType.tsx +++ b/packages/web/pages/profile/setup/personalityType.tsx @@ -1,18 +1,20 @@ import { SetupPersonalityType } from 'components/Setup/SetupPersonalityType'; import { SetupProfile } from 'components/Setup/SetupProfile'; import { SetupContextProvider } from 'contexts/SetupContext'; -import { getPersonalityTypes } from 'graphql/getPersonalityTypes'; -import { PersonalityType, PersonalityTypes } from 'graphql/types'; +import { getPersonalityInfo } from 'graphql/getPersonalityInfo'; import { useUser } from 'lib/hooks'; import { InferGetStaticPropsType } from 'next'; -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; export const getStaticProps = async () => { - const personalityTypeChoices = await getPersonalityTypes(); + const { types: personalityTypes, parts: personalityParts } = ( + await getPersonalityInfo() + ); return { props: { - personalityTypeChoices, + personalityParts, + personalityTypes, hideAppDrawer: true, }, }; @@ -22,24 +24,32 @@ type Props = InferGetStaticPropsType; const PersonalityTypeSetup: React.FC = (props) => { - const { personalityTypeChoices } = props; - const [personalityType, setPersonalityType] = useState(); + const { personalityTypes } = props; const { user } = useUser({ redirectTo: '/' }); + const [colorMask, setColorMask] = ( + useState(user?.player?.ColorAspect?.mask) + ); - if (user?.player) { - const { player } = user; - if (player.EnneagramType && !personalityType) { - setPersonalityType(PersonalityTypes[player.EnneagramType.name]); + const load = () => { + const { player } = user ?? {}; + if (player) { + if (colorMask === undefined && player.ColorAspect !== null) { + setColorMask(player.ColorAspect?.mask); + } } } + useEffect(load, [user, colorMask]); return ( - + ); diff --git a/packages/web/utils/mathHelper.ts b/packages/web/utils/mathHelper.ts new file mode 100644 index 00000000..e344a70a --- /dev/null +++ b/packages/web/utils/mathHelper.ts @@ -0,0 +1,5 @@ +// true if the number is a power of 2 +export const isPow2 = (int: number): boolean => ( + // eslint-disable-next-line no-bitwise + int > 0 && (int & (int - 1)) === 0 +); \ No newline at end of file diff --git a/schema.graphql b/schema.graphql index 41a819a3..14a8f4a4 100644 --- a/schema.graphql +++ b/schema.graphql @@ -203,6 +203,352 @@ type CollectiblesFavorites { tokenId: String } +""" +columns and relationships of "ColorAspect" +""" +type ColorAspect { + description: String + mask: Int! + name: String! + + """An array relationship""" + players( + """distinct select on columns""" + distinct_on: [player_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [player_order_by!] + + """filter the rows returned""" + where: player_bool_exp + ): [player!]! + + """An aggregated array relationship""" + players_aggregate( + """distinct select on columns""" + distinct_on: [player_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [player_order_by!] + + """filter the rows returned""" + where: player_bool_exp + ): player_aggregate! +} + +""" +aggregated selection of "ColorAspect" +""" +type ColorAspect_aggregate { + aggregate: ColorAspect_aggregate_fields + nodes: [ColorAspect!]! +} + +""" +aggregate fields of "ColorAspect" +""" +type ColorAspect_aggregate_fields { + avg: ColorAspect_avg_fields + count(columns: [ColorAspect_select_column!], distinct: Boolean): Int + max: ColorAspect_max_fields + min: ColorAspect_min_fields + stddev: ColorAspect_stddev_fields + stddev_pop: ColorAspect_stddev_pop_fields + stddev_samp: ColorAspect_stddev_samp_fields + sum: ColorAspect_sum_fields + var_pop: ColorAspect_var_pop_fields + var_samp: ColorAspect_var_samp_fields + variance: ColorAspect_variance_fields +} + +""" +order by aggregate values of table "ColorAspect" +""" +input ColorAspect_aggregate_order_by { + avg: ColorAspect_avg_order_by + count: order_by + max: ColorAspect_max_order_by + min: ColorAspect_min_order_by + stddev: ColorAspect_stddev_order_by + stddev_pop: ColorAspect_stddev_pop_order_by + stddev_samp: ColorAspect_stddev_samp_order_by + sum: ColorAspect_sum_order_by + var_pop: ColorAspect_var_pop_order_by + var_samp: ColorAspect_var_samp_order_by + variance: ColorAspect_variance_order_by +} + +""" +input type for inserting array relation for remote table "ColorAspect" +""" +input ColorAspect_arr_rel_insert_input { + data: [ColorAspect_insert_input!]! + on_conflict: ColorAspect_on_conflict +} + +"""aggregate avg on columns""" +type ColorAspect_avg_fields { + mask: Float +} + +""" +order by avg() on columns of table "ColorAspect" +""" +input ColorAspect_avg_order_by { + mask: order_by +} + +""" +Boolean expression to filter rows from the table "ColorAspect". All fields are combined with a logical 'AND'. +""" +input ColorAspect_bool_exp { + _and: [ColorAspect_bool_exp] + _not: ColorAspect_bool_exp + _or: [ColorAspect_bool_exp] + description: String_comparison_exp + mask: Int_comparison_exp + name: String_comparison_exp + players: player_bool_exp +} + +""" +unique or primary key constraints on table "ColorAspect" +""" +enum ColorAspect_constraint { + """unique or primary key constraint""" + ColorAspect_name_key + + """unique or primary key constraint""" + ColorAspect_pkey +} + +""" +input type for incrementing integer column in table "ColorAspect" +""" +input ColorAspect_inc_input { + mask: Int +} + +""" +input type for inserting data into table "ColorAspect" +""" +input ColorAspect_insert_input { + description: String + mask: Int + name: String + players: player_arr_rel_insert_input +} + +"""aggregate max on columns""" +type ColorAspect_max_fields { + description: String + mask: Int + name: String +} + +""" +order by max() on columns of table "ColorAspect" +""" +input ColorAspect_max_order_by { + description: order_by + mask: order_by + name: order_by +} + +"""aggregate min on columns""" +type ColorAspect_min_fields { + description: String + mask: Int + name: String +} + +""" +order by min() on columns of table "ColorAspect" +""" +input ColorAspect_min_order_by { + description: order_by + mask: order_by + name: order_by +} + +""" +response of any mutation on the table "ColorAspect" +""" +type ColorAspect_mutation_response { + """number of affected rows by the mutation""" + affected_rows: Int! + + """data of the affected rows by the mutation""" + returning: [ColorAspect!]! +} + +""" +input type for inserting object relation for remote table "ColorAspect" +""" +input ColorAspect_obj_rel_insert_input { + data: ColorAspect_insert_input! + on_conflict: ColorAspect_on_conflict +} + +""" +on conflict condition type for table "ColorAspect" +""" +input ColorAspect_on_conflict { + constraint: ColorAspect_constraint! + update_columns: [ColorAspect_update_column!]! + where: ColorAspect_bool_exp +} + +""" +ordering options when selecting data from "ColorAspect" +""" +input ColorAspect_order_by { + description: order_by + mask: order_by + name: order_by + players_aggregate: player_aggregate_order_by +} + +""" +primary key columns input for table: "ColorAspect" +""" +input ColorAspect_pk_columns_input { + mask: Int! +} + +""" +select columns of table "ColorAspect" +""" +enum ColorAspect_select_column { + """column name""" + description + + """column name""" + mask + + """column name""" + name +} + +""" +input type for updating data in table "ColorAspect" +""" +input ColorAspect_set_input { + description: String + mask: Int + name: String +} + +"""aggregate stddev on columns""" +type ColorAspect_stddev_fields { + mask: Float +} + +""" +order by stddev() on columns of table "ColorAspect" +""" +input ColorAspect_stddev_order_by { + mask: order_by +} + +"""aggregate stddev_pop on columns""" +type ColorAspect_stddev_pop_fields { + mask: Float +} + +""" +order by stddev_pop() on columns of table "ColorAspect" +""" +input ColorAspect_stddev_pop_order_by { + mask: order_by +} + +"""aggregate stddev_samp on columns""" +type ColorAspect_stddev_samp_fields { + mask: Float +} + +""" +order by stddev_samp() on columns of table "ColorAspect" +""" +input ColorAspect_stddev_samp_order_by { + mask: order_by +} + +"""aggregate sum on columns""" +type ColorAspect_sum_fields { + mask: Int +} + +""" +order by sum() on columns of table "ColorAspect" +""" +input ColorAspect_sum_order_by { + mask: order_by +} + +""" +update columns of table "ColorAspect" +""" +enum ColorAspect_update_column { + """column name""" + description + + """column name""" + mask + + """column name""" + name +} + +"""aggregate var_pop on columns""" +type ColorAspect_var_pop_fields { + mask: Float +} + +""" +order by var_pop() on columns of table "ColorAspect" +""" +input ColorAspect_var_pop_order_by { + mask: order_by +} + +"""aggregate var_samp on columns""" +type ColorAspect_var_samp_fields { + mask: Float +} + +""" +order by var_samp() on columns of table "ColorAspect" +""" +input ColorAspect_var_samp_order_by { + mask: order_by +} + +"""aggregate variance on columns""" +type ColorAspect_variance_fields { + mask: Float +} + +""" +order by variance() on columns of table "ColorAspect" +""" +input ColorAspect_variance_order_by { + mask: order_by +} + input CreateQuestCompletionInput { quest_id: String! submission_link: String @@ -1941,6 +2287,19 @@ type mutation_root { """ delete_AccountType_by_pk(type: String!): AccountType + """ + delete data from the table: "ColorAspect" + """ + delete_ColorAspect( + """filter the rows which have to be deleted""" + where: ColorAspect_bool_exp! + ): ColorAspect_mutation_response + + """ + delete single row from the table: "ColorAspect" + """ + delete_ColorAspect_by_pk(mask: Int!): ColorAspect + """ delete data from the table: "EnneagramType" """ @@ -2213,6 +2572,28 @@ type mutation_root { on_conflict: AccountType_on_conflict ): AccountType + """ + insert data into the table: "ColorAspect" + """ + insert_ColorAspect( + """the rows to be inserted""" + objects: [ColorAspect_insert_input!]! + + """on conflict condition""" + on_conflict: ColorAspect_on_conflict + ): ColorAspect_mutation_response + + """ + insert a single row into the table: "ColorAspect" + """ + insert_ColorAspect_one( + """the row to be inserted""" + object: ColorAspect_insert_input! + + """on conflict condition""" + on_conflict: ColorAspect_on_conflict + ): ColorAspect + """ insert data into the table: "EnneagramType" """ @@ -2677,6 +3058,32 @@ type mutation_root { pk_columns: AccountType_pk_columns_input! ): AccountType + """ + update data of the table: "ColorAspect" + """ + update_ColorAspect( + """increments the integer columns with given value of the filtered values""" + _inc: ColorAspect_inc_input + + """sets the columns of the filtered rows to the given values""" + _set: ColorAspect_set_input + + """filter the rows which have to be updated""" + where: ColorAspect_bool_exp! + ): ColorAspect_mutation_response + + """ + update single row of the table: "ColorAspect" + """ + update_ColorAspect_by_pk( + """increments the integer columns with given value of the filtered values""" + _inc: ColorAspect_inc_input + + """sets the columns of the filtered rows to the given values""" + _set: ColorAspect_set_input + pk_columns: ColorAspect_pk_columns_input! + ): ColorAspect + """ update data of the table: "EnneagramType" """ @@ -3200,6 +3607,9 @@ type player { where: player_account_bool_exp ): player_account_aggregate! + """An object relationship""" + ColorAspect: ColorAspect + """An object relationship""" EnneagramType: EnneagramType @@ -3245,6 +3655,7 @@ type player { """Remote relationship field""" brightid_status: BrightIdStatus + color_mask: Int created_at: timestamptz """Remote relationship field""" @@ -3609,6 +4020,7 @@ input player_arr_rel_insert_input { """aggregate avg on columns""" type player_avg_fields { availability_hours: Float + color_mask: Float player_type_id: Float total_xp: Float } @@ -3618,6 +4030,7 @@ order by avg() on columns of table "player" """ input player_avg_order_by { availability_hours: order_by + color_mask: order_by player_type_id: order_by total_xp: order_by } @@ -3627,12 +4040,14 @@ Boolean expression to filter rows from the table "player". All fields are combin """ input player_bool_exp { Accounts: player_account_bool_exp + ColorAspect: ColorAspect_bool_exp EnneagramType: EnneagramType_bool_exp Player_Skills: player_skill_bool_exp _and: [player_bool_exp] _not: player_bool_exp _or: [player_bool_exp] availability_hours: Int_comparison_exp + color_mask: Int_comparison_exp created_at: timestamptz_comparison_exp discord_id: String_comparison_exp enneagram: EnneagramType_enum_comparison_exp @@ -3677,6 +4092,7 @@ input type for incrementing integer column in table "player" """ input player_inc_input { availability_hours: Int + color_mask: Int player_type_id: Int total_xp: numeric } @@ -3686,9 +4102,11 @@ input type for inserting data into table "player" """ input player_insert_input { Accounts: player_account_arr_rel_insert_input + ColorAspect: ColorAspect_obj_rel_insert_input EnneagramType: EnneagramType_obj_rel_insert_input Player_Skills: player_skill_arr_rel_insert_input availability_hours: Int + color_mask: Int created_at: timestamptz discord_id: String enneagram: EnneagramType_enum @@ -3711,6 +4129,7 @@ input player_insert_input { """aggregate max on columns""" type player_max_fields { availability_hours: Int + color_mask: Int created_at: timestamptz discord_id: String ethereum_address: String @@ -3729,6 +4148,7 @@ order by max() on columns of table "player" """ input player_max_order_by { availability_hours: order_by + color_mask: order_by created_at: order_by discord_id: order_by ethereum_address: order_by @@ -3745,6 +4165,7 @@ input player_max_order_by { """aggregate min on columns""" type player_min_fields { availability_hours: Int + color_mask: Int created_at: timestamptz discord_id: String ethereum_address: String @@ -3763,6 +4184,7 @@ order by min() on columns of table "player" """ input player_min_order_by { availability_hours: order_by + color_mask: order_by created_at: order_by discord_id: order_by ethereum_address: order_by @@ -3809,9 +4231,11 @@ ordering options when selecting data from "player" """ input player_order_by { Accounts_aggregate: player_account_aggregate_order_by + ColorAspect: ColorAspect_order_by EnneagramType: EnneagramType_order_by Player_Skills_aggregate: player_skill_aggregate_order_by availability_hours: order_by + color_mask: order_by created_at: order_by discord_id: order_by enneagram: order_by @@ -3845,6 +4269,9 @@ enum player_select_column { """column name""" availability_hours + """column name""" + color_mask + """column name""" created_at @@ -3890,6 +4317,7 @@ input type for updating data in table "player" """ input player_set_input { availability_hours: Int + color_mask: Int created_at: timestamptz discord_id: String enneagram: EnneagramType_enum @@ -4084,6 +4512,7 @@ enum player_skill_update_column { """aggregate stddev on columns""" type player_stddev_fields { availability_hours: Float + color_mask: Float player_type_id: Float total_xp: Float } @@ -4093,6 +4522,7 @@ order by stddev() on columns of table "player" """ input player_stddev_order_by { availability_hours: order_by + color_mask: order_by player_type_id: order_by total_xp: order_by } @@ -4100,6 +4530,7 @@ input player_stddev_order_by { """aggregate stddev_pop on columns""" type player_stddev_pop_fields { availability_hours: Float + color_mask: Float player_type_id: Float total_xp: Float } @@ -4109,6 +4540,7 @@ order by stddev_pop() on columns of table "player" """ input player_stddev_pop_order_by { availability_hours: order_by + color_mask: order_by player_type_id: order_by total_xp: order_by } @@ -4116,6 +4548,7 @@ input player_stddev_pop_order_by { """aggregate stddev_samp on columns""" type player_stddev_samp_fields { availability_hours: Float + color_mask: Float player_type_id: Float total_xp: Float } @@ -4125,6 +4558,7 @@ order by stddev_samp() on columns of table "player" """ input player_stddev_samp_order_by { availability_hours: order_by + color_mask: order_by player_type_id: order_by total_xp: order_by } @@ -4132,6 +4566,7 @@ input player_stddev_samp_order_by { """aggregate sum on columns""" type player_sum_fields { availability_hours: Int + color_mask: Int player_type_id: Int total_xp: numeric } @@ -4141,6 +4576,7 @@ order by sum() on columns of table "player" """ input player_sum_order_by { availability_hours: order_by + color_mask: order_by player_type_id: order_by total_xp: order_by } @@ -4474,6 +4910,9 @@ enum player_update_column { """column name""" availability_hours + """column name""" + color_mask + """column name""" created_at @@ -4517,6 +4956,7 @@ enum player_update_column { """aggregate var_pop on columns""" type player_var_pop_fields { availability_hours: Float + color_mask: Float player_type_id: Float total_xp: Float } @@ -4526,6 +4966,7 @@ order by var_pop() on columns of table "player" """ input player_var_pop_order_by { availability_hours: order_by + color_mask: order_by player_type_id: order_by total_xp: order_by } @@ -4533,6 +4974,7 @@ input player_var_pop_order_by { """aggregate var_samp on columns""" type player_var_samp_fields { availability_hours: Float + color_mask: Float player_type_id: Float total_xp: Float } @@ -4542,6 +4984,7 @@ order by var_samp() on columns of table "player" """ input player_var_samp_order_by { availability_hours: order_by + color_mask: order_by player_type_id: order_by total_xp: order_by } @@ -4549,6 +4992,7 @@ input player_var_samp_order_by { """aggregate variance on columns""" type player_variance_fields { availability_hours: Float + color_mask: Float player_type_id: Float total_xp: Float } @@ -4558,6 +5002,7 @@ order by variance() on columns of table "player" """ input player_variance_order_by { availability_hours: order_by + color_mask: order_by player_type_id: order_by total_xp: order_by } @@ -4789,6 +5234,49 @@ type query_root { """fetch data from the table: "AccountType" using primary key columns""" AccountType_by_pk(type: String!): AccountType + """ + fetch data from the table: "ColorAspect" + """ + ColorAspect( + """distinct select on columns""" + distinct_on: [ColorAspect_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [ColorAspect_order_by!] + + """filter the rows returned""" + where: ColorAspect_bool_exp + ): [ColorAspect!]! + + """ + fetch aggregated fields from the table: "ColorAspect" + """ + ColorAspect_aggregate( + """distinct select on columns""" + distinct_on: [ColorAspect_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [ColorAspect_order_by!] + + """filter the rows returned""" + where: ColorAspect_bool_exp + ): ColorAspect_aggregate! + + """fetch data from the table: "ColorAspect" using primary key columns""" + ColorAspect_by_pk(mask: Int!): ColorAspect + """ fetch data from the table: "EnneagramType" """ @@ -7734,6 +8222,49 @@ type subscription_root { """fetch data from the table: "AccountType" using primary key columns""" AccountType_by_pk(type: String!): AccountType + """ + fetch data from the table: "ColorAspect" + """ + ColorAspect( + """distinct select on columns""" + distinct_on: [ColorAspect_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [ColorAspect_order_by!] + + """filter the rows returned""" + where: ColorAspect_bool_exp + ): [ColorAspect!]! + + """ + fetch aggregated fields from the table: "ColorAspect" + """ + ColorAspect_aggregate( + """distinct select on columns""" + distinct_on: [ColorAspect_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [ColorAspect_order_by!] + + """filter the rows returned""" + where: ColorAspect_bool_exp + ): ColorAspect_aggregate! + + """fetch data from the table: "ColorAspect" using primary key columns""" + ColorAspect_by_pk(mask: Int!): ColorAspect + """ fetch data from the table: "EnneagramType" """