From e631e88d9b3c9778dc549f1b23f4db8f593ee0ef Mon Sep 17 00:00:00 2001 From: Pedro Tiburcio Date: Thu, 19 Dec 2024 16:34:54 -0500 Subject: [PATCH 1/5] feat: follow/unfollow and move profile components to packages --- .../BlockToggleFragment.graphql.ts | 66 ++++ .../BlockToggleMutation.graphql.ts | 234 ++++++++++++ .../FollowToggleMutation.graphql.ts | 223 ++++++++++++ .../FollowToggleUpdatableFragment.graphql.ts | 51 +++ .../ProfileComponentFragment.graphql.ts | 231 ++++++++++++ .../ProfileUpdateMutation.graphql.ts | 343 ++++++++++++++++++ .../BlockButtonWithDialog/constants.ts | 14 + .../profiles/BlockButtonWithDialog/index.tsx | 125 +++++++ .../profiles/BlockButtonWithDialog/styled.tsx | 11 + .../profiles/BlockButtonWithDialog/types.ts | 15 + .../profiles/FollowToggleButton/index.tsx | 84 +++++ .../profiles/FollowToggleButton/types.ts | 6 + .../profiles/ProfileComponent/index.tsx | 212 +++++++++++ .../profiles/ProfileComponent/styled.tsx | 84 +++++ .../profiles/ProfileComponent/types.ts | 5 + .../profiles/graphql/mutations/BlockToggle.ts | 19 + .../graphql/mutations/FollowToggle.ts | 17 + .../graphql/mutations/ProfileUpdate.ts | 20 + .../profiles/graphql/queries/BlockToggle.ts | 12 + .../queries/FollowToggleUpdatableFragment.ts | 8 + .../graphql/queries/ProfileComponent.ts | 28 ++ packages/components/modules/profiles/index.ts | 2 + packages/components/package.json | 1 + packages/design-system/.storybook/preview.ts | 2 + .../components/icons/BlockIcon/index.tsx | 24 ++ .../components/icons/ThreeDotsIcon/index.tsx | 33 ++ .../components/icons/UnblockIcon/index.tsx | 30 ++ .../design-system/components/icons/index.ts | 3 + .../__storybook__/stories.tsx | 24 ++ .../images/ImageWithFallback/index.tsx | 36 ++ .../images/ImageWithFallback/types.ts | 11 + .../design-system/components/images/index.ts | 1 + packages/design-system/index.ts | 1 + pnpm-lock.yaml | 15 + 34 files changed, 1991 insertions(+) create mode 100644 packages/components/__generated__/BlockToggleFragment.graphql.ts create mode 100644 packages/components/__generated__/BlockToggleMutation.graphql.ts create mode 100644 packages/components/__generated__/FollowToggleMutation.graphql.ts create mode 100644 packages/components/__generated__/FollowToggleUpdatableFragment.graphql.ts create mode 100644 packages/components/__generated__/ProfileComponentFragment.graphql.ts create mode 100644 packages/components/__generated__/ProfileUpdateMutation.graphql.ts create mode 100644 packages/components/modules/profiles/BlockButtonWithDialog/constants.ts create mode 100644 packages/components/modules/profiles/BlockButtonWithDialog/index.tsx create mode 100644 packages/components/modules/profiles/BlockButtonWithDialog/styled.tsx create mode 100644 packages/components/modules/profiles/BlockButtonWithDialog/types.ts create mode 100644 packages/components/modules/profiles/FollowToggleButton/index.tsx create mode 100644 packages/components/modules/profiles/FollowToggleButton/types.ts create mode 100644 packages/components/modules/profiles/ProfileComponent/index.tsx create mode 100644 packages/components/modules/profiles/ProfileComponent/styled.tsx create mode 100644 packages/components/modules/profiles/ProfileComponent/types.ts create mode 100644 packages/components/modules/profiles/graphql/mutations/BlockToggle.ts create mode 100644 packages/components/modules/profiles/graphql/mutations/FollowToggle.ts create mode 100644 packages/components/modules/profiles/graphql/mutations/ProfileUpdate.ts create mode 100644 packages/components/modules/profiles/graphql/queries/BlockToggle.ts create mode 100644 packages/components/modules/profiles/graphql/queries/FollowToggleUpdatableFragment.ts create mode 100644 packages/components/modules/profiles/graphql/queries/ProfileComponent.ts create mode 100644 packages/design-system/components/icons/BlockIcon/index.tsx create mode 100644 packages/design-system/components/icons/ThreeDotsIcon/index.tsx create mode 100644 packages/design-system/components/icons/UnblockIcon/index.tsx create mode 100644 packages/design-system/components/images/ImageWithFallback/__storybook__/stories.tsx create mode 100644 packages/design-system/components/images/ImageWithFallback/index.tsx create mode 100644 packages/design-system/components/images/ImageWithFallback/types.ts create mode 100644 packages/design-system/components/images/index.ts diff --git a/packages/components/__generated__/BlockToggleFragment.graphql.ts b/packages/components/__generated__/BlockToggleFragment.graphql.ts new file mode 100644 index 00000000..6933ec0e --- /dev/null +++ b/packages/components/__generated__/BlockToggleFragment.graphql.ts @@ -0,0 +1,66 @@ +/** + * @generated SignedSource<<736dea7090465a624ce8a92c4ec975ae>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ + +/* eslint-disable */ +// @ts-nocheck +import { Fragment, ReaderFragment } from 'relay-runtime' +import { FragmentRefs } from 'relay-runtime' + +export type BlockToggleFragment$data = { + readonly id: string + readonly isBlockedByMe: boolean | null | undefined + readonly name?: string | null | undefined + readonly ' $fragmentType': 'BlockToggleFragment' +} +export type BlockToggleFragment$key = { + readonly ' $data'?: BlockToggleFragment$data + readonly ' $fragmentSpreads': FragmentRefs<'BlockToggleFragment'> +} + +const node: ReaderFragment = { + argumentDefinitions: [], + kind: 'Fragment', + metadata: null, + name: 'BlockToggleFragment', + selections: [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'id', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'isBlockedByMe', + storageKey: null, + }, + { + kind: 'InlineFragment', + selections: [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'name', + storageKey: null, + }, + ], + type: 'Profile', + abstractKey: null, + }, + ], + type: 'BlocksInterface', + abstractKey: '__isBlocksInterface', +} + +;(node as any).hash = 'e03ed2e064ae6dbdca724087c1dfdd16' + +export default node diff --git a/packages/components/__generated__/BlockToggleMutation.graphql.ts b/packages/components/__generated__/BlockToggleMutation.graphql.ts new file mode 100644 index 00000000..701e71a7 --- /dev/null +++ b/packages/components/__generated__/BlockToggleMutation.graphql.ts @@ -0,0 +1,234 @@ +/** + * @generated SignedSource<<67a5f0e7cdc45cc2315b67143872610e>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ + +/* eslint-disable */ +// @ts-nocheck +import { ConcreteRequest, Mutation } from 'relay-runtime' +import { FragmentRefs } from 'relay-runtime' + +export type BlockToggleInput = { + actorObjectId: string + clientMutationId?: string | null | undefined + targetObjectId: string +} +export type BlockToggleMutation$variables = { + input: BlockToggleInput +} +export type BlockToggleMutation$data = { + readonly blockToggle: + | { + readonly block: + | { + readonly node: + | { + readonly id: string + } + | null + | undefined + } + | null + | undefined + readonly blockDeletedId: string | null | undefined + readonly target: + | { + readonly id: string + readonly isBlockedByMe: boolean | null | undefined + readonly ' $fragmentSpreads': FragmentRefs<'BlockToggleFragment'> + } + | null + | undefined + } + | null + | undefined +} +export type BlockToggleMutation = { + response: BlockToggleMutation$data + variables: BlockToggleMutation$variables +} + +const node: ConcreteRequest = (function () { + var v0 = [ + { + defaultValue: null, + kind: 'LocalArgument', + name: 'input', + }, + ], + v1 = [ + { + kind: 'Variable', + name: 'input', + variableName: 'input', + }, + ], + v2 = { + alias: null, + args: null, + kind: 'ScalarField', + name: 'id', + storageKey: null, + }, + v3 = { + alias: null, + args: null, + concreteType: 'BlockEdge', + kind: 'LinkedField', + name: 'block', + plural: false, + selections: [ + { + alias: null, + args: null, + concreteType: 'Block', + kind: 'LinkedField', + name: 'node', + plural: false, + selections: [v2 /*: any*/], + storageKey: null, + }, + ], + storageKey: null, + }, + v4 = { + alias: null, + args: null, + kind: 'ScalarField', + name: 'blockDeletedId', + storageKey: null, + }, + v5 = { + alias: null, + args: null, + kind: 'ScalarField', + name: 'isBlockedByMe', + storageKey: null, + } + return { + fragment: { + argumentDefinitions: v0 /*: any*/, + kind: 'Fragment', + metadata: null, + name: 'BlockToggleMutation', + selections: [ + { + alias: null, + args: v1 /*: any*/, + concreteType: 'BlockTogglePayload', + kind: 'LinkedField', + name: 'blockToggle', + plural: false, + selections: [ + v3 /*: any*/, + v4 /*: any*/, + { + alias: null, + args: null, + concreteType: null, + kind: 'LinkedField', + name: 'target', + plural: false, + selections: [ + v2 /*: any*/, + v5 /*: any*/, + { + args: null, + kind: 'FragmentSpread', + name: 'BlockToggleFragment', + }, + ], + storageKey: null, + }, + ], + storageKey: null, + }, + ], + type: 'Mutation', + abstractKey: null, + }, + kind: 'Request', + operation: { + argumentDefinitions: v0 /*: any*/, + kind: 'Operation', + name: 'BlockToggleMutation', + selections: [ + { + alias: null, + args: v1 /*: any*/, + concreteType: 'BlockTogglePayload', + kind: 'LinkedField', + name: 'blockToggle', + plural: false, + selections: [ + v3 /*: any*/, + v4 /*: any*/, + { + alias: null, + args: null, + filters: null, + handle: 'deleteRecord', + key: '', + kind: 'ScalarHandle', + name: 'blockDeletedId', + }, + { + alias: null, + args: null, + concreteType: null, + kind: 'LinkedField', + name: 'target', + plural: false, + selections: [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: '__typename', + storageKey: null, + }, + v2 /*: any*/, + v5 /*: any*/, + { + kind: 'TypeDiscriminator', + abstractKey: '__isBlocksInterface', + }, + { + kind: 'InlineFragment', + selections: [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'name', + storageKey: null, + }, + ], + type: 'Profile', + abstractKey: null, + }, + ], + storageKey: null, + }, + ], + storageKey: null, + }, + ], + }, + params: { + cacheID: 'ffed8bf057da30f64200e9f801d9186c', + id: null, + metadata: {}, + name: 'BlockToggleMutation', + operationKind: 'mutation', + text: 'mutation BlockToggleMutation(\n $input: BlockToggleInput!\n) {\n blockToggle(input: $input) {\n block {\n node {\n id\n }\n }\n blockDeletedId\n target {\n __typename\n id\n isBlockedByMe\n ...BlockToggleFragment\n }\n }\n}\n\nfragment BlockToggleFragment on BlocksInterface {\n __isBlocksInterface: __typename\n id\n isBlockedByMe\n ... on Profile {\n id\n name\n }\n}\n', + }, + } +})() + +;(node as any).hash = '065f29d79d6f508cd4db5788802958e5' + +export default node diff --git a/packages/components/__generated__/FollowToggleMutation.graphql.ts b/packages/components/__generated__/FollowToggleMutation.graphql.ts new file mode 100644 index 00000000..18f528bf --- /dev/null +++ b/packages/components/__generated__/FollowToggleMutation.graphql.ts @@ -0,0 +1,223 @@ +/** + * @generated SignedSource<<8262681c5d1a1ba5f85d82327c6d6cbc>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ + +/* eslint-disable */ +// @ts-nocheck +import { ConcreteRequest, Mutation } from 'relay-runtime' +import { FragmentRefs } from 'relay-runtime' + +export type FollowToggleInput = { + actorObjectId: string + clientMutationId?: string | null | undefined + targetObjectId: string +} +export type FollowToggleMutation$variables = { + input: FollowToggleInput +} +export type FollowToggleMutation$data = { + readonly followToggle: + | { + readonly follow: + | { + readonly node: + | { + readonly target: { + readonly $updatableFragmentSpreads: FragmentRefs<'FollowToggleUpdatableFragment'> + readonly followersCount: number | null | undefined + readonly isFollowedByMe: boolean | null | undefined + } + } + | null + | undefined + } + | null + | undefined + } + | null + | undefined +} +export type FollowToggleMutation = { + response: FollowToggleMutation$data + variables: FollowToggleMutation$variables +} + +const node: ConcreteRequest = (function () { + var v0 = [ + { + defaultValue: null, + kind: 'LocalArgument', + name: 'input', + }, + ], + v1 = [ + { + kind: 'Variable', + name: 'input', + variableName: 'input', + }, + ], + v2 = { + alias: null, + args: null, + kind: 'ScalarField', + name: 'isFollowedByMe', + storageKey: null, + }, + v3 = { + alias: null, + args: null, + kind: 'ScalarField', + name: 'followersCount', + storageKey: null, + }, + v4 = { + alias: null, + args: null, + kind: 'ScalarField', + name: 'id', + storageKey: null, + } + return { + fragment: { + argumentDefinitions: v0 /*: any*/, + kind: 'Fragment', + metadata: null, + name: 'FollowToggleMutation', + selections: [ + { + alias: null, + args: v1 /*: any*/, + concreteType: 'FollowTogglePayload', + kind: 'LinkedField', + name: 'followToggle', + plural: false, + selections: [ + { + alias: null, + args: null, + concreteType: 'FollowEdge', + kind: 'LinkedField', + name: 'follow', + plural: false, + selections: [ + { + alias: null, + args: null, + concreteType: 'Follow', + kind: 'LinkedField', + name: 'node', + plural: false, + selections: [ + { + alias: null, + args: null, + concreteType: 'Profile', + kind: 'LinkedField', + name: 'target', + plural: false, + selections: [ + v2 /*: any*/, + v3 /*: any*/, + { + args: null, + kind: 'FragmentSpread', + name: 'FollowToggleUpdatableFragment', + }, + ], + storageKey: null, + }, + ], + storageKey: null, + }, + ], + storageKey: null, + }, + ], + storageKey: null, + }, + ], + type: 'Mutation', + abstractKey: null, + }, + kind: 'Request', + operation: { + argumentDefinitions: v0 /*: any*/, + kind: 'Operation', + name: 'FollowToggleMutation', + selections: [ + { + alias: null, + args: v1 /*: any*/, + concreteType: 'FollowTogglePayload', + kind: 'LinkedField', + name: 'followToggle', + plural: false, + selections: [ + { + alias: null, + args: null, + concreteType: 'FollowEdge', + kind: 'LinkedField', + name: 'follow', + plural: false, + selections: [ + { + alias: null, + args: null, + concreteType: 'Follow', + kind: 'LinkedField', + name: 'node', + plural: false, + selections: [ + { + alias: null, + args: null, + concreteType: 'Profile', + kind: 'LinkedField', + name: 'target', + plural: false, + selections: [ + v2 /*: any*/, + v3 /*: any*/, + { + alias: null, + args: null, + kind: 'ScalarField', + name: '__typename', + storageKey: null, + }, + v4 /*: any*/, + ], + storageKey: null, + }, + v4 /*: any*/, + ], + storageKey: null, + }, + ], + storageKey: null, + }, + ], + storageKey: null, + }, + ], + }, + params: { + cacheID: 'ebebfbcba39ec99da7c9589554a460d5', + id: null, + metadata: {}, + name: 'FollowToggleMutation', + operationKind: 'mutation', + text: 'mutation FollowToggleMutation(\n $input: FollowToggleInput!\n) {\n followToggle(input: $input) {\n follow {\n node {\n target {\n isFollowedByMe\n followersCount\n __typename\n id\n }\n id\n }\n }\n }\n}\n', + }, + } +})() + +;(node as any).hash = 'd58a9c2e3572d54fec982030e1ccaab0' + +export default node diff --git a/packages/components/__generated__/FollowToggleUpdatableFragment.graphql.ts b/packages/components/__generated__/FollowToggleUpdatableFragment.graphql.ts new file mode 100644 index 00000000..0860759f --- /dev/null +++ b/packages/components/__generated__/FollowToggleUpdatableFragment.graphql.ts @@ -0,0 +1,51 @@ +/** + * @generated SignedSource<<0c7af4c419997e9ef8ef7bf922938d7c>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ + +/* eslint-disable */ +// @ts-nocheck +import { ReaderFragment, UpdatableFragment } from 'relay-runtime' +import { FragmentRefs } from 'relay-runtime' + +export type FollowToggleUpdatableFragment$data = { + followersCount: number | null | undefined + isFollowedByMe: boolean | null | undefined + readonly ' $fragmentType': 'FollowToggleUpdatableFragment' +} +export type FollowToggleUpdatableFragment$key = { + readonly ' $data'?: FollowToggleUpdatableFragment$data + readonly $updatableFragmentSpreads: FragmentRefs<'FollowToggleUpdatableFragment'> +} + +const node: ReaderFragment = { + argumentDefinitions: [], + kind: 'Fragment', + metadata: null, + name: 'FollowToggleUpdatableFragment', + selections: [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'isFollowedByMe', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'followersCount', + storageKey: null, + }, + ], + type: 'Profile', + abstractKey: null, +} + +;(node as any).hash = '4d151f5906c7d00fa429a6ccd27ca8bd' + +export default node diff --git a/packages/components/__generated__/ProfileComponentFragment.graphql.ts b/packages/components/__generated__/ProfileComponentFragment.graphql.ts new file mode 100644 index 00000000..63f366f5 --- /dev/null +++ b/packages/components/__generated__/ProfileComponentFragment.graphql.ts @@ -0,0 +1,231 @@ +/** + * @generated SignedSource<> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ + +/* eslint-disable */ +// @ts-nocheck +import { Fragment, ReaderFragment } from 'relay-runtime' +import { FragmentRefs } from 'relay-runtime' + +export type ProfilesProfileStatusChoices = 'A_1' | 'A_2' | '%future added value' + +export type ProfileComponentFragment$data = { + readonly bannerImage: + | { + readonly url: string + } + | null + | undefined + readonly biography: string | null | undefined + readonly canChange: boolean | null | undefined + readonly followersCount: number | null | undefined + readonly followingCount: number | null | undefined + readonly id: string + readonly image: + | { + readonly url: string + } + | null + | undefined + readonly isBlockedByMe: boolean | null | undefined + readonly isFollowedByMe: boolean | null | undefined + readonly name: string | null | undefined + readonly owner: { + readonly phoneNumber: string | null | undefined + } + readonly status: ProfilesProfileStatusChoices + readonly urlPath: + | { + readonly path: string + } + | null + | undefined + readonly ' $fragmentSpreads': FragmentRefs<'BlockToggleFragment'> + readonly ' $fragmentType': 'ProfileComponentFragment' +} +export type ProfileComponentFragment$key = { + readonly ' $data'?: ProfileComponentFragment$data + readonly ' $fragmentSpreads': FragmentRefs<'ProfileComponentFragment'> +} + +const node: ReaderFragment = (function () { + var v0 = [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'url', + storageKey: null, + }, + ] + return { + argumentDefinitions: [], + kind: 'Fragment', + metadata: null, + name: 'ProfileComponentFragment', + selections: [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'id', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'status', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'name', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'biography', + storageKey: null, + }, + { + alias: null, + args: [ + { + kind: 'Literal', + name: 'height', + value: 96, + }, + { + kind: 'Literal', + name: 'width', + value: 96, + }, + ], + concreteType: 'File', + kind: 'LinkedField', + name: 'image', + plural: false, + selections: v0 /*: any*/, + storageKey: 'image(height:96,width:96)', + }, + { + alias: null, + args: [ + { + kind: 'Literal', + name: 'height', + value: 290, + }, + { + kind: 'Literal', + name: 'width', + value: 868, + }, + ], + concreteType: 'File', + kind: 'LinkedField', + name: 'bannerImage', + plural: false, + selections: v0 /*: any*/, + storageKey: 'bannerImage(height:290,width:868)', + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'isFollowedByMe', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'followersCount', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'followingCount', + storageKey: null, + }, + { + alias: 'canChange', + args: [ + { + kind: 'Literal', + name: 'perm', + value: 'change', + }, + ], + kind: 'ScalarField', + name: 'hasPerm', + storageKey: 'hasPerm(perm:"change")', + }, + { + alias: null, + args: null, + concreteType: 'URLPath', + kind: 'LinkedField', + name: 'urlPath', + plural: false, + selections: [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'path', + storageKey: null, + }, + ], + storageKey: null, + }, + { + alias: null, + args: null, + concreteType: 'User', + kind: 'LinkedField', + name: 'owner', + plural: false, + selections: [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'phoneNumber', + storageKey: null, + }, + ], + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'isBlockedByMe', + storageKey: null, + }, + { + args: null, + kind: 'FragmentSpread', + name: 'BlockToggleFragment', + }, + ], + type: 'Profile', + abstractKey: null, + } +})() + +;(node as any).hash = '14c553f27fa01a11431eb14bb57b92c8' + +export default node diff --git a/packages/components/__generated__/ProfileUpdateMutation.graphql.ts b/packages/components/__generated__/ProfileUpdateMutation.graphql.ts new file mode 100644 index 00000000..5fa7fbd6 --- /dev/null +++ b/packages/components/__generated__/ProfileUpdateMutation.graphql.ts @@ -0,0 +1,343 @@ +/** + * @generated SignedSource<<836b5baa0a9d93ecb928d3531107a238>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ + +/* eslint-disable */ +// @ts-nocheck +import { ConcreteRequest, Mutation } from 'relay-runtime' +import { FragmentRefs } from 'relay-runtime' + +export type ProfileUpdateInput = { + bannerImage?: string | null | undefined + biography?: string | null | undefined + clientMutationId?: string | null | undefined + id: string + image?: string | null | undefined + name?: string | null | undefined + owner?: string | null | undefined + phoneNumber?: string | null | undefined + urlPath?: string | null | undefined +} +export type ProfileUpdateMutation$variables = { + input: ProfileUpdateInput +} +export type ProfileUpdateMutation$data = { + readonly profileUpdate: + | { + readonly errors: + | ReadonlyArray< + | { + readonly field: string + readonly messages: ReadonlyArray + } + | null + | undefined + > + | null + | undefined + readonly profile: + | { + readonly ' $fragmentSpreads': FragmentRefs<'ProfileComponentFragment'> + } + | null + | undefined + } + | null + | undefined +} +export type ProfileUpdateMutation = { + response: ProfileUpdateMutation$data + variables: ProfileUpdateMutation$variables +} + +const node: ConcreteRequest = (function () { + var v0 = [ + { + defaultValue: null, + kind: 'LocalArgument', + name: 'input', + }, + ], + v1 = [ + { + kind: 'Variable', + name: 'input', + variableName: 'input', + }, + ], + v2 = { + alias: null, + args: null, + concreteType: 'ErrorType', + kind: 'LinkedField', + name: 'errors', + plural: true, + selections: [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'field', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'messages', + storageKey: null, + }, + ], + storageKey: null, + }, + v3 = { + alias: null, + args: null, + kind: 'ScalarField', + name: 'id', + storageKey: null, + }, + v4 = [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'url', + storageKey: null, + }, + ] + return { + fragment: { + argumentDefinitions: v0 /*: any*/, + kind: 'Fragment', + metadata: null, + name: 'ProfileUpdateMutation', + selections: [ + { + alias: null, + args: v1 /*: any*/, + concreteType: 'ProfileUpdatePayload', + kind: 'LinkedField', + name: 'profileUpdate', + plural: false, + selections: [ + { + alias: null, + args: null, + concreteType: 'Profile', + kind: 'LinkedField', + name: 'profile', + plural: false, + selections: [ + { + args: null, + kind: 'FragmentSpread', + name: 'ProfileComponentFragment', + }, + ], + storageKey: null, + }, + v2 /*: any*/, + ], + storageKey: null, + }, + ], + type: 'Mutation', + abstractKey: null, + }, + kind: 'Request', + operation: { + argumentDefinitions: v0 /*: any*/, + kind: 'Operation', + name: 'ProfileUpdateMutation', + selections: [ + { + alias: null, + args: v1 /*: any*/, + concreteType: 'ProfileUpdatePayload', + kind: 'LinkedField', + name: 'profileUpdate', + plural: false, + selections: [ + { + alias: null, + args: null, + concreteType: 'Profile', + kind: 'LinkedField', + name: 'profile', + plural: false, + selections: [ + v3 /*: any*/, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'status', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'name', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'biography', + storageKey: null, + }, + { + alias: null, + args: [ + { + kind: 'Literal', + name: 'height', + value: 96, + }, + { + kind: 'Literal', + name: 'width', + value: 96, + }, + ], + concreteType: 'File', + kind: 'LinkedField', + name: 'image', + plural: false, + selections: v4 /*: any*/, + storageKey: 'image(height:96,width:96)', + }, + { + alias: null, + args: [ + { + kind: 'Literal', + name: 'height', + value: 290, + }, + { + kind: 'Literal', + name: 'width', + value: 868, + }, + ], + concreteType: 'File', + kind: 'LinkedField', + name: 'bannerImage', + plural: false, + selections: v4 /*: any*/, + storageKey: 'bannerImage(height:290,width:868)', + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'isFollowedByMe', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'followersCount', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'followingCount', + storageKey: null, + }, + { + alias: 'canChange', + args: [ + { + kind: 'Literal', + name: 'perm', + value: 'change', + }, + ], + kind: 'ScalarField', + name: 'hasPerm', + storageKey: 'hasPerm(perm:"change")', + }, + { + alias: null, + args: null, + concreteType: 'URLPath', + kind: 'LinkedField', + name: 'urlPath', + plural: false, + selections: [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'path', + storageKey: null, + }, + v3 /*: any*/, + ], + storageKey: null, + }, + { + alias: null, + args: null, + concreteType: 'User', + kind: 'LinkedField', + name: 'owner', + plural: false, + selections: [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'phoneNumber', + storageKey: null, + }, + v3 /*: any*/, + ], + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'isBlockedByMe', + storageKey: null, + }, + { + kind: 'TypeDiscriminator', + abstractKey: '__isBlocksInterface', + }, + ], + storageKey: null, + }, + v2 /*: any*/, + ], + storageKey: null, + }, + ], + }, + params: { + cacheID: 'c0e960cbeeab17c8f65cbae625436ab9', + id: null, + metadata: {}, + name: 'ProfileUpdateMutation', + operationKind: 'mutation', + text: 'mutation ProfileUpdateMutation(\n $input: ProfileUpdateInput!\n) {\n profileUpdate(input: $input) {\n profile {\n ...ProfileComponentFragment\n id\n }\n errors {\n field\n messages\n }\n }\n}\n\nfragment BlockToggleFragment on BlocksInterface {\n __isBlocksInterface: __typename\n id\n isBlockedByMe\n ... on Profile {\n id\n name\n }\n}\n\nfragment ProfileComponentFragment on Profile {\n id\n status\n name\n biography\n image(height: 96, width: 96) {\n url\n }\n bannerImage(height: 290, width: 868) {\n url\n }\n isFollowedByMe\n followersCount\n followingCount\n canChange: hasPerm(perm: "change")\n urlPath {\n path\n id\n }\n owner {\n phoneNumber\n id\n }\n isBlockedByMe\n ...BlockToggleFragment\n}\n', + }, + } +})() + +;(node as any).hash = 'b15251b426798b8c3457aed1249f8a64' + +export default node diff --git a/packages/components/modules/profiles/BlockButtonWithDialog/constants.ts b/packages/components/modules/profiles/BlockButtonWithDialog/constants.ts new file mode 100644 index 00000000..e88a5d73 --- /dev/null +++ b/packages/components/modules/profiles/BlockButtonWithDialog/constants.ts @@ -0,0 +1,14 @@ +export const BLOCK_UNBLOCK_DIALOG_TEXTS = { + block: { + title: 'Block', + content: + "This person won’t be able to send you messages, find your profile or content. They won’t see your comments and reactions, and won't be able to mention or follow your profile. We won't notify them that they have been blocked.", + action: 'Block', + }, + unblock: { + title: 'Unblock', + content: + "This person will be able to send you messages, find your profile or content. They will see your comments and reactions, and will be able to mention or follow your profile. We won't notify them that they have been unblocked.", + action: 'Unblock', + }, +} diff --git a/packages/components/modules/profiles/BlockButtonWithDialog/index.tsx b/packages/components/modules/profiles/BlockButtonWithDialog/index.tsx new file mode 100644 index 00000000..82826618 --- /dev/null +++ b/packages/components/modules/profiles/BlockButtonWithDialog/index.tsx @@ -0,0 +1,125 @@ +import { FC, useState } from 'react' + +import { BlockIcon, ConfirmDialog, UnblockIcon } from '@baseapp-frontend/design-system' +import { useNotification } from '@baseapp-frontend/utils' + +import { Button, CircularProgress, Typography } from '@mui/material' +import { useFragment, useMutation } from 'react-relay' + +import { BlockToggleMutation } from '../../../__generated__/BlockToggleMutation.graphql' +import { BlockToggleMutationQuery } from '../graphql/mutations/BlockToggle' +import { BlockToggleFragment } from '../graphql/queries/BlockToggle' +import { BLOCK_UNBLOCK_DIALOG_TEXTS } from './constants' +import { ActionButton } from './styled' +import { BlockButtonWithDialogProps } from './types' + +const BlockButtonWithDialog: FC = ({ + target: targetRef, + isMenu, + handleError, + handleCloseMenu, + currentProfileId, +}) => { + const target = useFragment(BlockToggleFragment, targetRef) + const [commitMutation, isMutationInFlight] = + useMutation(BlockToggleMutationQuery) + const { sendToast } = useNotification() + const [open, setOpen] = useState(false) + + const isBlockedByMe = target?.isBlockedByMe + + const handleOpen = () => { + setOpen(true) + } + + const handleClose = () => { + setOpen(false) + } + + const handleSuccess = () => { + setOpen(false) + handleCloseMenu?.() + } + + const handleBlock = () => { + if (isMutationInFlight || !currentProfileId || !target) { + return + } + + commitMutation({ + variables: { + input: { + targetObjectId: target.id, + actorObjectId: currentProfileId, + }, + }, + onCompleted: (response, errors) => { + errors?.forEach((error) => { + sendToast(error.message, { type: 'error' }) + }) + handleSuccess() + sendToast( + `${target.name ?? ''} is ${response?.blockToggle?.target?.isBlockedByMe ? 'blocked' : 'unblocked'}`, + { type: 'info' }, + ) + }, + onError: () => { + handleError?.() + }, + }) + } + + return ( + <> + + + {isBlockedByMe ? : } + {`${isBlockedByMe ? BLOCK_UNBLOCK_DIALOG_TEXTS.unblock.title : BLOCK_UNBLOCK_DIALOG_TEXTS.block.title} ${target.name}?`} + + } + content={ + isBlockedByMe + ? BLOCK_UNBLOCK_DIALOG_TEXTS.unblock.content + : BLOCK_UNBLOCK_DIALOG_TEXTS.block.content + } + onClose={handleClose} + action={ + + {isBlockedByMe + ? BLOCK_UNBLOCK_DIALOG_TEXTS.unblock.action + : BLOCK_UNBLOCK_DIALOG_TEXTS.block.action} + {isMutationInFlight && } + + } + /> + + ) +} + +export default BlockButtonWithDialog diff --git a/packages/components/modules/profiles/BlockButtonWithDialog/styled.tsx b/packages/components/modules/profiles/BlockButtonWithDialog/styled.tsx new file mode 100644 index 00000000..61c8241f --- /dev/null +++ b/packages/components/modules/profiles/BlockButtonWithDialog/styled.tsx @@ -0,0 +1,11 @@ +import { Button } from '@mui/material' +import { styled } from '@mui/material/styles' + +import { ActionButtonProps } from './types' + +export const ActionButton = styled(Button)(({ theme, isBlocked = false }) => ({ + backgroundColor: isBlocked ? theme.palette.grey[800] : theme.palette.error.main, + '&:hover': { + backgroundColor: isBlocked ? theme.palette.grey[900] : theme.palette.error.dark, + }, +})) diff --git a/packages/components/modules/profiles/BlockButtonWithDialog/types.ts b/packages/components/modules/profiles/BlockButtonWithDialog/types.ts new file mode 100644 index 00000000..28e4b8a4 --- /dev/null +++ b/packages/components/modules/profiles/BlockButtonWithDialog/types.ts @@ -0,0 +1,15 @@ +import { ButtonProps } from '@mui/material' + +import { BlockToggleFragment$key } from '../../../__generated__/BlockToggleFragment.graphql' + +export interface ActionButtonProps extends ButtonProps { + isBlocked?: boolean | null +} + +export interface BlockButtonWithDialogProps { + target: BlockToggleFragment$key + currentProfileId?: string + isMenu?: boolean + handleError?: () => void + handleCloseMenu?: () => void +} diff --git a/packages/components/modules/profiles/FollowToggleButton/index.tsx b/packages/components/modules/profiles/FollowToggleButton/index.tsx new file mode 100644 index 00000000..5c448ccf --- /dev/null +++ b/packages/components/modules/profiles/FollowToggleButton/index.tsx @@ -0,0 +1,84 @@ +import { FC } from 'react' + +import { Iconify } from '@baseapp-frontend/design-system' +import { useNotification } from '@baseapp-frontend/utils' + +import { Button } from '@mui/material' +import { useMutation, useRelayEnvironment } from 'react-relay' +import { RecordSourceSelectorProxy, commitLocalUpdate } from 'relay-runtime' + +import { FollowToggleMutation } from '../../../__generated__/FollowToggleMutation.graphql' +import { FollowToggleMutationQuery } from '../graphql/mutations/FollowToggle' +import { FollowToggleUpdatableFragment } from '../graphql/queries/FollowToggleUpdatableFragment' +import { FollowToggleButtonProps } from './types' + +const FollowToggleButton: FC = ({ + targetId, + isFollowedByMe, + currentProfileId, + profileRef, +}) => { + const [commitMutation, isMutationInFlight] = + useMutation(FollowToggleMutationQuery) + const { sendToast } = useNotification() + const environment = useRelayEnvironment() + + const toggleFollow = () => { + if (isMutationInFlight || !currentProfileId) { + return + } + + commitMutation({ + variables: { + input: { + targetObjectId: targetId, + actorObjectId: currentProfileId, + }, + }, + onCompleted: (response, errors) => { + errors?.forEach((error) => { + sendToast(error.message, { type: 'error' }) + }) + if (errors) { + return + } + const follow = response.followToggle?.follow + + commitLocalUpdate(environment, (store: RecordSourceSelectorProxy) => { + if (profileRef == null) { + return + } + + const { updatableData } = store.readUpdatableFragment( + FollowToggleUpdatableFragment, + profileRef, + ) + + const updatedIsFollowedByMe = follow?.node?.target?.isFollowedByMe ?? false + const updatedFollowersCount = + follow?.node?.target?.followersCount ?? updatableData.followersCount - 1 + + updatableData.isFollowedByMe = updatedIsFollowedByMe + updatableData.followersCount = updatedFollowersCount + }) + }, + }) + } + + return ( + + ) +} + +export default FollowToggleButton diff --git a/packages/components/modules/profiles/FollowToggleButton/types.ts b/packages/components/modules/profiles/FollowToggleButton/types.ts new file mode 100644 index 00000000..380250bb --- /dev/null +++ b/packages/components/modules/profiles/FollowToggleButton/types.ts @@ -0,0 +1,6 @@ +export interface FollowToggleButtonProps { + targetId: string + isFollowedByMe: boolean | null | undefined + currentProfileId?: string + profileRef?: any +} diff --git a/packages/components/modules/profiles/ProfileComponent/index.tsx b/packages/components/modules/profiles/ProfileComponent/index.tsx new file mode 100644 index 00000000..4e9846cf --- /dev/null +++ b/packages/components/modules/profiles/ProfileComponent/index.tsx @@ -0,0 +1,212 @@ +'use client' + +import { FC, useState } from 'react' + +import { useCurrentProfile } from '@baseapp-frontend/authentication' +import { + AvatarWithPlaceholder, + ImageWithFallback, + OutlinedEditIcon, + ShareIcon, + SwipeableDrawer, + ThreeDotsIcon, + useResponsive, +} from '@baseapp-frontend/design-system' +import { useNotification } from '@baseapp-frontend/utils' + +import { Button, MenuItem, Typography } from '@mui/material' +import { useRouter } from 'next/navigation' +import numbro from 'numbro' +import { useFragment } from 'react-relay' + +import BlockButtonWithDialog from '../BlockButtonWithDialog' +import FollowToggleButton from '../FollowToggleButton' +import { ProfileComponentFragment } from '../graphql/queries/ProfileComponent' +import { + ProfileContainer, + ProfileContentContainer, + ProfileDescriptionContainer, + ProfileNameContainer, + StyledMenu, +} from './styled' +import { ProfileComponentProps } from './types' + +const ProfileComponent: FC = ({ profile: profileRef }) => { + const profile = useFragment(ProfileComponentFragment, profileRef) + const smDown = useResponsive('down', 'sm') + const router = useRouter() + const [anchorEl, setAnchorEl] = useState(null) + const { currentProfile } = useCurrentProfile() + + const open = Boolean(anchorEl) + const handleClick = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget) + } + const handleClose = () => { + setAnchorEl(null) + } + const { sendToast } = useNotification() + + const handleShareClick = () => { + const path = profile?.urlPath?.path ?? `/profile/${profile?.id}` + const url = [process.env.NEXT_PUBLIC_APP_BASE_URL, path].join('') + navigator.clipboard.writeText(url) + sendToast('Profile URL copied to clipboard!', { type: 'success' }) + handleClose() + } + + const formatFollowCount = (count?: number | null) => { + if (!count || count === 0) { + return 0 + } + if (count <= 1000) { + return count + } + if (count < 1050000) { + return numbro(count).format({ average: true }) + } + return numbro(count).format({ average: true, mantissa: 1 }) + } + + const renderProfileUpdatesButtons = () => { + if (profile && currentProfile) { + if (profile.id === currentProfile.id) { + return ( + + ) + } + return ( +
+ {!profile?.isBlockedByMe && ( + + )} + {profile?.isBlockedByMe && ( + + )} +
+ ) + } + return
+ } + + return ( +
+ + + + + + +
+ + {profile?.name} + + + {profile?.urlPath?.path ? `@${profile.urlPath.path}` : ''} + +
+
+
+ + {formatFollowCount(profile?.followersCount)} + + + Followers + +
+
+ + {formatFollowCount(profile?.followingCount)} + + + Following + +
+
+
+

{profile?.biography}

+
+
+ {renderProfileUpdatesButtons()} + + {!smDown && ( + + + + Share profile + + {profile && ( + + )} + + )} + {smDown && ( + + + + Share profile + + {profile && ( + + )} + + )} +
+
+
+
+ ) +} + +export default ProfileComponent diff --git a/packages/components/modules/profiles/ProfileComponent/styled.tsx b/packages/components/modules/profiles/ProfileComponent/styled.tsx new file mode 100644 index 00000000..250bffc6 --- /dev/null +++ b/packages/components/modules/profiles/ProfileComponent/styled.tsx @@ -0,0 +1,84 @@ +import { Box, Menu, MenuProps } from '@mui/material' +import { alpha, styled } from '@mui/material/styles' + +export const ProfileContainer = styled(Box)(({ theme }) => ({ + boxSizing: 'content-box', + display: 'grid', + width: '100%', + height: '100%', + maxWidth: 'fit-content', + gridAutoRows: 'max-content', + gridTemplateColumns: '1fr', + rowGap: theme.spacing(3), + placeSelf: 'center', + padding: `0 ${theme.spacing(2)} ${theme.spacing(2)}`, +})) + +export const ProfileContentContainer = styled(Box)(({ theme }) => ({ + display: 'grid', + gridTemplateColumns: '1fr', + gridTemplateRows: 'min-content auto', + gap: theme.spacing(3), + position: 'relative', + top: -48, + justifyContent: 'center', + [theme.breakpoints.up('sm')]: { + position: 'static', + top: 0, + gridTemplateColumns: 'max-content 480px', + gridTemplateRows: '1fr', + }, +})) + +export const ProfileDescriptionContainer = styled(Box)(({ theme }) => ({ + display: 'grid', + gridTemplateRows: 'auto auto', + gap: theme.spacing(3), + [theme.breakpoints.up('sm')]: { + gap: theme.spacing(2), + }, +})) + +export const ProfileNameContainer = styled(Box)(({ theme }) => ({ + display: 'grid', + gridTemplateRows: 'auto auto', + gridTemplateColumns: '1fr', + rowGap: theme.spacing(3), + placeItems: 'stretch', + justifyItems: 'center', + [theme.breakpoints.up('sm')]: { + gridTemplateRows: 'none', + gridTemplateColumns: '1fr 1fr', + columnGap: theme.spacing(3), + }, +})) + +export const StyledMenu = styled((props: MenuProps) => ( + +))(({ theme }) => ({ + '& .MuiPaper-root': { + minWidth: 190, + '& .MuiMenuItem-root': { + '& .MuiSvgIcon-root': { + marginRight: theme.spacing(1.5), + }, + '&:active': { + backgroundColor: alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity), + }, + }, + ...theme.applyStyles('dark', { + color: theme.palette.grey[300], + }), + }, +})) diff --git a/packages/components/modules/profiles/ProfileComponent/types.ts b/packages/components/modules/profiles/ProfileComponent/types.ts new file mode 100644 index 00000000..c46343d0 --- /dev/null +++ b/packages/components/modules/profiles/ProfileComponent/types.ts @@ -0,0 +1,5 @@ +import { ProfileComponentFragment$key } from '../../../__generated__/ProfileComponentFragment.graphql' + +export interface ProfileComponentProps { + profile?: ProfileComponentFragment$key | null +} diff --git a/packages/components/modules/profiles/graphql/mutations/BlockToggle.ts b/packages/components/modules/profiles/graphql/mutations/BlockToggle.ts new file mode 100644 index 00000000..dd90e334 --- /dev/null +++ b/packages/components/modules/profiles/graphql/mutations/BlockToggle.ts @@ -0,0 +1,19 @@ +import { graphql } from 'relay-runtime' + +export const BlockToggleMutationQuery = graphql` + mutation BlockToggleMutation($input: BlockToggleInput!) { + blockToggle(input: $input) { + block { + node { + id + } + } + blockDeletedId @deleteRecord + target { + id + isBlockedByMe + ...BlockToggleFragment + } + } + } +` diff --git a/packages/components/modules/profiles/graphql/mutations/FollowToggle.ts b/packages/components/modules/profiles/graphql/mutations/FollowToggle.ts new file mode 100644 index 00000000..28d9c91d --- /dev/null +++ b/packages/components/modules/profiles/graphql/mutations/FollowToggle.ts @@ -0,0 +1,17 @@ +import { graphql } from 'relay-runtime' + +export const FollowToggleMutationQuery = graphql` + mutation FollowToggleMutation($input: FollowToggleInput!) { + followToggle(input: $input) { + follow { + node { + target { + isFollowedByMe + followersCount + ...FollowToggleUpdatableFragment + } + } + } + } + } +` diff --git a/packages/components/modules/profiles/graphql/mutations/ProfileUpdate.ts b/packages/components/modules/profiles/graphql/mutations/ProfileUpdate.ts new file mode 100644 index 00000000..2c84fb85 --- /dev/null +++ b/packages/components/modules/profiles/graphql/mutations/ProfileUpdate.ts @@ -0,0 +1,20 @@ +import { graphql, useMutation } from 'react-relay' + +import { ProfileUpdateMutation } from '../../../../__generated__/ProfileUpdateMutation.graphql' + +const ProfileUpdateMutationQuery = graphql` + mutation ProfileUpdateMutation($input: ProfileUpdateInput!) { + profileUpdate(input: $input) { + profile { + ...ProfileComponentFragment + } + errors { + field + messages + } + } + } +` + +export const useProfileMutation = () => + useMutation(ProfileUpdateMutationQuery) diff --git a/packages/components/modules/profiles/graphql/queries/BlockToggle.ts b/packages/components/modules/profiles/graphql/queries/BlockToggle.ts new file mode 100644 index 00000000..4cfae378 --- /dev/null +++ b/packages/components/modules/profiles/graphql/queries/BlockToggle.ts @@ -0,0 +1,12 @@ +import { graphql } from 'relay-runtime' + +export const BlockToggleFragment = graphql` + fragment BlockToggleFragment on BlocksInterface { + id + isBlockedByMe + ... on Profile { + id + name + } + } +` diff --git a/packages/components/modules/profiles/graphql/queries/FollowToggleUpdatableFragment.ts b/packages/components/modules/profiles/graphql/queries/FollowToggleUpdatableFragment.ts new file mode 100644 index 00000000..d8939562 --- /dev/null +++ b/packages/components/modules/profiles/graphql/queries/FollowToggleUpdatableFragment.ts @@ -0,0 +1,8 @@ +import { graphql } from 'relay-runtime' + +export const FollowToggleUpdatableFragment = graphql` + fragment FollowToggleUpdatableFragment on Profile @updatable { + isFollowedByMe + followersCount + } +` diff --git a/packages/components/modules/profiles/graphql/queries/ProfileComponent.ts b/packages/components/modules/profiles/graphql/queries/ProfileComponent.ts new file mode 100644 index 00000000..d781587c --- /dev/null +++ b/packages/components/modules/profiles/graphql/queries/ProfileComponent.ts @@ -0,0 +1,28 @@ +import { graphql } from 'react-relay' + +export const ProfileComponentFragment = graphql` + fragment ProfileComponentFragment on Profile { + id + status + name + biography + image(height: 96, width: 96) { + url + } + bannerImage(height: 290, width: 868) { + url + } + isFollowedByMe + followersCount + followingCount + canChange: hasPerm(perm: "change") + urlPath { + path + } + owner { + phoneNumber + } + isBlockedByMe + ...BlockToggleFragment + } +` diff --git a/packages/components/modules/profiles/index.ts b/packages/components/modules/profiles/index.ts index 47b231a8..355326d9 100644 --- a/packages/components/modules/profiles/index.ts +++ b/packages/components/modules/profiles/index.ts @@ -1,2 +1,4 @@ export * from './ProfilePopover' export { default as Members } from './Members' +export { default as ProfileComponent } from './ProfileComponent' +export type * from './ProfileComponent/types' diff --git a/packages/components/package.json b/packages/components/package.json index e2e1531f..87a47ade 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -37,6 +37,7 @@ "js-cookie": "catalog:", "luxon": "catalog:", "next": "catalog:", + "numbro": "^2.5.0", "react-hook-form": "catalog:", "react-relay": "catalog:graphql", "react-virtuoso": "catalog:", diff --git a/packages/design-system/.storybook/preview.ts b/packages/design-system/.storybook/preview.ts index 250f7bdf..3ac8f16b 100644 --- a/packages/design-system/.storybook/preview.ts +++ b/packages/design-system/.storybook/preview.ts @@ -32,6 +32,8 @@ const preview: Preview = { 'LoadingState', // Drawers 'SwipeableDrawer', + // Images + 'ImageWithFallback', // Popover 'Popover', // Form diff --git a/packages/design-system/components/icons/BlockIcon/index.tsx b/packages/design-system/components/icons/BlockIcon/index.tsx new file mode 100644 index 00000000..fbef10f6 --- /dev/null +++ b/packages/design-system/components/icons/BlockIcon/index.tsx @@ -0,0 +1,24 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const BlockIcon: FC = ({ sx, ...props }) => ( + + + + + + +) + +export default BlockIcon diff --git a/packages/design-system/components/icons/ThreeDotsIcon/index.tsx b/packages/design-system/components/icons/ThreeDotsIcon/index.tsx new file mode 100644 index 00000000..40695225 --- /dev/null +++ b/packages/design-system/components/icons/ThreeDotsIcon/index.tsx @@ -0,0 +1,33 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const ThreeDotsIcon: FC = ({ sx, ...props }) => ( + + + + + + + +) + +export default ThreeDotsIcon diff --git a/packages/design-system/components/icons/UnblockIcon/index.tsx b/packages/design-system/components/icons/UnblockIcon/index.tsx new file mode 100644 index 00000000..802627ed --- /dev/null +++ b/packages/design-system/components/icons/UnblockIcon/index.tsx @@ -0,0 +1,30 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const UnblockIcon: FC = ({ sx, ...props }) => ( + + + + + + + +) + +export default UnblockIcon diff --git a/packages/design-system/components/icons/index.ts b/packages/design-system/components/icons/index.ts index d1c8732e..22499dca 100644 --- a/packages/design-system/components/icons/index.ts +++ b/packages/design-system/components/icons/index.ts @@ -2,6 +2,7 @@ export { default as AddIcon } from './AddIcon' export { default as ArchiveIcon } from './ArchiveIcon' export { default as AttachmentIcon } from './AttachmentIcon' export { default as BaseAppLogoCondensed } from './BaseAppLogoCondensed' +export { default as BlockIcon } from './BlockIcon' export { default as CheckMarkIcon } from './CheckMarkIcon' export { default as ChevronIcon } from './ChevronIcon' export { default as CloseIcon } from './CloseIcon' @@ -17,6 +18,8 @@ export { default as PenEditIcon } from './PenEditIcon' export { default as PinIcon } from './PinIcon' export { default as SendMessageIcon } from './SendMessageIcon' export { default as ShareIcon } from './ShareIcon' +export { default as ThreeDotsIcon } from './ThreeDotsIcon' export { default as TrashCanIcon } from './TrashCanIcon' export { default as UnarchiveIcon } from './UnarchiveIcon' +export { default as UnblockIcon } from './UnblockIcon' export { default as UnreadIcon } from './UnreadIcon' diff --git a/packages/design-system/components/images/ImageWithFallback/__storybook__/stories.tsx b/packages/design-system/components/images/ImageWithFallback/__storybook__/stories.tsx new file mode 100644 index 00000000..3e2a4685 --- /dev/null +++ b/packages/design-system/components/images/ImageWithFallback/__storybook__/stories.tsx @@ -0,0 +1,24 @@ +import React from 'react' + +import { Meta, StoryFn, StoryObj } from '@storybook/react' + +import ImageWithFallback from '..' +import { ImageWithFallbackProps } from '../types' + +export default { + title: '@baseapp-frontend-template / Design System/Displays/ImageWithFallback', + component: ImageWithFallback, +} as Meta + +type Story = StoryObj + +const Template: StoryFn = (args) => + +export const Default: Story = Template.bind({}) +Default.args = { + src: '/webp/home-banner.webp', + fallbackSrc: '/png/home-banner.png', + alt: 'Example image', + width: 400, + height: 300, +} diff --git a/packages/design-system/components/images/ImageWithFallback/index.tsx b/packages/design-system/components/images/ImageWithFallback/index.tsx new file mode 100644 index 00000000..5c69830b --- /dev/null +++ b/packages/design-system/components/images/ImageWithFallback/index.tsx @@ -0,0 +1,36 @@ +import { FC } from 'react' + +import Image from 'next/image' + +import { ImageWithFallbackProps } from './types' + +/** + * This component can have more than one source, offering alternative versions of an image for different display/device scenarios. + * + * It uses, by default, the webp format, but if the browser doesn't support it, it will fall back to png. + * + * @description + * This is a **BaseApp** feature. + * + * Developers can freely edit this to suit the project's needs. + * + * If you believe your changes should be in the BaseApp, please read the **CONTRIBUTING.md** guide. + */ +const ImageWithFallback: FC = ({ + src, + fallbackSrc, + type = 'image/webp', + fallbackType = 'image/png', + alt, + width, + height, + ...props +}) => ( + + + + {alt} + +) + +export default ImageWithFallback diff --git a/packages/design-system/components/images/ImageWithFallback/types.ts b/packages/design-system/components/images/ImageWithFallback/types.ts new file mode 100644 index 00000000..128de52a --- /dev/null +++ b/packages/design-system/components/images/ImageWithFallback/types.ts @@ -0,0 +1,11 @@ +import { ImageProps } from 'next/image' + +export interface ImageWithFallbackProps extends ImageProps { + src: string + fallbackSrc: string + type?: string + fallbackType?: string + alt: string + width: number + height: number +} diff --git a/packages/design-system/components/images/index.ts b/packages/design-system/components/images/index.ts new file mode 100644 index 00000000..6ddce5a4 --- /dev/null +++ b/packages/design-system/components/images/index.ts @@ -0,0 +1 @@ +export { default as ImageWithFallback } from './ImageWithFallback' diff --git a/packages/design-system/index.ts b/packages/design-system/index.ts index ca28fedd..74d72ee2 100644 --- a/packages/design-system/index.ts +++ b/packages/design-system/index.ts @@ -26,6 +26,7 @@ export * from './components/displays' export * from './components/drawers' export * from './components/icons' export * from './components/illustrations' +export * from './components/images' export * from './components/inputs' export * from './components/typographies' diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 42e91930..f2b757e6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -521,6 +521,9 @@ importers: next: specifier: 'catalog:' version: 14.3.0-canary.24(@babel/core@7.26.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + numbro: + specifier: ^2.5.0 + version: 2.5.0 react: specifier: catalog:react18 version: 18.3.1 @@ -4855,6 +4858,9 @@ packages: big.js@5.2.2: resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} + bignumber.js@9.1.2: + resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==} + binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} @@ -8028,6 +8034,9 @@ packages: nullthrows@1.1.1: resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==} + numbro@2.5.0: + resolution: {integrity: sha512-xDcctDimhzko/e+y+Q2/8i3qNC9Svw1QgOkSkQoO0kIPI473tR9QRbo2KP88Ty9p8WbPy+3OpTaAIzehtuHq+A==} + nwsapi@2.2.16: resolution: {integrity: sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==} @@ -15131,6 +15140,8 @@ snapshots: big.js@5.2.2: {} + bignumber.js@9.1.2: {} + binary-extensions@2.3.0: {} blob-util@2.0.2: {} @@ -19033,6 +19044,10 @@ snapshots: nullthrows@1.1.1: {} + numbro@2.5.0: + dependencies: + bignumber.js: 9.1.2 + nwsapi@2.2.16: {} ob1@0.81.0: From d3c7e67edf25ca3a4425f5081682eeb8bd2e56bd Mon Sep 17 00:00:00 2001 From: Pedro Tiburcio Date: Fri, 20 Dec 2024 11:07:16 -0500 Subject: [PATCH 2/5] chore: versioning --- packages/components/CHANGELOG.md | 10 ++++++++++ packages/components/package.json | 2 +- packages/design-system/CHANGELOG.md | 6 ++++++ packages/design-system/package.json | 2 +- packages/wagtail/CHANGELOG.md | 7 +++++++ packages/wagtail/package.json | 2 +- 6 files changed, 26 insertions(+), 3 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 2fcb7b79..5c42b3a5 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -1,5 +1,14 @@ # @baseapp-frontend/components +## 0.0.41 + +### Patch Changes + +- Added FollowToggle button +- Moved BlockButtonWithDialog, ProfileComponent and related queries and mutations from baseapp-frontend-template +- Updated dependencies + - @baseapp-frontend/design-system@0.0.27 + ## 0.0.40 ### Patch Changes @@ -46,6 +55,7 @@ - Updated dependencies - @baseapp-frontend/graphql@1.1.14 + ## 0.0.34 ### Patch Changes diff --git a/packages/components/package.json b/packages/components/package.json index 87a47ade..df68ad2c 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,7 +1,7 @@ { "name": "@baseapp-frontend/components", "description": "BaseApp components modules such as comments, notifications, messages, and more.", - "version": "0.0.40", + "version": "0.0.41", "main": "./index.ts", "types": "dist/index.d.ts", "sideEffects": false, diff --git a/packages/design-system/CHANGELOG.md b/packages/design-system/CHANGELOG.md index 17e64046..bdbd2ff0 100644 --- a/packages/design-system/CHANGELOG.md +++ b/packages/design-system/CHANGELOG.md @@ -1,5 +1,11 @@ # @baseapp-frontend/design-system +## 0.0.27 + +### Patch Changes + +- Moved BlockIcon, UnblockIcon, ThreeDotsIcon and ImageWithFallback from baseapp-frontend-template + ## 0.0.26 ### Patch Changes diff --git a/packages/design-system/package.json b/packages/design-system/package.json index 99fc94d6..15d8d399 100644 --- a/packages/design-system/package.json +++ b/packages/design-system/package.json @@ -1,7 +1,7 @@ { "name": "@baseapp-frontend/design-system", "description": "Design System components and configurations.", - "version": "0.0.26", + "version": "0.0.27", "main": "./index.ts", "types": "dist/index.d.ts", "sideEffects": false, diff --git a/packages/wagtail/CHANGELOG.md b/packages/wagtail/CHANGELOG.md index 5a8b1d18..4c59e128 100644 --- a/packages/wagtail/CHANGELOG.md +++ b/packages/wagtail/CHANGELOG.md @@ -1,5 +1,12 @@ # @baseapp-frontend/wagtail +## 1.0.12 + +### Patch Changes + +- Updated dependencies + - @baseapp-frontend/design-system@0.0.27 + ## 1.0.11 ### Patch Changes diff --git a/packages/wagtail/package.json b/packages/wagtail/package.json index d7351144..98c24c39 100644 --- a/packages/wagtail/package.json +++ b/packages/wagtail/package.json @@ -1,7 +1,7 @@ { "name": "@baseapp-frontend/wagtail", "description": "BaseApp Wagtail", - "version": "1.0.11", + "version": "1.0.12", "main": "./index.ts", "types": "dist/index.d.ts", "sideEffects": false, From c03daec5a0af98b646e19457c01854d1a2d146fa Mon Sep 17 00:00:00 2001 From: Alexandre Anicio Date: Mon, 30 Dec 2024 15:17:31 -0300 Subject: [PATCH 3/5] tweaks --- .../BlockButtonWithDialog/constants.ts | 0 .../{ => ProfileComponent}/BlockButtonWithDialog/index.tsx | 6 +++--- .../{ => ProfileComponent}/BlockButtonWithDialog/styled.tsx | 0 .../{ => ProfileComponent}/BlockButtonWithDialog/types.ts | 2 +- .../{ => ProfileComponent}/FollowToggleButton/index.tsx | 6 +++--- .../{ => ProfileComponent}/FollowToggleButton/types.ts | 0 .../components/modules/profiles/ProfileComponent/index.tsx | 4 ++-- 7 files changed, 9 insertions(+), 9 deletions(-) rename packages/components/modules/profiles/{ => ProfileComponent}/BlockButtonWithDialog/constants.ts (100%) rename packages/components/modules/profiles/{ => ProfileComponent}/BlockButtonWithDialog/index.tsx (93%) rename packages/components/modules/profiles/{ => ProfileComponent}/BlockButtonWithDialog/styled.tsx (100%) rename packages/components/modules/profiles/{ => ProfileComponent}/BlockButtonWithDialog/types.ts (77%) rename packages/components/modules/profiles/{ => ProfileComponent}/FollowToggleButton/index.tsx (89%) rename packages/components/modules/profiles/{ => ProfileComponent}/FollowToggleButton/types.ts (100%) diff --git a/packages/components/modules/profiles/BlockButtonWithDialog/constants.ts b/packages/components/modules/profiles/ProfileComponent/BlockButtonWithDialog/constants.ts similarity index 100% rename from packages/components/modules/profiles/BlockButtonWithDialog/constants.ts rename to packages/components/modules/profiles/ProfileComponent/BlockButtonWithDialog/constants.ts diff --git a/packages/components/modules/profiles/BlockButtonWithDialog/index.tsx b/packages/components/modules/profiles/ProfileComponent/BlockButtonWithDialog/index.tsx similarity index 93% rename from packages/components/modules/profiles/BlockButtonWithDialog/index.tsx rename to packages/components/modules/profiles/ProfileComponent/BlockButtonWithDialog/index.tsx index 82826618..e47c2ce2 100644 --- a/packages/components/modules/profiles/BlockButtonWithDialog/index.tsx +++ b/packages/components/modules/profiles/ProfileComponent/BlockButtonWithDialog/index.tsx @@ -6,9 +6,9 @@ import { useNotification } from '@baseapp-frontend/utils' import { Button, CircularProgress, Typography } from '@mui/material' import { useFragment, useMutation } from 'react-relay' -import { BlockToggleMutation } from '../../../__generated__/BlockToggleMutation.graphql' -import { BlockToggleMutationQuery } from '../graphql/mutations/BlockToggle' -import { BlockToggleFragment } from '../graphql/queries/BlockToggle' +import { BlockToggleMutation } from '../../../../__generated__/BlockToggleMutation.graphql' +import { BlockToggleMutationQuery } from '../../graphql/mutations/BlockToggle' +import { BlockToggleFragment } from '../../graphql/queries/BlockToggle' import { BLOCK_UNBLOCK_DIALOG_TEXTS } from './constants' import { ActionButton } from './styled' import { BlockButtonWithDialogProps } from './types' diff --git a/packages/components/modules/profiles/BlockButtonWithDialog/styled.tsx b/packages/components/modules/profiles/ProfileComponent/BlockButtonWithDialog/styled.tsx similarity index 100% rename from packages/components/modules/profiles/BlockButtonWithDialog/styled.tsx rename to packages/components/modules/profiles/ProfileComponent/BlockButtonWithDialog/styled.tsx diff --git a/packages/components/modules/profiles/BlockButtonWithDialog/types.ts b/packages/components/modules/profiles/ProfileComponent/BlockButtonWithDialog/types.ts similarity index 77% rename from packages/components/modules/profiles/BlockButtonWithDialog/types.ts rename to packages/components/modules/profiles/ProfileComponent/BlockButtonWithDialog/types.ts index 28e4b8a4..2237df49 100644 --- a/packages/components/modules/profiles/BlockButtonWithDialog/types.ts +++ b/packages/components/modules/profiles/ProfileComponent/BlockButtonWithDialog/types.ts @@ -1,6 +1,6 @@ import { ButtonProps } from '@mui/material' -import { BlockToggleFragment$key } from '../../../__generated__/BlockToggleFragment.graphql' +import { BlockToggleFragment$key } from '../../../../__generated__/BlockToggleFragment.graphql' export interface ActionButtonProps extends ButtonProps { isBlocked?: boolean | null diff --git a/packages/components/modules/profiles/FollowToggleButton/index.tsx b/packages/components/modules/profiles/ProfileComponent/FollowToggleButton/index.tsx similarity index 89% rename from packages/components/modules/profiles/FollowToggleButton/index.tsx rename to packages/components/modules/profiles/ProfileComponent/FollowToggleButton/index.tsx index 5c448ccf..4f8e16d8 100644 --- a/packages/components/modules/profiles/FollowToggleButton/index.tsx +++ b/packages/components/modules/profiles/ProfileComponent/FollowToggleButton/index.tsx @@ -7,9 +7,9 @@ import { Button } from '@mui/material' import { useMutation, useRelayEnvironment } from 'react-relay' import { RecordSourceSelectorProxy, commitLocalUpdate } from 'relay-runtime' -import { FollowToggleMutation } from '../../../__generated__/FollowToggleMutation.graphql' -import { FollowToggleMutationQuery } from '../graphql/mutations/FollowToggle' -import { FollowToggleUpdatableFragment } from '../graphql/queries/FollowToggleUpdatableFragment' +import { FollowToggleMutation } from '../../../../__generated__/FollowToggleMutation.graphql' +import { FollowToggleMutationQuery } from '../../graphql/mutations/FollowToggle' +import { FollowToggleUpdatableFragment } from '../../graphql/queries/FollowToggleUpdatableFragment' import { FollowToggleButtonProps } from './types' const FollowToggleButton: FC = ({ diff --git a/packages/components/modules/profiles/FollowToggleButton/types.ts b/packages/components/modules/profiles/ProfileComponent/FollowToggleButton/types.ts similarity index 100% rename from packages/components/modules/profiles/FollowToggleButton/types.ts rename to packages/components/modules/profiles/ProfileComponent/FollowToggleButton/types.ts diff --git a/packages/components/modules/profiles/ProfileComponent/index.tsx b/packages/components/modules/profiles/ProfileComponent/index.tsx index 4e9846cf..9c070960 100644 --- a/packages/components/modules/profiles/ProfileComponent/index.tsx +++ b/packages/components/modules/profiles/ProfileComponent/index.tsx @@ -19,9 +19,9 @@ import { useRouter } from 'next/navigation' import numbro from 'numbro' import { useFragment } from 'react-relay' -import BlockButtonWithDialog from '../BlockButtonWithDialog' -import FollowToggleButton from '../FollowToggleButton' import { ProfileComponentFragment } from '../graphql/queries/ProfileComponent' +import BlockButtonWithDialog from './BlockButtonWithDialog' +import FollowToggleButton from './FollowToggleButton' import { ProfileContainer, ProfileContentContainer, From 123baf8d3daec5fb341b1472547fc490ccfdcae2 Mon Sep 17 00:00:00 2001 From: Alexandre Anicio Date: Mon, 30 Dec 2024 15:31:15 -0300 Subject: [PATCH 4/5] fix lint --- .../images/ImageWithFallback/__storybook__/stories.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/design-system/components/images/ImageWithFallback/__storybook__/stories.tsx b/packages/design-system/components/images/ImageWithFallback/__storybook__/stories.tsx index 3e2a4685..11fa4c52 100644 --- a/packages/design-system/components/images/ImageWithFallback/__storybook__/stories.tsx +++ b/packages/design-system/components/images/ImageWithFallback/__storybook__/stories.tsx @@ -5,10 +5,12 @@ import { Meta, StoryFn, StoryObj } from '@storybook/react' import ImageWithFallback from '..' import { ImageWithFallbackProps } from '../types' -export default { +const meta: Meta = { title: '@baseapp-frontend-template / Design System/Displays/ImageWithFallback', component: ImageWithFallback, -} as Meta +} + +export default meta type Story = StoryObj From e2dec1bfef95783934922b0e07bb892d8c82fc73 Mon Sep 17 00:00:00 2001 From: Pedro Tiburcio Date: Mon, 6 Jan 2025 10:26:03 -0500 Subject: [PATCH 5/5] fix: PR fixes --- .../FollowToggleButton/index.tsx | 2 +- .../FollowToggleButton/types.ts | 2 +- .../profiles/ProfileComponent/index.tsx | 71 ++++---- .../profiles/ProfileComponent/types.ts | 1 + pnpm-lock.yaml | 170 ++++++++---------- 5 files changed, 112 insertions(+), 134 deletions(-) diff --git a/packages/components/modules/profiles/ProfileComponent/FollowToggleButton/index.tsx b/packages/components/modules/profiles/ProfileComponent/FollowToggleButton/index.tsx index 4f8e16d8..1775904c 100644 --- a/packages/components/modules/profiles/ProfileComponent/FollowToggleButton/index.tsx +++ b/packages/components/modules/profiles/ProfileComponent/FollowToggleButton/index.tsx @@ -24,7 +24,7 @@ const FollowToggleButton: FC = ({ const environment = useRelayEnvironment() const toggleFollow = () => { - if (isMutationInFlight || !currentProfileId) { + if (isMutationInFlight || !currentProfileId || !targetId) { return } diff --git a/packages/components/modules/profiles/ProfileComponent/FollowToggleButton/types.ts b/packages/components/modules/profiles/ProfileComponent/FollowToggleButton/types.ts index 380250bb..0cd79e4f 100644 --- a/packages/components/modules/profiles/ProfileComponent/FollowToggleButton/types.ts +++ b/packages/components/modules/profiles/ProfileComponent/FollowToggleButton/types.ts @@ -1,5 +1,5 @@ export interface FollowToggleButtonProps { - targetId: string + targetId?: string isFollowedByMe: boolean | null | undefined currentProfileId?: string profileRef?: any diff --git a/packages/components/modules/profiles/ProfileComponent/index.tsx b/packages/components/modules/profiles/ProfileComponent/index.tsx index 9c070960..4f59260e 100644 --- a/packages/components/modules/profiles/ProfileComponent/index.tsx +++ b/packages/components/modules/profiles/ProfileComponent/index.tsx @@ -2,7 +2,6 @@ import { FC, useState } from 'react' -import { useCurrentProfile } from '@baseapp-frontend/authentication' import { AvatarWithPlaceholder, ImageWithFallback, @@ -31,12 +30,11 @@ import { } from './styled' import { ProfileComponentProps } from './types' -const ProfileComponent: FC = ({ profile: profileRef }) => { +const ProfileComponent: FC = ({ profile: profileRef, currentProfileId }) => { const profile = useFragment(ProfileComponentFragment, profileRef) const smDown = useResponsive('down', 'sm') const router = useRouter() const [anchorEl, setAnchorEl] = useState(null) - const { currentProfile } = useCurrentProfile() const open = Boolean(anchorEl) const handleClick = (event: React.MouseEvent) => { @@ -69,42 +67,39 @@ const ProfileComponent: FC = ({ profile: profileRef }) => } const renderProfileUpdatesButtons = () => { - if (profile && currentProfile) { - if (profile.id === currentProfile.id) { - return ( - - ) - } + if (currentProfileId === profile?.id) { return ( -
- {!profile?.isBlockedByMe && ( - - )} - {profile?.isBlockedByMe && ( - - )} -
+ ) } - return
+ return ( +
+ {!profile?.isBlockedByMe && ( + + )} + {profile?.isBlockedByMe && ( + + )} +
+ ) } return ( @@ -180,7 +175,7 @@ const ProfileComponent: FC = ({ profile: profileRef }) => )} @@ -196,7 +191,7 @@ const ProfileComponent: FC = ({ profile: profileRef }) => )} diff --git a/packages/components/modules/profiles/ProfileComponent/types.ts b/packages/components/modules/profiles/ProfileComponent/types.ts index c46343d0..ab5c1257 100644 --- a/packages/components/modules/profiles/ProfileComponent/types.ts +++ b/packages/components/modules/profiles/ProfileComponent/types.ts @@ -2,4 +2,5 @@ import { ProfileComponentFragment$key } from '../../../__generated__/ProfileComp export interface ProfileComponentProps { profile?: ProfileComponentFragment$key | null + currentProfileId?: string } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f2b757e6..c362955f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2159,12 +2159,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/preset-react@7.26.3': - resolution: {integrity: sha512-Nl03d6T9ky516DGK2YMxrTqvnpUW63TnJMOMonj+Zae0JiPC5BC9xPMSL6L8fiSpA5vP88qfygavVQvnLp+6Cw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/preset-typescript@7.26.0': resolution: {integrity: sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==} engines: {node: '>=6.9.0'} @@ -10290,7 +10284,7 @@ snapshots: '@babel/generator@7.17.7': dependencies: - '@babel/types': 7.17.0 + '@babel/types': 7.26.3 jsesc: 2.5.2 source-map: 0.5.7 @@ -11126,18 +11120,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/preset-react@7.26.3(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-validator-option': 7.25.9 - '@babel/plugin-transform-react-display-name': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-react-jsx-development': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-react-pure-annotations': 7.25.9(@babel/core@7.26.0) - transitivePeerDependencies: - - supports-color - '@babel/preset-typescript@7.26.0(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 @@ -11492,7 +11474,7 @@ snapshots: dependencies: '@babel/runtime': 7.26.0 '@emotion/babel-plugin': 11.13.5 - '@emotion/cache': 11.11.0 + '@emotion/cache': 11.14.0 '@emotion/serialize': 1.3.3 '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@18.3.1) '@emotion/utils': 1.4.2 @@ -12089,7 +12071,7 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 22.7.2 + '@types/node': 22.10.2 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 @@ -12102,14 +12084,14 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.7.2 + '@types/node': 22.10.2 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@22.7.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.2)(typescript@5.4.5)) + jest-config: 29.7.0(@types/node@22.10.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.2)(typescript@5.4.5)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -12137,14 +12119,14 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.7.2 + '@types/node': 22.10.2 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@22.7.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.7.2)(typescript@5.4.5)) + jest-config: 29.7.0(@types/node@22.10.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.7.2)(typescript@5.4.5)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -12173,7 +12155,7 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.7.2 + '@types/node': 22.10.2 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -12191,7 +12173,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 22.7.2 + '@types/node': 22.10.2 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -12213,7 +12195,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 22.7.2 + '@types/node': 22.10.2 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -12283,7 +12265,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 22.7.2 + '@types/node': 22.10.2 '@types/yargs': 17.0.33 chalk: 4.1.2 @@ -14287,7 +14269,7 @@ snapshots: '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 22.7.2 + '@types/node': 22.10.2 '@types/html-minifier-terser@5.1.2': {} @@ -14320,7 +14302,7 @@ snapshots: '@types/jsdom@20.0.1': dependencies: - '@types/node': 22.7.2 + '@types/node': 22.10.2 '@types/tough-cookie': 4.0.5 parse5: 7.2.1 @@ -15098,7 +15080,7 @@ snapshots: '@babel/plugin-transform-export-namespace-from': 7.25.9(@babel/core@7.26.0) '@babel/plugin-transform-object-rest-spread': 7.25.9(@babel/core@7.26.0) '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.0) - '@babel/preset-react': 7.26.3(@babel/core@7.26.0) + '@babel/preset-react': 7.25.9(@babel/core@7.26.0) '@babel/preset-typescript': 7.26.0(@babel/core@7.26.0) '@react-native/babel-preset': 0.76.5(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0)) babel-plugin-react-native-web: 0.19.13 @@ -15660,12 +15642,12 @@ snapshots: css-loader@6.11.0(webpack@5.93.0(@swc/core@1.10.4(@swc/helpers@0.5.15))): dependencies: - icss-utils: 5.1.0(postcss@8.4.38) - postcss: 8.4.38 - postcss-modules-extract-imports: 3.1.0(postcss@8.4.38) - postcss-modules-local-by-default: 4.2.0(postcss@8.4.38) - postcss-modules-scope: 3.2.1(postcss@8.4.38) - postcss-modules-values: 4.0.0(postcss@8.4.38) + icss-utils: 5.1.0(postcss@8.4.49) + postcss: 8.4.49 + postcss-modules-extract-imports: 3.1.0(postcss@8.4.49) + postcss-modules-local-by-default: 4.2.0(postcss@8.4.49) + postcss-modules-scope: 3.2.1(postcss@8.4.49) + postcss-modules-values: 4.0.0(postcss@8.4.49) postcss-value-parser: 4.2.0 semver: 7.6.3 optionalDependencies: @@ -15673,12 +15655,12 @@ snapshots: css-loader@6.11.0(webpack@5.93.0): dependencies: - icss-utils: 5.1.0(postcss@8.4.38) - postcss: 8.4.38 - postcss-modules-extract-imports: 3.1.0(postcss@8.4.38) - postcss-modules-local-by-default: 4.2.0(postcss@8.4.38) - postcss-modules-scope: 3.2.1(postcss@8.4.38) - postcss-modules-values: 4.0.0(postcss@8.4.38) + icss-utils: 5.1.0(postcss@8.4.49) + postcss: 8.4.49 + postcss-modules-extract-imports: 3.1.0(postcss@8.4.49) + postcss-modules-local-by-default: 4.2.0(postcss@8.4.49) + postcss-modules-scope: 3.2.1(postcss@8.4.49) + postcss-modules-values: 4.0.0(postcss@8.4.49) postcss-value-parser: 4.2.0 semver: 7.6.3 optionalDependencies: @@ -15686,12 +15668,12 @@ snapshots: css-loader@7.1.2(webpack@5.93.0(@swc/core@1.10.4(@swc/helpers@0.5.15))): dependencies: - icss-utils: 5.1.0(postcss@8.4.38) - postcss: 8.4.38 - postcss-modules-extract-imports: 3.1.0(postcss@8.4.38) - postcss-modules-local-by-default: 4.2.0(postcss@8.4.38) - postcss-modules-scope: 3.2.1(postcss@8.4.38) - postcss-modules-values: 4.0.0(postcss@8.4.38) + icss-utils: 5.1.0(postcss@8.4.49) + postcss: 8.4.49 + postcss-modules-extract-imports: 3.1.0(postcss@8.4.49) + postcss-modules-local-by-default: 4.2.0(postcss@8.4.49) + postcss-modules-scope: 3.2.1(postcss@8.4.49) + postcss-modules-values: 4.0.0(postcss@8.4.49) postcss-value-parser: 4.2.0 semver: 7.6.3 optionalDependencies: @@ -15699,12 +15681,12 @@ snapshots: css-loader@7.1.2(webpack@5.93.0): dependencies: - icss-utils: 5.1.0(postcss@8.4.38) - postcss: 8.4.38 - postcss-modules-extract-imports: 3.1.0(postcss@8.4.38) - postcss-modules-local-by-default: 4.2.0(postcss@8.4.38) - postcss-modules-scope: 3.2.1(postcss@8.4.38) - postcss-modules-values: 4.0.0(postcss@8.4.38) + icss-utils: 5.1.0(postcss@8.4.49) + postcss: 8.4.49 + postcss-modules-extract-imports: 3.1.0(postcss@8.4.49) + postcss-modules-local-by-default: 4.2.0(postcss@8.4.49) + postcss-modules-scope: 3.2.1(postcss@8.4.49) + postcss-modules-values: 4.0.0(postcss@8.4.49) postcss-value-parser: 4.2.0 semver: 7.6.3 optionalDependencies: @@ -17386,9 +17368,9 @@ snapshots: dependencies: safer-buffer: 2.1.2 - icss-utils@5.1.0(postcss@8.4.38): + icss-utils@5.1.0(postcss@8.4.49): dependencies: - postcss: 8.4.38 + postcss: 8.4.49 ieee754@1.2.1: {} @@ -17722,7 +17704,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.7.2 + '@types/node': 22.10.2 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.3(babel-plugin-macros@3.1.0) @@ -17811,7 +17793,7 @@ snapshots: - babel-plugin-macros - supports-color - jest-config@29.7.0(@types/node@22.7.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.2)(typescript@5.4.5)): + jest-config@29.7.0(@types/node@22.10.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.7.2)(typescript@5.4.5)): dependencies: '@babel/core': 7.26.0 '@jest/test-sequencer': 29.7.0 @@ -17836,8 +17818,8 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 22.7.2 - ts-node: 10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.2)(typescript@5.4.5) + '@types/node': 22.10.2 + ts-node: 10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.7.2)(typescript@5.4.5) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -17898,7 +17880,7 @@ snapshots: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 '@types/jsdom': 20.0.1 - '@types/node': 22.7.2 + '@types/node': 22.10.2 jest-mock: 29.7.0 jest-util: 29.7.0 jsdom: 20.0.3 @@ -17912,7 +17894,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.7.2 + '@types/node': 22.10.2 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -17922,7 +17904,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 22.7.2 + '@types/node': 22.10.2 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -17961,7 +17943,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 22.7.2 + '@types/node': 22.10.2 jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -17996,7 +17978,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.7.2 + '@types/node': 22.10.2 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -18024,7 +18006,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.7.2 + '@types/node': 22.10.2 chalk: 4.1.2 cjs-module-lexer: 1.4.1 collect-v8-coverage: 1.0.2 @@ -18070,7 +18052,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 22.7.2 + '@types/node': 22.10.2 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -18089,7 +18071,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.7.2 + '@types/node': 22.10.2 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -18104,7 +18086,7 @@ snapshots: jest-worker@29.7.0: dependencies: - '@types/node': 22.7.2 + '@types/node': 22.10.2 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -19391,24 +19373,24 @@ snapshots: possible-typed-array-names@1.0.0: {} - postcss-import@15.1.0(postcss@8.4.38): + postcss-import@15.1.0(postcss@8.4.49): dependencies: - postcss: 8.4.38 + postcss: 8.4.49 postcss-value-parser: 4.2.0 read-cache: 1.0.0 resolve: 1.22.10 - postcss-js@4.0.1(postcss@8.4.38): + postcss-js@4.0.1(postcss@8.4.49): dependencies: camelcase-css: 2.0.1 - postcss: 8.4.38 + postcss: 8.4.49 - postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.2)(typescript@5.4.5)): + postcss-load-config@4.0.2(postcss@8.4.49)(ts-node@10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.2)(typescript@5.4.5)): dependencies: lilconfig: 3.1.3 yaml: 2.6.1 optionalDependencies: - postcss: 8.4.38 + postcss: 8.4.49 ts-node: 10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.2)(typescript@5.4.5) postcss-loader@8.1.1(postcss@8.4.38)(typescript@5.4.5)(webpack@5.93.0(@swc/core@1.10.4(@swc/helpers@0.5.15))): @@ -19433,30 +19415,30 @@ snapshots: transitivePeerDependencies: - typescript - postcss-modules-extract-imports@3.1.0(postcss@8.4.38): + postcss-modules-extract-imports@3.1.0(postcss@8.4.49): dependencies: - postcss: 8.4.38 + postcss: 8.4.49 - postcss-modules-local-by-default@4.2.0(postcss@8.4.38): + postcss-modules-local-by-default@4.2.0(postcss@8.4.49): dependencies: - icss-utils: 5.1.0(postcss@8.4.38) - postcss: 8.4.38 + icss-utils: 5.1.0(postcss@8.4.49) + postcss: 8.4.49 postcss-selector-parser: 7.0.0 postcss-value-parser: 4.2.0 - postcss-modules-scope@3.2.1(postcss@8.4.38): + postcss-modules-scope@3.2.1(postcss@8.4.49): dependencies: - postcss: 8.4.38 + postcss: 8.4.49 postcss-selector-parser: 7.0.0 - postcss-modules-values@4.0.0(postcss@8.4.38): + postcss-modules-values@4.0.0(postcss@8.4.49): dependencies: - icss-utils: 5.1.0(postcss@8.4.38) - postcss: 8.4.38 + icss-utils: 5.1.0(postcss@8.4.49) + postcss: 8.4.49 - postcss-nested@6.2.0(postcss@8.4.38): + postcss-nested@6.2.0(postcss@8.4.49): dependencies: - postcss: 8.4.38 + postcss: 8.4.49 postcss-selector-parser: 6.1.2 postcss-selector-parser@6.0.10: @@ -20605,11 +20587,11 @@ snapshots: normalize-path: 3.0.0 object-hash: 3.0.0 picocolors: 1.1.1 - postcss: 8.4.38 - postcss-import: 15.1.0(postcss@8.4.38) - postcss-js: 4.0.1(postcss@8.4.38) - postcss-load-config: 4.0.2(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.2)(typescript@5.4.5)) - postcss-nested: 6.2.0(postcss@8.4.38) + postcss: 8.4.49 + postcss-import: 15.1.0(postcss@8.4.49) + postcss-js: 4.0.1(postcss@8.4.49) + postcss-load-config: 4.0.2(postcss@8.4.49)(ts-node@10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.2)(typescript@5.4.5)) + postcss-nested: 6.2.0(postcss@8.4.49) postcss-selector-parser: 6.1.2 resolve: 1.22.10 sucrase: 3.35.0