Files
Nitro-V3/src/components/user-profile/UserContainerView.tsx
T
simoleo89 72bc4da3c0 feat(profile): add full-box card background tab and rendering
Adds a "Cards" tab to the Profile Background picker (BackgroundsView)
that selects a pattern applied to the entire user info card and the
extended profile container, in addition to the existing avatar-pad
background/stand/overlay layers.

- AvatarInfoUser/Utilities: propagate cardBackgroundId from RoomUserData.
- InfoStandWidgetUserView: stateful cardBackgroundId, applied as
  .profile-card-background.card-background-{id} on the outer Column
  with bg-color suppressed when active.
- UserContainerView: same class on the wrapper of the extended profile.
- BackgroundsView: 4th tab "cards" backed by cards.data config
  (falls back to backgrounds.data); sends 4-id message via the
  extended sendBackgroundMessage signature.
- ui-config.example: cards.data dataset (15 entries).
- BackgroundsView.css: 188 .card-background-{N} rules cloned from
  background-{N} (repeat-tiled) plus 15 CSS-pattern overrides for the
  provisional dataset (gradients, stripes, dots, grid, checker).
2026-05-03 22:09:12 +02:00

119 lines
5.1 KiB
TypeScript

import { GetSessionDataManager, RequestFriendComposer, UserProfileParser } from '@nitrots/nitro-renderer';
import { FC, useEffect, useState } from 'react';
import { FriendlyTime, LocalizeText, SendMessageComposer } from '../../api';
import { LayoutAvatarImageView, Text } from '../../common';
export const UserContainerView: FC<{
userProfile: UserProfileParser;
}> = props =>
{
const { userProfile = null } = props;
const [ requestSent, setRequestSent ] = useState(userProfile.requestSent);
const isOwnProfile = (userProfile.id === GetSessionDataManager().userId);
const canSendFriendRequest = !requestSent && (!isOwnProfile && !userProfile.isMyFriend && !userProfile.requestSent);
const infostandBackgroundClass = `background-${userProfile.backgroundId ?? 'default'}`;
const infostandStandClass = `stand-${userProfile.standId ?? 'default'}`;
const infostandOverlayClass = `overlay-${userProfile.overlayId ?? 'default'}`;
const profileCardBgClass = userProfile.cardBackgroundId ? `card-background-${userProfile.cardBackgroundId}` : '';
const addFriend = () =>
{
setRequestSent(true);
SendMessageComposer(new RequestFriendComposer(userProfile.username));
};
useEffect(() =>
{
setRequestSent(userProfile.requestSent);
}, [ userProfile ]);
return (
<div className={`flex gap-2 p-2 rounded profile-card-background ${profileCardBgClass}`}>
<div className={`flex flex-col justify-center items-center w-[75px] h-[120px] rounded-sm relative overflow-hidden profile-background ${infostandBackgroundClass}`}>
<div className={`absolute inset-0 profile-stand ${infostandStandClass}`} />
<LayoutAvatarImageView direction={ 2 } figure={ userProfile.figure } />
<div className={`absolute inset-0 profile-overlay ${infostandOverlayClass}`} />
</div>
<div className="flex flex-col gap-2">
<div className="flex flex-col gap-0">
<p className="leading-tight font-bold">{ userProfile.username }</p>
<p className="text-sm italic leading-tight">{ userProfile.motto }</p>
</div>
<div className="flex flex-col gap-1">
<p
className="text-sm leading-none"
dangerouslySetInnerHTML={{
__html: LocalizeText(
'extendedprofile.created',
['created'],
[userProfile.registration]
)
}}
/>
<p
className="text-sm leading-none"
dangerouslySetInnerHTML={{
__html: LocalizeText(
'extendedprofile.last.login',
['lastlogin'],
[FriendlyTime.format(userProfile.secondsSinceLastVisit, '.ago', 2)]
)
}}
/>
<p
className="text-sm leading-none"
dangerouslySetInnerHTML={{
__html: LocalizeText(
'extendedprofile.friends.count',
['count'],
[userProfile.friendsCount]
)
}}
/>
<p className="text-sm leading-none">
<b>{ LocalizeText('extendedprofile.achievementscore') }</b> { userProfile.achievementPoints }
</p>
</div>
<div className="flex items-center gap-1">
{ userProfile.isOnline &&
<i className="nitro-icon icon-pf-online" /> }
{ !userProfile.isOnline &&
<i className="nitro-icon icon-pf-offline" /> }
<div className="flex items-center gap-1">
{ canSendFriendRequest &&
<Text pointer small underline onClick={ addFriend }>
{ LocalizeText('extendedprofile.addasafriend') }
</Text> }
{ !canSendFriendRequest &&
<>
<i className="nitro-icon icon-pf-tick" />
{ isOwnProfile &&
<p>{ LocalizeText('extendedprofile.me') }</p> }
{ userProfile.isMyFriend &&
<p>{ LocalizeText('extendedprofile.friend') }</p> }
{ (requestSent || userProfile.requestSent) &&
<p>{ LocalizeText('extendedprofile.friendrequestsent') }</p> }
</> }
</div>
</div>
</div>
</div>
);
};