Group information (not done)
@ -21,7 +21,7 @@
|
||||
"pet.asset.url": "${asset.url}/bundled/pet/%libname%.nitro",
|
||||
"generic.asset.url": "${asset.url}/bundled/generic/%libname%.nitro",
|
||||
"badge.asset.url": "${image.library.url}album1584/%badgename%.gif",
|
||||
"badge.asset.group.url": "${asset.url}/group-badge/%badgedata%",
|
||||
"badge.asset.group.url": "https://cdn.ironhotel.biz/group-badge/%badgedata%.gif",
|
||||
"furni.rotation.bounce.steps": 20,
|
||||
"furni.rotation.bounce.height": 0.0625,
|
||||
"enable.avatar.arrow": false,
|
||||
|
BIN
src/assets/images/groups/group_decorate_icon.png
Normal file
After Width: | Height: | Size: 311 B |
BIN
src/assets/images/groups/group_icon_big_admin.png
Normal file
After Width: | Height: | Size: 429 B |
BIN
src/assets/images/groups/group_icon_big_member.png
Normal file
After Width: | Height: | Size: 447 B |
BIN
src/assets/images/groups/group_icon_big_owner.png
Normal file
After Width: | Height: | Size: 460 B |
BIN
src/assets/images/groups/grouptype_icon_0.png
Normal file
After Width: | Height: | Size: 542 B |
BIN
src/assets/images/groups/grouptype_icon_1.png
Normal file
After Width: | Height: | Size: 349 B |
BIN
src/assets/images/groups/grouptype_icon_2.png
Normal file
After Width: | Height: | Size: 373 B |
BIN
src/assets/images/loading/progress_habbos.gif
Normal file
After Width: | Height: | Size: 12 KiB |
@ -549,6 +549,48 @@
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
&.icon-group-type-0 {
|
||||
background: url('../images/groups/grouptype_icon_0.png');
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
&.icon-group-type-1 {
|
||||
background: url('../images/groups/grouptype_icon_1.png');
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
&.icon-group-type-2 {
|
||||
background: url('../images/groups/grouptype_icon_2.png');
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
&.icon-group-decorate {
|
||||
background: url('../images/groups/group_decorate_icon.png');
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
&.icon-group-member {
|
||||
background: url('../images/groups/group_icon_big_member.png');
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
&.icon-group-admin {
|
||||
background: url('../images/groups/group_icon_big_admin.png');
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
&.icon-group-owner {
|
||||
background: url('../images/groups/group_icon_big_owner.png');
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
&.spin {
|
||||
animation: rotating 1s linear infinite;
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
@import './card/NitroCardView';
|
||||
@import './draggable-window/DraggableWindow';
|
||||
@import './loading-habbos/LoadingHabbosView';
|
||||
@import './loading-spinner/LoadingSpinnerView';
|
||||
@import './mini-camera/NitroLayoutMiniCameraView';
|
||||
@import './notification-bubble/NotificationBubbleView';
|
||||
|
7
src/layout/loading-habbos/LoadingHabbosView.scss
Normal file
@ -0,0 +1,7 @@
|
||||
.loading-habbos {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url(../../assets/images/loading/progress_habbos.gif);
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
8
src/layout/loading-habbos/LoadingHabbosView.tsx
Normal file
@ -0,0 +1,8 @@
|
||||
import { FC } from 'react';
|
||||
|
||||
export const LoadingHabbosView: FC = props =>
|
||||
{
|
||||
return (
|
||||
<div className="loading-habbos"></div>
|
||||
);
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
@import './avatar-editor/AvatarEditorView';
|
||||
@import './catalog/CatalogView';
|
||||
@import './friend-list/FriendListView';
|
||||
@import './groups/GroupView';
|
||||
@import './hotel-view/HotelView';
|
||||
@import './inventory/InventoryView';
|
||||
@import './loading/LoadingView';
|
||||
|
1
src/views/groups/GroupView.scss
Normal file
@ -0,0 +1 @@
|
||||
@import './views/GroupinformationView';
|
6
src/views/groups/GroupsView.tsx
Normal file
@ -0,0 +1,6 @@
|
||||
import { FC } from 'react';
|
||||
|
||||
export const GroupsView: FC<{}> = props =>
|
||||
{
|
||||
return null;
|
||||
};
|
6
src/views/groups/common/GroupMembershipType.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export class GroupMembershipType
|
||||
{
|
||||
public static NOT_MEMBER: number = 0;
|
||||
public static MEMBER: number = 1;
|
||||
public static REQUEST_PENDING: number = 2;
|
||||
}
|
6
src/views/groups/common/GroupType.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export class GroupType
|
||||
{
|
||||
public static REGULAR: number = 0;
|
||||
public static EXCLUSIVE: number = 1;
|
||||
public static PRIVATE: number = 2;
|
||||
}
|
90
src/views/groups/views/GroupInformationView.tsx
Normal file
@ -0,0 +1,90 @@
|
||||
import { GroupInformationComposer, GroupInformationEvent, GroupInformationParser } from '@nitrots/nitro-renderer';
|
||||
import { FC, useCallback, useEffect, useState } from 'react';
|
||||
import { LocalizeText } from '../../../api';
|
||||
import { CreateMessageHook, SendMessageHook } from '../../../hooks';
|
||||
import { BadgeImageView } from '../../shared/badge-image/BadgeImageView';
|
||||
import { GroupMembershipType } from '../common/GroupMembershipType';
|
||||
import { GroupType } from '../common/GroupType';
|
||||
import { GroupInformationViewProps } from './GroupInformationView.types';
|
||||
|
||||
export const GroupInformationView: FC<GroupInformationViewProps> = props =>
|
||||
{
|
||||
const { group = null } = props;
|
||||
|
||||
const [ groupInformation, setGroupInformation ] = useState<GroupInformationParser>(null);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
setGroupInformation(null);
|
||||
if(group) SendMessageHook(new GroupInformationComposer(group.id, true));
|
||||
}, [ group ]);
|
||||
|
||||
const onGroupInformationEvent = useCallback((event: GroupInformationEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
setGroupInformation(parser);
|
||||
}, []);
|
||||
|
||||
CreateMessageHook(GroupInformationEvent, onGroupInformationEvent);
|
||||
|
||||
if(!groupInformation) return null;
|
||||
|
||||
return (
|
||||
<div className="group-information p-2">
|
||||
<div>
|
||||
<div className="group-badge text-center">
|
||||
<BadgeImageView badgeCode={ group.badge } isGroup={ true } />
|
||||
<div className="mt-3">
|
||||
<a href="#" className="small text-black">
|
||||
{ LocalizeText('group.membercount', ['totalMembers'], [groupInformation.membersCount.toString()]) }
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
{ groupInformation.pendingRequestsCount > 0 && <a href="#" className="small text-black">
|
||||
{ LocalizeText('group.pendingmembercount', ['totalMembers'], [groupInformation.pendingRequestsCount.toString()]) }
|
||||
</a> }
|
||||
</div>
|
||||
<div className="mt-3">
|
||||
{ groupInformation.membershipType === GroupMembershipType.MEMBER && !groupInformation.isAdmin && <i className="icon icon-group-member" title={ LocalizeText('group.youaremember') } /> }
|
||||
{ groupInformation.isAdmin && !groupInformation.isOwner && <i className="icon icon-group-admin" title={ LocalizeText('group.youareadmin') } /> }
|
||||
{ groupInformation.isOwner && <i className="icon icon-group-owner" title={ LocalizeText('group.youareowner') } /> }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="ms-2 w-100">
|
||||
<div className="fw-bold d-flex align-items-center">
|
||||
<i className={ 'icon icon-group-type-' + groupInformation.type } />
|
||||
{ groupInformation.canMembersDecorate && <i className="icon icon-group-decorate ms-1" /> }
|
||||
<div className="ms-1">{ group.title }</div>
|
||||
</div>
|
||||
<div>{ LocalizeText('group.created', ['date', 'owner'], [groupInformation.createdAt, groupInformation.ownerName]) }</div>
|
||||
<div className="group-description small overflow-auto">{ groupInformation.description }</div>
|
||||
<div>
|
||||
<a href="#" className="small text-black">
|
||||
{ LocalizeText('group.linktobase') }
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<a href="#" className="small text-black">
|
||||
{ LocalizeText('group.buyfurni') }
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<a href="#" className="small text-black">
|
||||
{ LocalizeText('group.showgroups') }
|
||||
</a>
|
||||
</div>
|
||||
{ groupInformation.type !== GroupType.PRIVATE &&
|
||||
<button className="btn btn-primary w-100 mt-2" disabled={ groupInformation.membershipType === GroupMembershipType.REQUEST_PENDING }>
|
||||
{ groupInformation.membershipType === GroupMembershipType.MEMBER && LocalizeText('group.leave') }
|
||||
{ groupInformation.membershipType === GroupMembershipType.NOT_MEMBER && groupInformation.type === GroupType.REGULAR && LocalizeText('group.join') }
|
||||
{ groupInformation.type === GroupType.EXCLUSIVE && <>
|
||||
{ groupInformation.membershipType === GroupMembershipType.NOT_MEMBER && LocalizeText('group.requestmembership') }
|
||||
{ groupInformation.membershipType === GroupMembershipType.REQUEST_PENDING && LocalizeText('group.membershippending') }
|
||||
</> }
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
6
src/views/groups/views/GroupInformationView.types.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { GroupDataParser } from '@nitrots/nitro-renderer';
|
||||
|
||||
export interface GroupInformationViewProps
|
||||
{
|
||||
group: GroupDataParser;
|
||||
}
|
18
src/views/groups/views/GroupinformationView.scss
Normal file
@ -0,0 +1,18 @@
|
||||
.group-information {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
|
||||
.group-badge {
|
||||
width: 78px;
|
||||
height: 78px;
|
||||
|
||||
.badge-image {
|
||||
background-size: contain;
|
||||
}
|
||||
}
|
||||
|
||||
.group-description {
|
||||
height: 55px;
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
.user-profile {
|
||||
width: 560px;
|
||||
|
||||
.content-area {
|
||||
color: black;
|
||||
}
|
||||
@ -44,4 +45,5 @@
|
||||
}
|
||||
}
|
||||
|
||||
@import "./views/relationships-container/RelationshipsContainerView";
|
||||
@import './views/relationships-container/RelationshipsContainerView';
|
||||
@import './views/groups-container/GroupsContainerView';
|
||||
|
@ -5,6 +5,7 @@ import { CreateMessageHook, SendMessageHook } from '../../hooks';
|
||||
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../layout';
|
||||
import { BadgesContainerView } from './views/badges-container/BadgesContainerView';
|
||||
import { FriendsContainerView } from './views/friends-container/FriendsContainerView';
|
||||
import { GroupsContainerView } from './views/groups-container/GroupsContainerView';
|
||||
import { UserContainerView } from './views/user-container/UserContainerView';
|
||||
|
||||
export const UserProfileView: FC = props =>
|
||||
@ -51,6 +52,7 @@ export const UserProfileView: FC = props =>
|
||||
}
|
||||
|
||||
setUserProfile(parser);
|
||||
console.log(parser);
|
||||
SendMessageHook(new UserCurrentBadgesComposer(parser.id));
|
||||
SendMessageHook(new UserRelationshipsComposer(parser.id));
|
||||
}, [userProfile]);
|
||||
@ -79,14 +81,7 @@ export const UserProfileView: FC = props =>
|
||||
<i className="icon icon-rooms" /><span className="rooms-button">{LocalizeText('extendedprofile.rooms')}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-sm-4">
|
||||
groups list goes here
|
||||
</div>
|
||||
<div className="col-sm-8">
|
||||
group info goes here
|
||||
</div>
|
||||
</div>
|
||||
<GroupsContainerView groups={ userProfile.groups } />
|
||||
</NitroCardContentView>
|
||||
</NitroCardView>
|
||||
)
|
||||
|
@ -0,0 +1,17 @@
|
||||
.profile-groups {
|
||||
height: 219px;
|
||||
|
||||
.profile-groups-item {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: $border-radius;
|
||||
border-color: $grid-border-color !important;
|
||||
background-color: $grid-bg-color;
|
||||
border: nth(map-values($border-widths), 2) solid;
|
||||
|
||||
&.active {
|
||||
border-color: $grid-active-border-color !important;
|
||||
background-color: $grid-active-bg-color !important;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
import classNames from 'classnames';
|
||||
import { FC, useEffect, useState } from 'react';
|
||||
import { GroupInformationView } from '../../../groups/views/GroupInformationView';
|
||||
import { BadgeImageView } from '../../../shared/badge-image/BadgeImageView';
|
||||
import { GroupsContainerViewProps } from './GroupsContainerView.types';
|
||||
|
||||
export const GroupsContainerView: FC<GroupsContainerViewProps> = props =>
|
||||
{
|
||||
const { groups = null } = props;
|
||||
|
||||
const [ selectedIndex, setSelectedIndex ] = useState<number>(null);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
if(groups.length > 0 && selectedIndex === null) setSelectedIndex(0);
|
||||
}, [ groups ]);
|
||||
|
||||
if(!groups) return null;
|
||||
|
||||
return (
|
||||
<div className="d-flex">
|
||||
<div className="profile-groups p-2">
|
||||
<div className="h-100 overflow-auto d-flex flex-column gap-1">
|
||||
{ groups.map((group, index) =>
|
||||
{
|
||||
return <div key={ index } onClick={ () => setSelectedIndex(index) } className={ 'profile-groups-item flex-shrink-0 d-flex align-items-center justify-content-center cursor-pointer' + classNames({ ' active': selectedIndex === index }) }>
|
||||
<BadgeImageView badgeCode={ group.badge } isGroup={ true } />
|
||||
</div>
|
||||
}) }
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-100">
|
||||
{ selectedIndex > -1 && <GroupInformationView group={ groups[selectedIndex] } /> }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
import { GroupDataParser } from '@nitrots/nitro-renderer';
|
||||
|
||||
export interface GroupsContainerViewProps
|
||||
{
|
||||
groups: GroupDataParser[];
|
||||
}
|