@selfcommunity/react-templates
Version:
React Templates Components to integrate a Community created with SelfCommunity.
258 lines (251 loc) • 12.4 kB
JavaScript
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}`)] })) })) }))] })));
}