diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 2dcb3b14..a29181a0 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -1,5 +1,11 @@ # @baseapp-frontend/components +## 1.0.24 + +### Patch Changes + +- create profile page storybook + ## 1.0.23 ### Patch Changes diff --git a/packages/components/__generated__/ActivityLogsFragment.graphql.ts b/packages/components/__generated__/ActivityLogsFragment.graphql.ts deleted file mode 100644 index a2f6832d..00000000 --- a/packages/components/__generated__/ActivityLogsFragment.graphql.ts +++ /dev/null @@ -1,288 +0,0 @@ -/** - * @generated SignedSource<> - * @lightSyntaxTransform - * @nogrep - */ - -/* tslint:disable */ - -/* eslint-disable */ -// @ts-nocheck -import { ReaderFragment, RefetchableFragment } from 'relay-runtime' -import { FragmentRefs } from 'relay-runtime' - -export type ActivityLogsFragment$data = { - readonly activityLogs: - | { - readonly edges: ReadonlyArray< - | { - readonly node: - | { - readonly createdAt: any - readonly id: string - readonly url: string | null | undefined - readonly user: - | { - readonly avatar: - | { - readonly url: string - } - | null - | undefined - readonly email: string | null | undefined - readonly fullName: string | null | undefined - readonly id: string - } - | null - | undefined - readonly verb: string | null | undefined - } - | null - | undefined - } - | null - | undefined - > - readonly pageInfo: { - readonly endCursor: string | null | undefined - readonly hasNextPage: boolean - } - } - | null - | undefined - readonly ' $fragmentType': 'ActivityLogsFragment' -} -export type ActivityLogsFragment$key = { - readonly ' $data'?: ActivityLogsFragment$data - readonly ' $fragmentSpreads': FragmentRefs<'ActivityLogsFragment'> -} - -const node: ReaderFragment = (function () { - var v0 = ['activityLogs'], - v1 = { - alias: null, - args: null, - kind: 'ScalarField', - name: 'id', - storageKey: null, - }, - v2 = { - alias: null, - args: null, - kind: 'ScalarField', - name: 'url', - storageKey: null, - } - return { - argumentDefinitions: [ - { - defaultValue: 10, - kind: 'LocalArgument', - name: 'count', - }, - { - defaultValue: null, - kind: 'LocalArgument', - name: 'createdFrom', - }, - { - defaultValue: null, - kind: 'LocalArgument', - name: 'createdTo', - }, - { - defaultValue: null, - kind: 'LocalArgument', - name: 'cursor', - }, - { - defaultValue: null, - kind: 'LocalArgument', - name: 'userName', - }, - ], - kind: 'Fragment', - metadata: { - connection: [ - { - count: 'count', - cursor: 'cursor', - direction: 'forward', - path: v0 /*: any*/, - }, - ], - refetch: { - connection: { - forward: { - count: 'count', - cursor: 'cursor', - }, - backward: null, - path: v0 /*: any*/, - }, - fragmentPathInResult: [], - operation: require('./ActivityLogsPaginationQuery.graphql'), - }, - }, - name: 'ActivityLogsFragment', - selections: [ - { - alias: 'activityLogs', - args: [ - { - kind: 'Variable', - name: 'createdFrom', - variableName: 'createdFrom', - }, - { - kind: 'Variable', - name: 'createdTo', - variableName: 'createdTo', - }, - { - kind: 'Variable', - name: 'userName', - variableName: 'userName', - }, - ], - concreteType: 'ActivityLogConnection', - kind: 'LinkedField', - name: '__ActivityLogs_activityLogs_connection', - plural: false, - selections: [ - { - alias: null, - args: null, - concreteType: 'ActivityLogEdge', - kind: 'LinkedField', - name: 'edges', - plural: true, - selections: [ - { - alias: null, - args: null, - concreteType: 'ActivityLog', - kind: 'LinkedField', - name: 'node', - plural: false, - selections: [ - v1 /*: any*/, - { - alias: null, - args: null, - kind: 'ScalarField', - name: 'createdAt', - storageKey: null, - }, - { - alias: null, - args: null, - kind: 'ScalarField', - name: 'verb', - storageKey: null, - }, - v2 /*: any*/, - { - alias: null, - args: null, - concreteType: 'User', - kind: 'LinkedField', - name: 'user', - plural: false, - selections: [ - v1 /*: any*/, - { - alias: null, - args: null, - kind: 'ScalarField', - name: 'fullName', - storageKey: null, - }, - { - alias: null, - args: null, - kind: 'ScalarField', - name: 'email', - storageKey: null, - }, - { - alias: null, - args: [ - { - kind: 'Literal', - name: 'height', - value: 48, - }, - { - kind: 'Literal', - name: 'width', - value: 48, - }, - ], - concreteType: 'File', - kind: 'LinkedField', - name: 'avatar', - plural: false, - selections: [v2 /*: any*/], - storageKey: 'avatar(height:48,width:48)', - }, - ], - storageKey: null, - }, - { - alias: null, - args: null, - kind: 'ScalarField', - name: '__typename', - storageKey: null, - }, - ], - storageKey: null, - }, - { - alias: null, - args: null, - kind: 'ScalarField', - name: 'cursor', - storageKey: null, - }, - ], - storageKey: null, - }, - { - alias: null, - args: null, - concreteType: 'PageInfo', - kind: 'LinkedField', - name: 'pageInfo', - plural: false, - selections: [ - { - alias: null, - args: null, - kind: 'ScalarField', - name: 'endCursor', - storageKey: null, - }, - { - alias: null, - args: null, - kind: 'ScalarField', - name: 'hasNextPage', - storageKey: null, - }, - ], - storageKey: null, - }, - ], - storageKey: null, - }, - ], - type: 'Query', - abstractKey: null, - } -})() - -;(node as any).hash = 'f5d29f31cbedd5432a4805c649a74929' - -export default node diff --git a/packages/components/__generated__/RemoveMemberMutation.graphql.ts b/packages/components/__generated__/RemoveMemberMutation.graphql.ts deleted file mode 100644 index 3eaa670d..00000000 --- a/packages/components/__generated__/RemoveMemberMutation.graphql.ts +++ /dev/null @@ -1,119 +0,0 @@ -/** - * @generated SignedSource<<75b6ee0b9ad6bcd307634d310129e71b>> - * @lightSyntaxTransform - * @nogrep - */ - -/* tslint:disable */ - -/* eslint-disable */ -// @ts-nocheck -import { ConcreteRequest, Mutation } from 'relay-runtime' - -export type ProfileRemoveMemberInput = { - clientMutationId?: string | null | undefined - profileId: string - userId: string -} -export type RemoveMemberMutation$variables = { - input: ProfileRemoveMemberInput -} -export type RemoveMemberMutation$data = { - readonly profileRemoveMember: - | { - readonly deletedId: string | null | undefined - } - | null - | undefined -} -export type RemoveMemberMutation = { - response: RemoveMemberMutation$data - variables: RemoveMemberMutation$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: 'deletedId', - storageKey: null, - } - return { - fragment: { - argumentDefinitions: v0 /*: any*/, - kind: 'Fragment', - metadata: null, - name: 'RemoveMemberMutation', - selections: [ - { - alias: null, - args: v1 /*: any*/, - concreteType: 'ProfileRemoveMemberPayload', - kind: 'LinkedField', - name: 'profileRemoveMember', - plural: false, - selections: [v2 /*: any*/], - storageKey: null, - }, - ], - type: 'Mutation', - abstractKey: null, - }, - kind: 'Request', - operation: { - argumentDefinitions: v0 /*: any*/, - kind: 'Operation', - name: 'RemoveMemberMutation', - selections: [ - { - alias: null, - args: v1 /*: any*/, - concreteType: 'ProfileRemoveMemberPayload', - kind: 'LinkedField', - name: 'profileRemoveMember', - plural: false, - selections: [ - v2 /*: any*/, - { - alias: null, - args: null, - filters: null, - handle: 'deleteRecord', - key: '', - kind: 'ScalarHandle', - name: 'deletedId', - }, - ], - storageKey: null, - }, - ], - }, - params: { - cacheID: '7ede42a17cf2d60398c7a5019de5f013', - id: null, - metadata: {}, - name: 'RemoveMemberMutation', - operationKind: 'mutation', - text: 'mutation RemoveMemberMutation(\n $input: ProfileRemoveMemberInput!\n) {\n profileRemoveMember(input: $input) {\n deletedId\n }\n}\n', - }, - } -})() - -;(node as any).hash = '4426831487fa708c1e351d2c7608e1f8' - -export default node diff --git a/packages/components/modules/messages/web/CreateGroup/types.ts b/packages/components/modules/messages/web/CreateGroup/types.ts index 012facec..f2393035 100644 --- a/packages/components/modules/messages/web/CreateGroup/types.ts +++ b/packages/components/modules/messages/web/CreateGroup/types.ts @@ -1,7 +1,7 @@ import { FC, PropsWithChildren } from 'react' -import { GroupChatMembersListProps } from '../__shared__/GroupChatMembersList/types' import { ChatRoomsQuery$data } from '../../../../__generated__/ChatRoomsQuery.graphql' +import { GroupChatMembersListProps } from '../__shared__/GroupChatMembersList/types' export interface CreateGroupProps extends PropsWithChildren { allProfilesRef: ChatRoomsQuery$data diff --git a/packages/components/modules/messages/web/EditGroup/types.ts b/packages/components/modules/messages/web/EditGroup/types.ts index 53de99e9..0647a328 100644 --- a/packages/components/modules/messages/web/EditGroup/types.ts +++ b/packages/components/modules/messages/web/EditGroup/types.ts @@ -2,9 +2,9 @@ import { FC, PropsWithChildren } from 'react' import { PreloadedQuery } from 'react-relay' -import { GroupChatMembersListProps } from '../__shared__/GroupChatMembersList/types' import { ChatRoomsQuery$data } from '../../../../__generated__/ChatRoomsQuery.graphql' import { GroupDetailsQuery } from '../../../../__generated__/GroupDetailsQuery.graphql' +import { GroupChatMembersListProps } from '../__shared__/GroupChatMembersList/types' export interface EditGroupProps extends PropsWithChildren { allProfilesRef: ChatRoomsQuery$data diff --git a/packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/types.ts b/packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/types.ts index cb1446b9..361a4b03 100644 --- a/packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/types.ts +++ b/packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/types.ts @@ -1,7 +1,7 @@ import { FC } from 'react' -import { MessageItemProps } from './MessageItem/types' import { MessageNode } from '../../../../common' +import { MessageItemProps } from './MessageItem/types' export interface UserMessageProps { allMessages: MessageNode[] diff --git a/packages/components/modules/messages/web/MessagesList/MessagesGroup/types.ts b/packages/components/modules/messages/web/MessagesList/MessagesGroup/types.ts index 4dac05f7..6a4b46bd 100644 --- a/packages/components/modules/messages/web/MessagesList/MessagesGroup/types.ts +++ b/packages/components/modules/messages/web/MessagesList/MessagesGroup/types.ts @@ -1,8 +1,8 @@ import { FC } from 'react' +import { MessageNode } from '../../../common' import { SystemMessageProps } from './SystemMessage/types' import { UserMessageProps } from './UserMessage/types' -import { MessageNode } from '../../../common' export interface MessagesGroupProps { allMessages: MessageNode[] diff --git a/packages/components/modules/messages/web/__shared__/GroupChatMembersList/ProfilesList/types.ts b/packages/components/modules/messages/web/__shared__/GroupChatMembersList/ProfilesList/types.ts index ba2c4769..a8974cd1 100644 --- a/packages/components/modules/messages/web/__shared__/GroupChatMembersList/ProfilesList/types.ts +++ b/packages/components/modules/messages/web/__shared__/GroupChatMembersList/ProfilesList/types.ts @@ -1,8 +1,9 @@ import { FC } from 'react' +import { BoxProps } from '@mui/material' import { LoadMoreFn } from 'react-relay' import { VirtuosoProps } from 'react-virtuoso' -import { BoxProps } from '@mui/material' + import { ProfileNode } from '../../types' export interface ProfilesListProps { diff --git a/packages/components/modules/messages/web/__shared__/GroupChatMembersList/types.ts b/packages/components/modules/messages/web/__shared__/GroupChatMembersList/types.ts index 9b6504cc..80b34bae 100644 --- a/packages/components/modules/messages/web/__shared__/GroupChatMembersList/types.ts +++ b/packages/components/modules/messages/web/__shared__/GroupChatMembersList/types.ts @@ -1,7 +1,6 @@ import { FC, PropsWithChildren } from 'react' import { SearchbarProps } from '@baseapp-frontend/design-system/components/web/inputs' - import { WithControllerProps } from '@baseapp-frontend/utils' import { BoxProps } from '@mui/material' diff --git a/packages/components/modules/messages/web/__shared__/types.ts b/packages/components/modules/messages/web/__shared__/types.ts index 0f2e8764..69290ff1 100644 --- a/packages/components/modules/messages/web/__shared__/types.ts +++ b/packages/components/modules/messages/web/__shared__/types.ts @@ -1,6 +1,5 @@ -import { AllProfilesListFragment$data } from "../../../../__generated__/AllProfilesListFragment.graphql" -import { MessagesListFragment$data } from "../../../../__generated__/MessagesListFragment.graphql" - +import { AllProfilesListFragment$data } from '../../../../__generated__/AllProfilesListFragment.graphql' +import { MessagesListFragment$data } from '../../../../__generated__/MessagesListFragment.graphql' export interface TitleAndImage { title: string diff --git a/packages/components/modules/navigations/web/__shared__/NavSectionHorizontal/NavList/NavItem/index.tsx b/packages/components/modules/navigations/web/__shared__/NavSectionHorizontal/NavList/NavItem/index.tsx index 6cfb4be0..ab9ec420 100644 --- a/packages/components/modules/navigations/web/__shared__/NavSectionHorizontal/NavList/NavItem/index.tsx +++ b/packages/components/modules/navigations/web/__shared__/NavSectionHorizontal/NavList/NavItem/index.tsx @@ -84,12 +84,7 @@ const NavItem = forwardRef( ) return ( - + {content} ) diff --git a/packages/components/modules/navigations/web/__shared__/NavSectionHorizontal/NavList/NavItem/styled.tsx b/packages/components/modules/navigations/web/__shared__/NavSectionHorizontal/NavList/NavItem/styled.tsx index 52a7d3f8..33f01373 100644 --- a/packages/components/modules/navigations/web/__shared__/NavSectionHorizontal/NavList/NavItem/styled.tsx +++ b/packages/components/modules/navigations/web/__shared__/NavSectionHorizontal/NavList/NavItem/styled.tsx @@ -135,4 +135,3 @@ export const StyledLink = styled(Link)( variants: [], }), ) - diff --git a/packages/components/modules/profiles/web/ProfileComponent/BlockButtonWithDialog/__storybook__/BlockButtonWithDialog.mdx b/packages/components/modules/profiles/web/ProfileComponent/BlockButtonWithDialog/__storybook__/BlockButtonWithDialog.mdx new file mode 100644 index 00000000..c44e31e5 --- /dev/null +++ b/packages/components/modules/profiles/web/ProfileComponent/BlockButtonWithDialog/__storybook__/BlockButtonWithDialog.mdx @@ -0,0 +1,70 @@ +import { Meta } from '@storybook/addon-docs' + + + +# Component Documentation + +## BlockButtonWithDialog + +- **Purpose**: + The `BlockButtonWithDialog` component allows users to block or unblock a profile. It provides a confirmation dialog to ensure the user understands the action before proceeding. + +- **Expected Behavior**: + - When clicked, the button opens a confirmation dialog to block or unblock a profile. + - The state of the button dynamically changes based on whether the profile is already blocked (`isBlockedByMe`). + - Displays a loading indicator when the mutation is in progress. + - Displays a toast notification with feedback after the action is completed or if an error occurs. + +--- + +## Use Cases + +- **Current Usage**: Used within the `ProfileComponent` to manage the block/unblock functionality for a user profile. + +- **Potential Usage**: Can be reused in any other context where blocking/unblocking a user is needed, such as chat applications or user management dashboards. + +--- + +## Props + +- **target** (Relay Fragment Reference): The target profile to be blocked or unblocked. Includes data like `id`, `name`, and `isBlockedByMe`. + +- **currentProfileId** (string): The ID of the currently logged-in user's profile. Used to identify the actor of the block/unblock action. + +- **isMenu** (boolean): Determines whether the button is rendered as part of a menu. Defaults to `false`. + +- **handleError** (function): Callback function to handle errors that occur during the block/unblock action. + +- **handleCloseMenu** (function): Callback function to close the menu if the button is used inside a dropdown or context menu. + +--- + +## Notes + +- **Related Components**: `ProfileComponent`: Integrates the `BlockButtonWithDialog` to manage block/unblock actions. + +--- + +## Example Usage + +```javascript +import BlockButtonWithDialog from '@baseapp-frontend/components/Profiles/BlockButtonWithDialog' + +const ExampleBlockButton = () => { + const targetProfile = { + id: 'profile-2', + name: 'Jane Doe', + isBlockedByMe: false, + } + + return ( + console.error('An error occurred while blocking/unblocking the profile.')} + /> + ) +} + +export default ExampleBlockButton +``` diff --git a/packages/components/modules/profiles/web/ProfileComponent/BlockButtonWithDialog/__storybook__/BlockButtonWithDialogWithQuery/index.tsx b/packages/components/modules/profiles/web/ProfileComponent/BlockButtonWithDialog/__storybook__/BlockButtonWithDialogWithQuery/index.tsx new file mode 100644 index 00000000..19c8d9cf --- /dev/null +++ b/packages/components/modules/profiles/web/ProfileComponent/BlockButtonWithDialog/__storybook__/BlockButtonWithDialogWithQuery/index.tsx @@ -0,0 +1,28 @@ +import { graphql, useLazyLoadQuery } from 'react-relay' + +import BlockButtonWithDialog from '../..' +import { BlockButtonWithDialogWithQuery as Query } from '../../../../../../../__generated__/BlockButtonWithDialogWithQuery.graphql' +import { BlockToggleFragment$key } from '../../../../../../__generated__/BlockToggleFragment.graphql' + +const BlockButtonWithDialogWithQuery = () => { + const data = useLazyLoadQuery( + graphql` + query BlockButtonWithDialogWithQuery @relay_test_operation { + target: node(id: "test-id") { + ...BlockToggleFragment + } + } + `, + {}, + ) + + return ( + + ) +} + +export default BlockButtonWithDialogWithQuery diff --git a/packages/components/modules/profiles/web/ProfileComponent/BlockButtonWithDialog/__storybook__/mockResolvers.ts b/packages/components/modules/profiles/web/ProfileComponent/BlockButtonWithDialog/__storybook__/mockResolvers.ts new file mode 100644 index 00000000..7bcc2c98 --- /dev/null +++ b/packages/components/modules/profiles/web/ProfileComponent/BlockButtonWithDialog/__storybook__/mockResolvers.ts @@ -0,0 +1,8 @@ +export const mockResolvers = { + Node: () => ({ + __typename: 'Profile', + id: 'profile-1', + name: 'John Doe', + isBlockedByMe: false, + }), +} diff --git a/packages/components/modules/profiles/web/ProfileComponent/BlockButtonWithDialog/__storybook__/stories.tsx b/packages/components/modules/profiles/web/ProfileComponent/BlockButtonWithDialog/__storybook__/stories.tsx new file mode 100644 index 00000000..ac13be2f --- /dev/null +++ b/packages/components/modules/profiles/web/ProfileComponent/BlockButtonWithDialog/__storybook__/stories.tsx @@ -0,0 +1,33 @@ +import { Meta, StoryObj } from '@storybook/react' + +import BlockButtonWithDialog from '..' +import BlockButtonWithDialogWithQuery from './BlockButtonWithDialogWithQuery' +import { mockResolvers } from './mockResolvers' + +const meta: Meta = { + title: '@baseapp-frontend | components/Profiles/ProfileComponent/BlockButtonWithDialog', + component: BlockButtonWithDialogWithQuery, +} + +export default meta + +type Story = StoryObj + +export const NotBlocked: Story = { + name: 'Not Blocked', + parameters: { + mockResolvers, + }, +} + +export const Blocked: Story = { + name: 'Blocked', + parameters: { + mockResolvers: { + Node: () => ({ + ...mockResolvers.Node(), + isBlockedByMe: true, + }), + }, + }, +} diff --git a/packages/components/modules/profiles/web/ProfileComponent/__storybook__/ProfileComponent.mdx b/packages/components/modules/profiles/web/ProfileComponent/__storybook__/ProfileComponent.mdx new file mode 100644 index 00000000..66917ff0 --- /dev/null +++ b/packages/components/modules/profiles/web/ProfileComponent/__storybook__/ProfileComponent.mdx @@ -0,0 +1,69 @@ +import { Meta } from '@storybook/addon-docs' + + + +# Component Documentation + +## ProfileComponent + +- **Purpose**: The `ProfileComponent` displays a detailed view of a user profile, including their profile picture, name, biography, followers count, and additional actions like "Follow," "Block," or "Edit Profile" (when applicable). + +- **Expected Behavior**: + The component should render all profile-related information and actions based on the props provided. It also supports: + - Conditional rendering of the "Edit Profile" button if the `currentProfileId` matches the profile's `id`. + - Feedback when the "Share Profile" button is clicked. + - Handling edge cases, such as missing profile data or API errors. + +--- + +## Use Cases + +- **Current Usage**: The `ProfileComponent` is used in the `ProfilePage` to provide a detailed view of a user's profile. + +--- + +## Props + +- **profile** (Relay Fragment Reference): The profile data to be displayed. This includes the user's name, biography, images, and other information about the profile. + +- **currentProfileId** (string): The ID of the currently logged-in user's profile. Used to determine if the "Edit Profile" button should be displayed. + +--- + +## Notes + +- **Related Components**: + - `BlockButtonWithDialog`: Used within the `ProfileComponent` for blocking or unblocking profiles. + - `FollowToggleButton`: Allows toggling the follow/unfollow state for the profile. + +--- + +## Example Usage + +```javascript +import ProfileComponent from '@baseapp-frontend/components/Profiles/ProfileComponent' + +const ExampleProfile = () => { + const profileData = { + id: 'profile-1', + name: 'John Doe', + biography: 'Software Engineer at Example Inc.', + image: { + url: 'https://developers.elementor.com/docs/assets/img/elementor-placeholder-image.png', + }, + bannerImage: { + url: 'https://developers.elementor.com/docs/assets/img/elementor-placeholder-image.png', + }, + followersCount: 120, + followingCount: 80, + isFollowedByMe: false, + isBlockedByMe: false, + canChange: true, + urlPath: { path: '/john-doe' }, + } + + return +} + +export default ExampleProfile +``` diff --git a/packages/components/modules/profiles/web/ProfileComponent/__storybook__/ProfileComponentWithQuery/index.tsx b/packages/components/modules/profiles/web/ProfileComponent/__storybook__/ProfileComponentWithQuery/index.tsx new file mode 100644 index 00000000..9848004b --- /dev/null +++ b/packages/components/modules/profiles/web/ProfileComponent/__storybook__/ProfileComponentWithQuery/index.tsx @@ -0,0 +1,31 @@ +import { graphql, useLazyLoadQuery } from 'react-relay' + +import ProfileComponent from '../..' +import { ProfileComponentWithQuery as Query } from '../../../../../../__generated__/ProfileComponentWithQuery.graphql' +import { ProfileComponentFragment$key } from '../../../../../__generated__/ProfileComponentFragment.graphql' + +interface ProfileComponentWithQueryProps { + currentProfileId: string +} + +const ProfileComponentWithQuery = ({ currentProfileId }: ProfileComponentWithQueryProps) => { + const data = useLazyLoadQuery( + graphql` + query ProfileComponentWithQuery @relay_test_operation { + profile(id: "test-id") { + ...ProfileComponentFragment + } + } + `, + {}, + ) + + return ( + + ) +} + +export default ProfileComponentWithQuery diff --git a/packages/components/modules/profiles/web/ProfileComponent/__storybook__/mockResolvers.ts b/packages/components/modules/profiles/web/ProfileComponent/__storybook__/mockResolvers.ts new file mode 100644 index 00000000..ace20e84 --- /dev/null +++ b/packages/components/modules/profiles/web/ProfileComponent/__storybook__/mockResolvers.ts @@ -0,0 +1,19 @@ +export const mockResolvers = { + Profile: () => ({ + id: 'profile-1', + name: 'John Doe', + biography: 'Software Engineer at Example Inc.', + image: { + url: 'https://nyc3.digitaloceanspaces.com/baseapp-production-storage/media/user-avatars/c/9/19/resized/50/50/cb95449a94688af33f6e9bb090cf2936.png', + }, + bannerImage: { + url: 'https://developers.elementor.com/docs/assets/img/elementor-placeholder-image.png', + }, + followersCount: 120, + followingCount: 80, + isFollowedByMe: false, + isBlockedByMe: false, + canChange: true, + urlPath: { path: '/john-doe' }, + }), +} diff --git a/packages/components/modules/profiles/web/ProfileComponent/__storybook__/stories.tsx b/packages/components/modules/profiles/web/ProfileComponent/__storybook__/stories.tsx new file mode 100644 index 00000000..7b1eb9b1 --- /dev/null +++ b/packages/components/modules/profiles/web/ProfileComponent/__storybook__/stories.tsx @@ -0,0 +1,79 @@ +import { Meta, StoryObj } from '@storybook/react' + +import ProfileComponentWithQuery from './ProfileComponentWithQuery' +import { mockResolvers } from './mockResolvers' + +const meta: Meta = { + title: '@baseapp-frontend | components/Profiles/ProfileComponent', + component: ProfileComponentWithQuery, + decorators: [ + (Story) => ( +
{ + if (e.key === 'Enter' || e.key === ' ') { + const target = e.target as HTMLElement + if ((e.target as HTMLElement).tagName === 'A' || target.closest('a')) { + e.preventDefault() + } + if (target && target.innerText === 'Share profile') { + alert('Profile URL copied to clipboard!') + } + } + }} + onClick={(e) => { + const target = e.target as HTMLElement + if ((e.target as HTMLElement).tagName === 'A' || target.closest('a')) { + e.preventDefault() + } + if (target && target.innerText === 'Share profile') { + alert('Profile URL copied to clipboard!') + } + }} + style={{ cursor: 'pointer' }} + > + +
+ ), + ], +} + +export default meta + +type Story = StoryObj + +export const UnfollowedProfile: Story = { + name: 'Unfollowed Profile', + args: { + currentProfileId: 'profile-2', + }, + parameters: { + mockResolvers, + }, +} + +export const FollowedProfile: Story = { + name: 'Followed Profile', + args: { + currentProfileId: 'profile-2', + }, + parameters: { + mockResolvers: { + Profile: () => ({ + ...mockResolvers.Profile(), + isFollowedByMe: true, + }), + }, + }, +} + +export const ProfileOwner: Story = { + name: 'Profile Owner', + args: { + currentProfileId: 'profile-1', + }, + parameters: { + mockResolvers, + }, +} diff --git a/packages/components/modules/profiles/web/ProfileComponent/index.tsx b/packages/components/modules/profiles/web/ProfileComponent/index.tsx index 4b6a04ef..c370ab87 100644 --- a/packages/components/modules/profiles/web/ProfileComponent/index.tsx +++ b/packages/components/modules/profiles/web/ProfileComponent/index.tsx @@ -14,7 +14,6 @@ import { useResponsive } from '@baseapp-frontend/design-system/hooks/web' 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' @@ -33,7 +32,6 @@ import { ProfileComponentProps } from './types' 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 open = Boolean(anchorEl) @@ -75,7 +73,7 @@ const ProfileComponent: FC = ({ profile: profileRef, curr color="inherit" startIcon={} sx={{ maxWidth: smDown ? '100%' : 'fit-content' }} - onClick={() => router.push('/user/settings')} + href="/user/settings" > Edit Profile diff --git a/packages/components/package.json b/packages/components/package.json index ff3f2e38..99cd687f 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": "1.0.23", + "version": "1.0.24", "sideEffects": false, "scripts": { "babel:transpile": "babel modules -d tmp-babel --extensions .ts,.tsx --ignore '**/__tests__/**','**/__storybook__/**'", diff --git a/turbo.json b/turbo.json index a54ee2fb..86e179ea 100644 --- a/turbo.json +++ b/turbo.json @@ -38,7 +38,7 @@ "outputs": [] }, "storybook": { - "dependsOn": ["^storybook"] + "dependsOn": ["^build", "^storybook"] } } }