UNPKG

@selfcommunity/react-templates

Version:

React Templates Components to integrate a Community created with SelfCommunity.

258 lines (251 loc) • 12.4 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import { useEffect, useMemo, useState } from 'react'; import { Box, Button, Icon, Stack, Typography, styled } from '@mui/material'; import { ConnectionUserButton, LoyaltyProgramWidget, TagChip, UserActionIconButton, UserConnectionsRequestsSentWidget, UserConnectionsRequestsWidget, UserConnectionsWidget, UserCounters, UserCreatedCoursesWidget, UserFollowedCategoriesWidget, UserFollowedUsersWidget, UserFollowersWidget, UserLiveStreamWidget, UserProfileBlocked, UserProfileHeader, UserSubscribedGroupsWidget } from '@selfcommunity/react-ui'; import UserFeed from '../UserFeed'; import { SCPreferences, SCRoutes, useSCFetchUser, useSCPreferences, useSCRouting, useSCUser, useSCFetchUserBlockedBy } from '@selfcommunity/react-core'; import { SCFeatureName } from '@selfcommunity/types'; import UserProfileSkeleton from './Skeleton'; import classNames from 'classnames'; import { FormattedMessage, useIntl } from 'react-intl'; import { useThemeProps } from '@mui/system'; import UserFeedSkeleton from '../UserFeed/Skeleton'; import { PREFIX } from './constants'; const classes = { root: `${PREFIX}-root`, counters: `${PREFIX}-counters`, tags: `${PREFIX}-tags`, info: `${PREFIX}-info`, feed: `${PREFIX}-feed`, actions: `${PREFIX}-actions` }; const Root = styled(Box, { name: PREFIX, slot: 'Root' })(() => ({})); const WIDGETS_FOLLOWERS = [ { type: 'widget', component: UserLiveStreamWidget, componentProps: {}, column: 'right', position: 0 }, { type: 'widget', component: UserFollowedCategoriesWidget, componentProps: {}, column: 'right', position: 1 }, { type: 'widget', component: UserFollowedUsersWidget, componentProps: {}, column: 'right', position: 2 }, { type: 'widget', component: UserFollowersWidget, componentProps: {}, column: 'right', position: 3 }, { type: 'widget', component: UserSubscribedGroupsWidget, componentProps: {}, column: 'right', position: 4 }, { type: 'widget', component: UserCreatedCoursesWidget, componentProps: {}, column: 'right', position: 5 } ]; const WIDGETS_FOLLOWERS_MY_PROFILE = [ { type: 'widget', component: LoyaltyProgramWidget, componentProps: {}, column: 'right', position: -1 } ]; const WIDGETS_CONNECTIONS = [ { type: 'widget', component: UserLiveStreamWidget, componentProps: {}, column: 'right', position: 0 }, { type: 'widget', component: UserFollowedCategoriesWidget, componentProps: {}, column: 'right', position: 1 }, { type: 'widget', component: UserConnectionsWidget, componentProps: {}, column: 'right', position: 2 }, { type: 'widget', component: UserSubscribedGroupsWidget, componentProps: {}, column: 'right', position: 3 } ]; const WIDGETS_CONNECTIONS_MY_PROFILE = [ { type: 'widget', component: LoyaltyProgramWidget, componentProps: {}, column: 'right', position: -1 }, { type: 'widget', component: UserConnectionsRequestsWidget, componentProps: { autoHide: true }, column: 'right', position: 2 }, { type: 'widget', component: UserConnectionsRequestsSentWidget, componentProps: { autoHide: true }, column: 'right', position: 3 } ]; /** * > API documentation for the Community-JS User Profile Template. Learn about the available props and the CSS API. * * * This component renders a specific user's profile template. * Take a look at our <strong>demo</strong> component [here](/docs/sdk/community-js/react-templates/Components/UserProfile) #### Import ```jsx import {UserProfile} from '@selfcommunity/react-templates'; ``` #### Component Name The name `SCUserProfileTemplate` can be used when providing style overrides in the theme. #### CSS |Rule Name|Global class|Description| |---|---|---| |root|.SCUserProfileTemplate-root|Styles applied to the root element.| |counters|.SCUserProfileTemplate-counters|Styles applied to the counters section.| |tags|.SCUserProfileTemplate-tags|Styles applied to the tags section.| |info|.SCUserProfileTemplate-info|Styles applied to the info section.| |feed|.SCUserProfileTemplate-feed|Styles applied to the feed section.| |actions|.SCUserProfileTemplate-actions|Styles applied to the actions section.| * * @param inProps */ export default function UserProfile(inProps) { // PROPS const props = useThemeProps({ props: inProps, name: PREFIX }); const { id = 'user_profile', className, user, userId, startActions = null, endActions = null, viewStartActions = null, viewEndActions = null, editStartActions = null, editEndActions = null, widgets = null, FeedObjectProps, FeedSidebarProps, UserProfileHeaderProps = {}, onEditClick = null, UserFeedProps = {} } = props; // CONTEXT const scUserContext = useSCUser(); const scPreferencesContext = useSCPreferences(); const scRoutingContext = useSCRouting(); const { features } = useSCPreferences(); // STATE const [isConnection, setIsConnection] = useState(undefined); // HOOKS const { scUser } = useSCFetchUser({ id: userId, user }); const { blockedBy, loading: loadingBlockedBy } = useSCFetchUserBlockedBy({ user: scUser }); const intl = useIntl(); // MEMO const taggingEnabled = useMemo(() => features.includes(SCFeatureName.TAGGING), [features]); const isMe = useMemo(() => scUserContext.user && (scUser === null || scUser === void 0 ? void 0 : scUser.id) === scUserContext.user.id, [scUserContext.user, scUser]); const followEnabled = useMemo(() => SCPreferences.CONFIGURATIONS_FOLLOW_ENABLED in scPreferencesContext.preferences && scPreferencesContext.preferences[SCPreferences.CONFIGURATIONS_FOLLOW_ENABLED].value, [scPreferencesContext.preferences]); const connectionEnabled = SCPreferences.CONFIGURATIONS_CONNECTION_ENABLED in scPreferencesContext.preferences && scPreferencesContext.preferences[SCPreferences.CONFIGURATIONS_CONNECTION_ENABLED].value; const privateMessagingEnabled = useMemo(() => SCPreferences.ADDONS_PRIVATE_MESSAGES_ENABLED in scPreferencesContext.preferences && scPreferencesContext.preferences[SCPreferences.ADDONS_PRIVATE_MESSAGES_ENABLED].value, [scPreferencesContext.preferences]); const _widgets = useMemo(() => { var _a, _b; if (widgets !== null) { return widgets; } if (!scUser || (!followEnabled && !connectionEnabled)) { return []; } let _widgets = []; if (followEnabled && ((_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.id) === scUser.id) { _widgets = [...WIDGETS_FOLLOWERS, ...WIDGETS_FOLLOWERS_MY_PROFILE]; } else if (followEnabled) { _widgets = [...WIDGETS_FOLLOWERS]; } else if (!followEnabled && ((_b = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _b === void 0 ? void 0 : _b.id) === scUser.id) { _widgets = [...WIDGETS_CONNECTIONS, ...WIDGETS_CONNECTIONS_MY_PROFILE]; } else { _widgets = [...WIDGETS_CONNECTIONS]; } return _widgets.map((w) => (Object.assign(Object.assign({}, w), { componentProps: Object.assign(Object.assign({}, w.componentProps), { userId: scUser.id }) }))); }, [widgets, followEnabled, scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user, scUser]); /** * Check if the authenticated user is connected (follow/friend) to the profile user */ useEffect(() => { if (user && Object.is(isConnection !== null && isConnection !== void 0 ? isConnection : null, null)) { if (isMe) { setIsConnection(false); } else if (followEnabled && scUserContext.managers.followers.isFollower) { setIsConnection(scUserContext.managers.followers.isFollower(user)); } else if (!followEnabled && scUserContext.managers.connections.status) { setIsConnection(scUserContext.managers.connections.status(user) === 'connected'); } } }, [isConnection, scUserContext.managers.followers, scUserContext.managers.connections, followEnabled, isMe, user, scUserContext.user]); if (!scUser) { return _jsx(UserProfileSkeleton, {}); } // HANDLERS const handleEdit = () => { onEditClick && onEditClick(scUser); }; // RENDER if (!isMe) { UserFeedProps.FeedProps = Object.assign({ HeaderComponent: null }, UserFeedProps.FeedProps); } let actionItems = []; if (privateMessagingEnabled && !isMe && user && user.can_send_pm_to) { actionItems = [ { label: _jsx(FormattedMessage, { defaultMessage: "templates.userProfile.send.pm", id: "templates.userProfile.send.pm" }), to: scRoutingContext.url(SCRoutes.USER_PRIVATE_MESSAGES_ROUTE_NAME, scUser) } ]; } return (_jsxs(Root, Object.assign({ id: id, className: classNames(classes.root, className) }, { children: [_jsx(UserProfileHeader, Object.assign({ user: scUser }, UserProfileHeaderProps, { actions: !isMe && scUser && Boolean((scUserContext.user && scUserContext.managers.blockedUsers.isBlocked(scUser)) || blockedBy) ? null : (_jsxs(Stack, Object.assign({ direction: "row", spacing: 2, className: classes.actions }, { children: [startActions, isMe ? editStartActions : viewStartActions, isMe ? (_jsx(Button, Object.assign({ variant: "contained", color: "secondary", onClick: handleEdit }, { children: _jsx(FormattedMessage, { defaultMessage: "templates.userProfile.edit", id: "templates.userProfile.edit" }) }))) : (_jsx(ConnectionUserButton, { user: scUser })), isMe ? editEndActions : viewEndActions, endActions, _jsx(UserActionIconButton, { user: scUser, items: actionItems })] }), `actions_${scUser.id}`)) })), scUserContext.user === undefined || (scUserContext.user && ((loadingBlockedBy && blockedBy === null) || scUserContext.managers.blockedUsers.isLoading())) ? (_jsx(UserFeedSkeleton, {})) : (_jsx(_Fragment, { children: loadingBlockedBy || (scUserContext.user && scUserContext.managers.blockedUsers.loading) ? null : (_jsx(_Fragment, { children: !isMe && scUser && Boolean((scUserContext.user && scUserContext.managers.blockedUsers.isBlocked(scUser)) || blockedBy) ? (_jsx(UserProfileBlocked, { user: scUser, blockedByUser: blockedBy })) : (_jsxs(_Fragment, { children: [_jsx(UserCounters, { className: classes.counters, userId: userId, user: scUser }), scUser.date_joined && (_jsx(Typography, Object.assign({ className: classes.info }, { children: _jsx(FormattedMessage, { id: "templates.userProfile.dateJoined", defaultMessage: "templates.userProfile.dateJoined", values: { date: intl.formatDate(scUser.date_joined, { year: 'numeric', month: 'long' }) } }) }))), scUser.location && (_jsxs(Typography, Object.assign({ className: classes.info }, { children: [_jsx(Icon, { children: "add_location_alt" }), " ", scUser.location] }))), taggingEnabled && (_jsx(Stack, Object.assign({ direction: "row", spacing: 2, className: classes.tags }, { children: scUser.tags .filter((t) => t.visible) .map((tag) => (_jsx(TagChip, { tag: tag, clickable: false, disposable: false }, tag.id))) }), `tags_${scUser.id}`)), _jsx(UserFeed, Object.assign({ className: classes.feed, user: scUser, widgets: _widgets, FeedObjectProps: FeedObjectProps, FeedSidebarProps: FeedSidebarProps }, UserFeedProps), `feed_${scUser.id}`)] })) })) }))] }))); }