Communities and channels
This commit is contained in:
parent
79dbeb6b7a
commit
280158470a
34 changed files with 558 additions and 62 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "pulsar-web",
|
"name": "pulsar-web",
|
||||||
"version": "0.1.0",
|
"version": "0.2.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,14 @@
|
||||||
import { callApi, HTTP } from "../tools";
|
import { callApi, HTTP } from "../tools";
|
||||||
import { IFetchCommunityRequest, IFetchCommunityResponse } from "./types";
|
import {
|
||||||
|
IFetchCommunityRequest,
|
||||||
|
IFetchCommunityResponse,
|
||||||
|
IFetchCommunityChannelsRequest,
|
||||||
|
IFetchCommunityChannelsResponse,
|
||||||
|
IFetchCommunityRolesRequest,
|
||||||
|
IFetchCommunityRolesResponse,
|
||||||
|
IFetchCommunityMembersRequest,
|
||||||
|
IFetchCommunityMembersResponse,
|
||||||
|
} from "./types";
|
||||||
|
|
||||||
const fetchCommunityApi = async (
|
const fetchCommunityApi = async (
|
||||||
request: IFetchCommunityRequest,
|
request: IFetchCommunityRequest,
|
||||||
|
|
@ -7,4 +16,27 @@ const fetchCommunityApi = async (
|
||||||
return await callApi(HTTP.GET, `community/${request.id}`);
|
return await callApi(HTTP.GET, `community/${request.id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
export { fetchCommunityApi };
|
const fetchCommunityChannelsApi = async (
|
||||||
|
request: IFetchCommunityChannelsRequest,
|
||||||
|
): Promise<IFetchCommunityChannelsResponse> => {
|
||||||
|
return await callApi(HTTP.GET, `community/${request.id}/channels`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchCommunityRolesApi = async (
|
||||||
|
request: IFetchCommunityRolesRequest,
|
||||||
|
): Promise<IFetchCommunityRolesResponse> => {
|
||||||
|
return await callApi(HTTP.GET, `community/${request.id}/roles`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchCommunityMembersApi = async (
|
||||||
|
request: IFetchCommunityMembersRequest,
|
||||||
|
): Promise<IFetchCommunityMembersResponse> => {
|
||||||
|
return await callApi(HTTP.GET, `community/${request.id}/members`);
|
||||||
|
};
|
||||||
|
|
||||||
|
export {
|
||||||
|
fetchCommunityApi,
|
||||||
|
fetchCommunityChannelsApi,
|
||||||
|
fetchCommunityRolesApi,
|
||||||
|
fetchCommunityMembersApi,
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,59 @@ interface IFetchCommunityRequest {
|
||||||
|
|
||||||
interface IFetchCommunityResponse extends IFetchCommunity {}
|
interface IFetchCommunityResponse extends IFetchCommunity {}
|
||||||
|
|
||||||
|
interface IFetchCommunityChannelsRequest {
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IFetchCommunityChannelsResponse {
|
||||||
|
id: string;
|
||||||
|
channels: IFetchCommunityChannel[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IFetchCommunityChannel {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IFetchCommunityRolesRequest {
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IFetchCommunityRolesResponse {
|
||||||
|
id: string;
|
||||||
|
roles: IFetchCommunityRole[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IFetchCommunityRole {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IFetchCommunityMembersRequest {
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IFetchCommunityMembersResponse {
|
||||||
|
id: string;
|
||||||
|
members: IFetchCommunityMember[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IFetchCommunityMember {
|
||||||
|
id: string;
|
||||||
|
username: string;
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
type IFetchCommunity,
|
type IFetchCommunity,
|
||||||
type IFetchCommunityRequest,
|
type IFetchCommunityRequest,
|
||||||
type IFetchCommunityResponse,
|
type IFetchCommunityResponse,
|
||||||
|
type IFetchCommunityChannelsRequest,
|
||||||
|
type IFetchCommunityChannelsResponse,
|
||||||
|
type IFetchCommunityChannel,
|
||||||
|
type IFetchCommunityRolesRequest,
|
||||||
|
type IFetchCommunityRolesResponse,
|
||||||
|
type IFetchCommunityRole,
|
||||||
|
type IFetchCommunityMembersRequest,
|
||||||
|
type IFetchCommunityMembersResponse,
|
||||||
|
type IFetchCommunityMember,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,16 @@
|
||||||
import type { Component } from "solid-js";
|
import type { Component } from "solid-js";
|
||||||
|
import { IChannelProps } from "./types";
|
||||||
|
|
||||||
const Channel: Component = () => {
|
const Channel: Component<IChannelProps> = (props: IChannelProps) => {
|
||||||
return <div></div>;
|
return (
|
||||||
|
<li
|
||||||
|
class={`flex flex-row gap-2 items-center p-1 cursor-pointer rounded-lg ${props.active ? "bg-stone-700 hover:bg-stone-700" : "hover:bg-stone-800"}`}
|
||||||
|
onClick={() => props.onChannelClick(props.id)}
|
||||||
|
>
|
||||||
|
<div class="font-bold text-xl"> #</div>
|
||||||
|
<div class="font-bold">{props.name}</div>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export { Channel };
|
export { Channel };
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
export * from "./Channel";
|
export * from "./Channel";
|
||||||
|
export * from "./types";
|
||||||
|
|
|
||||||
8
src/components/Channel/types.ts
Normal file
8
src/components/Channel/types.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
interface IChannelProps {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
active: boolean;
|
||||||
|
onChannelClick: (id: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { type IChannelProps };
|
||||||
|
|
@ -1,9 +1,15 @@
|
||||||
import type { Component } from "solid-js";
|
import type { Component } from "solid-js";
|
||||||
|
import { IChannelBarProps } from "./types";
|
||||||
|
|
||||||
const ChannelBar: Component = () => {
|
const ChannelBar: Component<IChannelBarProps> = (props: IChannelBarProps) => {
|
||||||
return (
|
return (
|
||||||
<div class="absolute w-full top-0 z-10">
|
<div class="absolute w-full top-0 z-10">
|
||||||
<div class="bg-stone-800/25 backdrop-blur-md h-16 w-full shadow-bar p-2"></div>
|
<div class="flex flex-col justify-center bg-stone-800/25 backdrop-blur-md h-16 w-full shadow-bar px-5">
|
||||||
|
<h2 class="text-sm font-bold">
|
||||||
|
{props.name ? `# ${props.name}` : undefined}
|
||||||
|
</h2>
|
||||||
|
<p class="text-xs">{props.description}</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
export * from "./ChannelBar";
|
export * from "./ChannelBar";
|
||||||
|
export * from "./types";
|
||||||
|
|
|
||||||
7
src/components/ChannelBar/types.ts
Normal file
7
src/components/ChannelBar/types.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
interface IChannelBarProps {
|
||||||
|
id?: string;
|
||||||
|
name?: string;
|
||||||
|
description?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { type IChannelBarProps };
|
||||||
|
|
@ -7,7 +7,9 @@ const Community: Component<ICommunityProps> = (props: ICommunityProps) => {
|
||||||
class="avatar cursor-pointer"
|
class="avatar cursor-pointer"
|
||||||
onClick={() => props.onCommunityClick(props.id)}
|
onClick={() => props.onCommunityClick(props.id)}
|
||||||
>
|
>
|
||||||
<div class="w-full rounded-full">
|
<div
|
||||||
|
class={`w-full transition-[border-radius] duration-300 outline-stone-300 hover:outline-2 ${props.active ? "rounded-lg outline-2" : "rounded-4xl"}`}
|
||||||
|
>
|
||||||
<img src={props.avatar} />
|
<img src={props.avatar} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ interface ICommunityProps {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
avatar: string;
|
avatar: string;
|
||||||
|
active: boolean;
|
||||||
onCommunityClick: (id: string) => void;
|
onCommunityClick: (id: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
19
src/components/CommunityBar/CommunityBar.tsx
Normal file
19
src/components/CommunityBar/CommunityBar.tsx
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
import type { Component } from "solid-js";
|
||||||
|
import { ICommunityBarProps } from "./types";
|
||||||
|
|
||||||
|
const CommunityBar: Component<ICommunityBarProps> = (
|
||||||
|
props: ICommunityBarProps,
|
||||||
|
) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
class={`absolute w-full top-0 z-10 bg-cover bg-top bg-no-repeat bg-[url('${props.avatar}')]`}
|
||||||
|
>
|
||||||
|
<div class="flex flex-col justify-center bg-stone-800/25 backdrop-blur-md h-16 w-full shadow-bar px-5">
|
||||||
|
<h2 class="text-sm font-bold">{props.name}</h2>
|
||||||
|
<p class="text-xs">{props.description}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export { CommunityBar };
|
||||||
2
src/components/CommunityBar/index.ts
Normal file
2
src/components/CommunityBar/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./CommunityBar";
|
||||||
|
export * from "./types";
|
||||||
8
src/components/CommunityBar/types.ts
Normal file
8
src/components/CommunityBar/types.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
interface ICommunityBarProps {
|
||||||
|
id?: string;
|
||||||
|
name?: string;
|
||||||
|
description?: string;
|
||||||
|
avatar?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { type ICommunityBarProps };
|
||||||
|
|
@ -1,7 +1,20 @@
|
||||||
import type { Component } from "solid-js";
|
import type { Component } from "solid-js";
|
||||||
|
import { IMemberProps } from "./types";
|
||||||
|
|
||||||
const Member: Component = () => {
|
const Member: Component<IMemberProps> = (props: IMemberProps) => {
|
||||||
return <div></div>;
|
return (
|
||||||
|
<li
|
||||||
|
class={`flex flex-row gap-4 items-center p-1 cursor-pointer rounded-lg ${props.active ? "bg-stone-700 hover:bg-stone-700" : "hover:bg-stone-800"}`}
|
||||||
|
onClick={() => props.onMemberClick(props.id)}
|
||||||
|
>
|
||||||
|
<div class="avatar">
|
||||||
|
<div class="w-9 rounded-full">
|
||||||
|
<img src={props.avatar} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="font-bold">{props.username}</div>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export { Member };
|
export { Member };
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
export * from "./Member";
|
export * from "./Member";
|
||||||
|
export * from "./types";
|
||||||
|
|
|
||||||
9
src/components/Member/types.ts
Normal file
9
src/components/Member/types.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
interface IMemberProps {
|
||||||
|
id: string;
|
||||||
|
username: string;
|
||||||
|
avatar: string;
|
||||||
|
active: boolean;
|
||||||
|
onMemberClick: (id: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { type IMemberProps };
|
||||||
|
|
@ -3,7 +3,7 @@ import { IMessageProps } from "./types";
|
||||||
|
|
||||||
const Message: Component<IMessageProps> = (props: IMessageProps) => {
|
const Message: Component<IMessageProps> = (props: IMessageProps) => {
|
||||||
return (
|
return (
|
||||||
<li class="list-row hover:bg-stone-700">
|
<li class="list-row p-3 hover:bg-stone-700">
|
||||||
<div
|
<div
|
||||||
class="avatar cursor-pointer"
|
class="avatar cursor-pointer"
|
||||||
onClick={() => props.onProfileClick(props.userId)}
|
onClick={() => props.onProfileClick(props.userId)}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import type { Component } from "solid-js";
|
import type { Component } from "solid-js";
|
||||||
|
import { state } from "../../store/state";
|
||||||
|
|
||||||
const MessageBar: Component = () => {
|
const MessageBar: Component = () => {
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,13 @@
|
||||||
import { fetchCommunityApi } from "../../api/community";
|
import {
|
||||||
|
fetchCommunityApi,
|
||||||
|
fetchCommunityChannelsApi,
|
||||||
|
fetchCommunityRolesApi,
|
||||||
|
fetchCommunityMembersApi,
|
||||||
|
} from "../../api/community";
|
||||||
import { CommunityActionTypes } from "../../store/community";
|
import { CommunityActionTypes } from "../../store/community";
|
||||||
|
import { ChannelActionTypes } from "../../store/channel";
|
||||||
|
import { RoleActionTypes } from "../../store/role";
|
||||||
|
import { UserActionTypes } from "../../store/user";
|
||||||
import { dispatch } from "../../store/state";
|
import { dispatch } from "../../store/state";
|
||||||
|
|
||||||
const fetchCommunity = async (id: string) => {
|
const fetchCommunity = async (id: string) => {
|
||||||
|
|
@ -13,4 +21,63 @@ const fetchCommunity = async (id: string) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export { fetchCommunity };
|
const fetchCommunityChannels = async (id: string) => {
|
||||||
|
const data = await fetchCommunityChannelsApi({
|
||||||
|
id: id,
|
||||||
|
});
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: CommunityActionTypes.FETCH_COMMUNITY_CHANNELS_FINISH,
|
||||||
|
payload: data,
|
||||||
|
});
|
||||||
|
|
||||||
|
data.channels.forEach((channel) => {
|
||||||
|
dispatch({
|
||||||
|
type: ChannelActionTypes.SET_CHANNEL,
|
||||||
|
payload: channel,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchCommunityRoles = async (id: string) => {
|
||||||
|
const data = await fetchCommunityRolesApi({
|
||||||
|
id: id,
|
||||||
|
});
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: CommunityActionTypes.FETCH_COMMUNITY_ROLES_FINISH,
|
||||||
|
payload: data,
|
||||||
|
});
|
||||||
|
|
||||||
|
data.roles.forEach((role) => {
|
||||||
|
dispatch({
|
||||||
|
type: RoleActionTypes.SET_ROLE,
|
||||||
|
payload: role,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchCommunityMembers = async (id: string) => {
|
||||||
|
const data = await fetchCommunityMembersApi({
|
||||||
|
id: id,
|
||||||
|
});
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: CommunityActionTypes.FETCH_COMMUNITY_MEMBERS_FINISH,
|
||||||
|
payload: data,
|
||||||
|
});
|
||||||
|
|
||||||
|
data.members.forEach((member) => {
|
||||||
|
dispatch({
|
||||||
|
type: UserActionTypes.SET_USER,
|
||||||
|
payload: member,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export {
|
||||||
|
fetchCommunity,
|
||||||
|
fetchCommunityChannels,
|
||||||
|
fetchCommunityRoles,
|
||||||
|
fetchCommunityMembers,
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,13 @@ import {
|
||||||
IUpdateChannelResponse,
|
IUpdateChannelResponse,
|
||||||
IRemoveChannelResponse,
|
IRemoveChannelResponse,
|
||||||
} from "../../api/channel";
|
} from "../../api/channel";
|
||||||
|
import { IFetchCommunityChannel } from "../../api/community";
|
||||||
|
|
||||||
enum ChannelActionTypes {
|
enum ChannelActionTypes {
|
||||||
FETCH_CHANNEL_START = "FETCH_COMMUNITY_START",
|
SET_CHANNEL = "SET_CHANNEL",
|
||||||
FETCH_CHANNEL_FINISH = "FETCH_COMMUNITY_FINISH",
|
SET_ACTIVE_CHANNEL = "SET_ACTIVE_CHANNEL",
|
||||||
|
FETCH_CHANNEL_START = "FETCH_CHANNEL_START",
|
||||||
|
FETCH_CHANNEL_FINISH = "FETCH_CHANNEL_FINISH",
|
||||||
CREATE_CHANNEL_START = "CREATE_CHANNEL_START",
|
CREATE_CHANNEL_START = "CREATE_CHANNEL_START",
|
||||||
CREATE_CHANNEL_FINISH = "CREATE_CHANNEL_FINISH",
|
CREATE_CHANNEL_FINISH = "CREATE_CHANNEL_FINISH",
|
||||||
UPDATE_CHANNEL_START = "UPDATE_CHANNEL_START",
|
UPDATE_CHANNEL_START = "UPDATE_CHANNEL_START",
|
||||||
|
|
@ -18,6 +21,14 @@ enum ChannelActionTypes {
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChannelAction =
|
type ChannelAction =
|
||||||
|
| {
|
||||||
|
type: ChannelActionTypes.SET_CHANNEL;
|
||||||
|
payload: IFetchCommunityChannel;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: ChannelActionTypes.SET_ACTIVE_CHANNEL;
|
||||||
|
payload: string;
|
||||||
|
}
|
||||||
| { type: ChannelActionTypes.FETCH_CHANNEL_START; payload: string }
|
| { type: ChannelActionTypes.FETCH_CHANNEL_START; payload: string }
|
||||||
| {
|
| {
|
||||||
type: ChannelActionTypes.FETCH_CHANNEL_FINISH;
|
type: ChannelActionTypes.FETCH_CHANNEL_FINISH;
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,17 @@ import { IChannelState } from "./types";
|
||||||
|
|
||||||
function channelReducer(state: IChannelState, action: ChannelAction) {
|
function channelReducer(state: IChannelState, action: ChannelAction) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
case ChannelActionTypes.SET_CHANNEL:
|
||||||
|
setState("channel", "channels", action.payload.id, action.payload);
|
||||||
|
break;
|
||||||
|
case ChannelActionTypes.SET_ACTIVE_CHANNEL:
|
||||||
|
setState("channel", "active", action.payload);
|
||||||
|
break;
|
||||||
case ChannelActionTypes.FETCH_CHANNEL_START:
|
case ChannelActionTypes.FETCH_CHANNEL_START:
|
||||||
fetchChannel(action.payload);
|
fetchChannel(action.payload);
|
||||||
break;
|
break;
|
||||||
case ChannelActionTypes.FETCH_CHANNEL_FINISH:
|
case ChannelActionTypes.FETCH_CHANNEL_FINISH:
|
||||||
setState("channel", "channels", {
|
setState("channel", "channels", action.payload.id, action.payload);
|
||||||
...state.channels,
|
|
||||||
[action.payload.id]: action.payload,
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
case ChannelActionTypes.CREATE_CHANNEL_START:
|
case ChannelActionTypes.CREATE_CHANNEL_START:
|
||||||
createChannel(action.payload.name, action.payload.communityId);
|
createChannel(action.payload.name, action.payload.communityId);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
interface IChannelState {
|
interface IChannelState {
|
||||||
|
active: string;
|
||||||
channels: Record<string, IChannel>;
|
channels: Record<string, IChannel>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,61 @@
|
||||||
import { IFetchCommunityResponse } from "../../api/community";
|
import {
|
||||||
|
IFetchCommunityResponse,
|
||||||
|
IFetchCommunityChannelsResponse,
|
||||||
|
IFetchCommunityRolesResponse,
|
||||||
|
IFetchCommunityMembersResponse,
|
||||||
|
} from "../../api/community";
|
||||||
import { IFetchUserCommunity } from "../../api/user";
|
import { IFetchUserCommunity } from "../../api/user";
|
||||||
|
|
||||||
enum CommunityActionTypes {
|
enum CommunityActionTypes {
|
||||||
|
SET_COMMUNITY = "SET_COMMUNITY",
|
||||||
|
SET_ACTIVE_COMMUNITY = "SET_ACTIVE_COMMUNITY",
|
||||||
FETCH_COMMUNITY_START = "FETCH_COMMUNITY_START",
|
FETCH_COMMUNITY_START = "FETCH_COMMUNITY_START",
|
||||||
FETCH_COMMUNITY_FINISH = "FETCH_COMMUNITY_FINISH",
|
FETCH_COMMUNITY_FINISH = "FETCH_COMMUNITY_FINISH",
|
||||||
SET_COMMUNITY = "SET_COMMUNITY",
|
FETCH_COMMUNITY_CHANNELS_START = "FETCH_COMMUNITY_CHANNELS_START",
|
||||||
|
FETCH_COMMUNITY_CHANNELS_FINISH = "FETCH_COMMUNITY_CHANNELS_FINISH",
|
||||||
|
FETCH_COMMUNITY_ROLES_START = "FETCH_COMMUNITY_ROLES_START",
|
||||||
|
FETCH_COMMUNITY_ROLES_FINISH = "FETCH_COMMUNITY_ROLES_FINISH",
|
||||||
|
FETCH_COMMUNITY_MEMBERS_START = "FETCH_COMMUNITY_MEMBERS_START",
|
||||||
|
FETCH_COMMUNITY_MEMBERS_FINISH = "FETCH_COMMUNITY_MEMBERS_FINISH",
|
||||||
}
|
}
|
||||||
|
|
||||||
type CommunityAction =
|
type CommunityAction =
|
||||||
|
| {
|
||||||
|
type: CommunityActionTypes.SET_COMMUNITY;
|
||||||
|
payload: IFetchUserCommunity;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: CommunityActionTypes.SET_ACTIVE_COMMUNITY;
|
||||||
|
payload: string;
|
||||||
|
}
|
||||||
| { type: CommunityActionTypes.FETCH_COMMUNITY_START; payload: string }
|
| { type: CommunityActionTypes.FETCH_COMMUNITY_START; payload: string }
|
||||||
| {
|
| {
|
||||||
type: CommunityActionTypes.FETCH_COMMUNITY_FINISH;
|
type: CommunityActionTypes.FETCH_COMMUNITY_FINISH;
|
||||||
payload: IFetchCommunityResponse;
|
payload: IFetchCommunityResponse;
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: CommunityActionTypes.SET_COMMUNITY;
|
type: CommunityActionTypes.FETCH_COMMUNITY_CHANNELS_START;
|
||||||
payload: IFetchUserCommunity;
|
payload: string;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: CommunityActionTypes.FETCH_COMMUNITY_CHANNELS_FINISH;
|
||||||
|
payload: IFetchCommunityChannelsResponse;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: CommunityActionTypes.FETCH_COMMUNITY_ROLES_START;
|
||||||
|
payload: string;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: CommunityActionTypes.FETCH_COMMUNITY_ROLES_FINISH;
|
||||||
|
payload: IFetchCommunityRolesResponse;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: CommunityActionTypes.FETCH_COMMUNITY_MEMBERS_START;
|
||||||
|
payload: string;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: CommunityActionTypes.FETCH_COMMUNITY_MEMBERS_FINISH;
|
||||||
|
payload: IFetchCommunityMembersResponse;
|
||||||
};
|
};
|
||||||
|
|
||||||
export { CommunityActionTypes, type CommunityAction };
|
export { CommunityActionTypes, type CommunityAction };
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,59 @@
|
||||||
import { fetchCommunity } from "../../services/community";
|
import {
|
||||||
|
fetchCommunity,
|
||||||
|
fetchCommunityChannels,
|
||||||
|
fetchCommunityRoles,
|
||||||
|
fetchCommunityMembers,
|
||||||
|
} from "../../services/community";
|
||||||
import { setState } from "../state";
|
import { setState } from "../state";
|
||||||
import { CommunityActionTypes, CommunityAction } from "./actions";
|
import { CommunityActionTypes, CommunityAction } from "./actions";
|
||||||
import { ICommunityState } from "./types";
|
import { ICommunityState } from "./types";
|
||||||
|
|
||||||
function communityReducer(state: ICommunityState, action: CommunityAction) {
|
function communityReducer(state: ICommunityState, action: CommunityAction) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
case CommunityActionTypes.SET_COMMUNITY:
|
||||||
|
setState(
|
||||||
|
"community",
|
||||||
|
"communities",
|
||||||
|
action.payload.id,
|
||||||
|
action.payload,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case CommunityActionTypes.SET_ACTIVE_COMMUNITY:
|
||||||
|
setState("community", "active", action.payload);
|
||||||
|
break;
|
||||||
case CommunityActionTypes.FETCH_COMMUNITY_START:
|
case CommunityActionTypes.FETCH_COMMUNITY_START:
|
||||||
fetchCommunity(action.payload);
|
fetchCommunity(action.payload);
|
||||||
break;
|
break;
|
||||||
case CommunityActionTypes.FETCH_COMMUNITY_FINISH:
|
case CommunityActionTypes.FETCH_COMMUNITY_FINISH:
|
||||||
setState("community", "communities", {
|
setState(
|
||||||
...state.communities,
|
"community",
|
||||||
[action.payload.id]: action.payload,
|
"communities",
|
||||||
|
action.payload.id,
|
||||||
|
action.payload,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case CommunityActionTypes.FETCH_COMMUNITY_CHANNELS_START:
|
||||||
|
fetchCommunityChannels(action.payload);
|
||||||
|
break;
|
||||||
|
case CommunityActionTypes.FETCH_COMMUNITY_CHANNELS_FINISH:
|
||||||
|
setState("community", "communities", action.payload.id, {
|
||||||
|
channels: action.payload.channels.map((channel) => channel.id),
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case CommunityActionTypes.SET_COMMUNITY:
|
case CommunityActionTypes.FETCH_COMMUNITY_ROLES_START:
|
||||||
setState("community", "communities", {
|
fetchCommunityRoles(action.payload);
|
||||||
...state.communities,
|
break;
|
||||||
[action.payload.id]: action.payload,
|
case CommunityActionTypes.FETCH_COMMUNITY_ROLES_FINISH:
|
||||||
|
setState("community", "communities", action.payload.id, {
|
||||||
|
roles: action.payload.roles.map((role) => role.id),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case CommunityActionTypes.FETCH_COMMUNITY_MEMBERS_START:
|
||||||
|
fetchCommunityMembers(action.payload);
|
||||||
|
break;
|
||||||
|
case CommunityActionTypes.FETCH_COMMUNITY_MEMBERS_FINISH:
|
||||||
|
setState("community", "communities", action.payload.id, {
|
||||||
|
members: action.payload.members.map((member) => member.id),
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
interface ICommunityState {
|
interface ICommunityState {
|
||||||
|
active: string;
|
||||||
communities: Record<string, ICommunity>;
|
communities: Record<string, ICommunity>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -8,6 +9,9 @@ interface ICommunity {
|
||||||
description?: string;
|
description?: string;
|
||||||
owner?: string;
|
owner?: string;
|
||||||
creationDate?: number;
|
creationDate?: number;
|
||||||
|
channels?: string[];
|
||||||
|
roles?: string[];
|
||||||
|
members?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export { type ICommunityState, type ICommunity };
|
export { type ICommunityState, type ICommunity };
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { IFetchCommunityRole } from "../../api/community";
|
||||||
import {
|
import {
|
||||||
ICreateRoleRequest,
|
ICreateRoleRequest,
|
||||||
IFetchRoleResponse,
|
IFetchRoleResponse,
|
||||||
|
|
@ -7,6 +8,7 @@ import {
|
||||||
} from "../../api/role";
|
} from "../../api/role";
|
||||||
|
|
||||||
enum RoleActionTypes {
|
enum RoleActionTypes {
|
||||||
|
SET_ROLE = "SET_ROLE",
|
||||||
FETCH_ROLE_START = "FETCH_ROLE_START",
|
FETCH_ROLE_START = "FETCH_ROLE_START",
|
||||||
FETCH_ROLE_FINISH = "FETCH_ROLE_FINISH",
|
FETCH_ROLE_FINISH = "FETCH_ROLE_FINISH",
|
||||||
CREATE_ROLE_START = "CREATE_ROLE_START",
|
CREATE_ROLE_START = "CREATE_ROLE_START",
|
||||||
|
|
@ -18,6 +20,10 @@ enum RoleActionTypes {
|
||||||
}
|
}
|
||||||
|
|
||||||
type RoleAction =
|
type RoleAction =
|
||||||
|
| {
|
||||||
|
type: RoleActionTypes.SET_ROLE;
|
||||||
|
payload: IFetchCommunityRole;
|
||||||
|
}
|
||||||
| { type: RoleActionTypes.FETCH_ROLE_START; payload: string }
|
| { type: RoleActionTypes.FETCH_ROLE_START; payload: string }
|
||||||
| {
|
| {
|
||||||
type: RoleActionTypes.FETCH_ROLE_FINISH;
|
type: RoleActionTypes.FETCH_ROLE_FINISH;
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,14 @@ import { IRoleState } from "./types";
|
||||||
|
|
||||||
function roleReducer(state: IRoleState, action: RoleAction) {
|
function roleReducer(state: IRoleState, action: RoleAction) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
case RoleActionTypes.SET_ROLE:
|
||||||
|
setState("role", "roles", action.payload.id, action.payload);
|
||||||
|
break;
|
||||||
case RoleActionTypes.FETCH_ROLE_START:
|
case RoleActionTypes.FETCH_ROLE_START:
|
||||||
fetchRole(action.payload);
|
fetchRole(action.payload);
|
||||||
break;
|
break;
|
||||||
case RoleActionTypes.FETCH_ROLE_FINISH:
|
case RoleActionTypes.FETCH_ROLE_FINISH:
|
||||||
setState("role", "roles", {
|
setState("role", "roles", action.payload.id, action.payload);
|
||||||
...state.roles,
|
|
||||||
[action.payload.id]: action.payload,
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
case RoleActionTypes.CREATE_ROLE_START:
|
case RoleActionTypes.CREATE_ROLE_START:
|
||||||
createRole(action.payload.name, action.payload.communityId);
|
createRole(action.payload.name, action.payload.communityId);
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { IFetchCommunityMember } from "../../api/community";
|
||||||
import {
|
import {
|
||||||
IFetchLoggedUserResponse,
|
IFetchLoggedUserResponse,
|
||||||
IFetchUserResponse,
|
IFetchUserResponse,
|
||||||
|
|
@ -5,6 +6,7 @@ import {
|
||||||
} from "../../api/user";
|
} from "../../api/user";
|
||||||
|
|
||||||
enum UserActionTypes {
|
enum UserActionTypes {
|
||||||
|
SET_USER = "SET_USER",
|
||||||
FETCH_LOGGED_USER_ID_START = "FETCH_LOGGED_USER_ID_START",
|
FETCH_LOGGED_USER_ID_START = "FETCH_LOGGED_USER_ID_START",
|
||||||
FETCH_LOGGED_USER_ID_FINISH = "FETCH_LOGGED_USER_ID_FINISH",
|
FETCH_LOGGED_USER_ID_FINISH = "FETCH_LOGGED_USER_ID_FINISH",
|
||||||
FETCH_USER_START = "FETCH_USER_START",
|
FETCH_USER_START = "FETCH_USER_START",
|
||||||
|
|
@ -14,6 +16,10 @@ enum UserActionTypes {
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserAction =
|
type UserAction =
|
||||||
|
| {
|
||||||
|
type: UserActionTypes.SET_USER;
|
||||||
|
payload: IFetchCommunityMember;
|
||||||
|
}
|
||||||
| { type: UserActionTypes.FETCH_LOGGED_USER_ID_START }
|
| { type: UserActionTypes.FETCH_LOGGED_USER_ID_START }
|
||||||
| {
|
| {
|
||||||
type: UserActionTypes.FETCH_LOGGED_USER_ID_FINISH;
|
type: UserActionTypes.FETCH_LOGGED_USER_ID_FINISH;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,9 @@ import { IUserState } from "./types";
|
||||||
|
|
||||||
function userReducer(state: IUserState, action: UserAction) {
|
function userReducer(state: IUserState, action: UserAction) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
case UserActionTypes.SET_USER:
|
||||||
|
setState("user", "users", action.payload.id, action.payload);
|
||||||
|
break;
|
||||||
case UserActionTypes.FETCH_LOGGED_USER_ID_START:
|
case UserActionTypes.FETCH_LOGGED_USER_ID_START:
|
||||||
fetchLoggedUser();
|
fetchLoggedUser();
|
||||||
break;
|
break;
|
||||||
|
|
@ -19,23 +22,16 @@ function userReducer(state: IUserState, action: UserAction) {
|
||||||
fetchUser(action.payload);
|
fetchUser(action.payload);
|
||||||
break;
|
break;
|
||||||
case UserActionTypes.FETCH_USER_FINISH:
|
case UserActionTypes.FETCH_USER_FINISH:
|
||||||
setState("user", "users", {
|
setState("user", "users", action.payload.id, action.payload);
|
||||||
...state.users,
|
|
||||||
[action.payload.id]: action.payload,
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
case UserActionTypes.FETCH_USER_COMMUNITIES_START:
|
case UserActionTypes.FETCH_USER_COMMUNITIES_START:
|
||||||
fetchUserCommunities(action.payload);
|
fetchUserCommunities(action.payload);
|
||||||
break;
|
break;
|
||||||
case UserActionTypes.FETCH_USER_COMMUNITIES_FINISH:
|
case UserActionTypes.FETCH_USER_COMMUNITIES_FINISH:
|
||||||
setState("user", "users", {
|
setState("user", "users", action.payload.id, {
|
||||||
...state.users,
|
communities: action.payload.communities.map(
|
||||||
[action.payload.id]: {
|
(community) => community.id,
|
||||||
id: action.payload.id,
|
),
|
||||||
communities: action.payload.communities.map(
|
|
||||||
(community) => community.id,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,83 @@
|
||||||
import type { Component } from "solid-js";
|
import { createEffect, createMemo, type Component } from "solid-js";
|
||||||
import { CommunityView } from "../CommunityView";
|
import { CommunityView } from "../CommunityView";
|
||||||
|
import { dispatch, state } from "../../store/state";
|
||||||
|
import { CommunityActionTypes, ICommunity } from "../../store/community";
|
||||||
|
import { ChannelActionTypes } from "../../store/channel";
|
||||||
|
import { Channel } from "../../components/Channel";
|
||||||
|
import { CommunityBar } from "../../components/CommunityBar";
|
||||||
|
|
||||||
const ChannelView: Component = () => {
|
const ChannelView: Component = () => {
|
||||||
|
const channelIds = createMemo(() => {
|
||||||
|
const activeCommunityId = state.community.active;
|
||||||
|
if (!activeCommunityId) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const community = state.community.communities[activeCommunityId];
|
||||||
|
if (!community) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return community.channels ?? [];
|
||||||
|
});
|
||||||
|
|
||||||
|
const communityInfo = createMemo<ICommunity | undefined>(() => {
|
||||||
|
const activeCommunityId = state.community.active;
|
||||||
|
return state.community.communities[activeCommunityId];
|
||||||
|
});
|
||||||
|
|
||||||
|
createEffect(() => {
|
||||||
|
if (state.community.active) {
|
||||||
|
dispatch({
|
||||||
|
type: CommunityActionTypes.FETCH_COMMUNITY_CHANNELS_START,
|
||||||
|
payload: state.community.active,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const onChannelClick = (id: string) => {
|
||||||
|
dispatch({
|
||||||
|
type: ChannelActionTypes.FETCH_CHANNEL_START,
|
||||||
|
payload: id,
|
||||||
|
});
|
||||||
|
dispatch({
|
||||||
|
type: ChannelActionTypes.SET_ACTIVE_CHANNEL,
|
||||||
|
payload: id,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapChannel = (channelId: string) => {
|
||||||
|
const channel = state.channel.channels[channelId];
|
||||||
|
if (!channel) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Channel
|
||||||
|
id={channel.id}
|
||||||
|
name={channel.name ?? ""}
|
||||||
|
active={channel.id === state.channel.active}
|
||||||
|
onChannelClick={onChannelClick}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="bg-stone-900 w-96 shadow-panel z-20">
|
<div class="flex flex-row bg-stone-900 w-80 shadow-panel z-20">
|
||||||
<CommunityView />
|
<CommunityView />
|
||||||
<div></div>
|
<div class="h-full w-full relative">
|
||||||
|
<CommunityBar
|
||||||
|
id={communityInfo()?.id}
|
||||||
|
name={communityInfo()?.name}
|
||||||
|
description={communityInfo()?.description}
|
||||||
|
avatar={
|
||||||
|
"https://img.daisyui.com/images/profile/demo/yellingcat@192.webp"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<ul class="h-full list flex flex-col p-2 gap-1 pt-18 overflow-y-auto scrollbar-thin scrollbar-thumb-gray-500 scrollbar-track-gray-800">
|
||||||
|
{channelIds().map(mapChannel)}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
import { onMount, type Component } from "solid-js";
|
import { createMemo, onMount, type Component } from "solid-js";
|
||||||
import { ChannelBar } from "../../components/ChannelBar";
|
import { ChannelBar } from "../../components/ChannelBar";
|
||||||
import { MessageBar } from "../../components/MessageBar";
|
import { MessageBar } from "../../components/MessageBar";
|
||||||
import { Message } from "../../components/Message";
|
import { Message } from "../../components/Message";
|
||||||
|
import { dispatch, state } from "../../store/state";
|
||||||
|
import { UserActionTypes } from "../../store/user";
|
||||||
|
import { IChannel } from "../../store/channel";
|
||||||
|
|
||||||
const ChatView: Component = () => {
|
const ChatView: Component = () => {
|
||||||
const testMessages = [
|
const testMessages = [
|
||||||
|
|
@ -175,6 +178,11 @@ const ChatView: Component = () => {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const channelInfo = createMemo<IChannel | undefined>(() => {
|
||||||
|
const activeChannelId = state.channel.active;
|
||||||
|
return state.channel.channels[activeChannelId];
|
||||||
|
});
|
||||||
|
|
||||||
let scrollRef: HTMLUListElement | undefined;
|
let scrollRef: HTMLUListElement | undefined;
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
if (scrollRef) {
|
if (scrollRef) {
|
||||||
|
|
@ -183,16 +191,23 @@ const ChatView: Component = () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const onProfileClick = (userId: string) => {
|
const onProfileClick = (userId: string) => {
|
||||||
console.log(userId);
|
dispatch({
|
||||||
|
type: UserActionTypes.FETCH_USER_START,
|
||||||
|
payload: userId,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="bg-stone-800 flex-1 z-0 relative">
|
<div class="bg-stone-800 flex-1 z-0 relative">
|
||||||
<div class="h-full">
|
<div class="h-full">
|
||||||
<ChannelBar />
|
<ChannelBar
|
||||||
|
id={channelInfo()?.id}
|
||||||
|
name={channelInfo()?.name}
|
||||||
|
description={channelInfo()?.description}
|
||||||
|
/>
|
||||||
<ul
|
<ul
|
||||||
ref={scrollRef}
|
ref={scrollRef}
|
||||||
class="h-full list flex flex-col p-2 pt-16 pb-24 overflow-y-auto scrollbar-thin scrollbar-thumb-gray-500 scrollbar-track-gray-800"
|
class="h-full list flex flex-col p-2 pt-18 pb-24 overflow-y-auto scrollbar-thin scrollbar-thumb-gray-500 scrollbar-track-gray-800"
|
||||||
>
|
>
|
||||||
{testMessages.map((msg) => (
|
{testMessages.map((msg) => (
|
||||||
<Message
|
<Message
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { createMemo, type Component } from "solid-js";
|
import { createMemo, type Component } from "solid-js";
|
||||||
import { Community } from "../../components/Community";
|
import { Community } from "../../components/Community";
|
||||||
import { state } from "../../store/state";
|
import { dispatch, state } from "../../store/state";
|
||||||
|
import { CommunityActionTypes } from "../../store/community";
|
||||||
|
|
||||||
const CommunityView: Component = () => {
|
const CommunityView: Component = () => {
|
||||||
const communityIds = createMemo(() => {
|
const communityIds = createMemo(() => {
|
||||||
|
|
@ -18,7 +19,14 @@ const CommunityView: Component = () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const onCommunityClick = (id: string) => {
|
const onCommunityClick = (id: string) => {
|
||||||
console.log(id);
|
dispatch({
|
||||||
|
type: CommunityActionTypes.FETCH_COMMUNITY_START,
|
||||||
|
payload: id,
|
||||||
|
});
|
||||||
|
dispatch({
|
||||||
|
type: CommunityActionTypes.SET_ACTIVE_COMMUNITY,
|
||||||
|
payload: id,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapCommunity = (communityId: string) => {
|
const mapCommunity = (communityId: string) => {
|
||||||
|
|
@ -34,16 +42,15 @@ const CommunityView: Component = () => {
|
||||||
avatar={
|
avatar={
|
||||||
"https://img.daisyui.com/images/profile/demo/yellingcat@192.webp"
|
"https://img.daisyui.com/images/profile/demo/yellingcat@192.webp"
|
||||||
}
|
}
|
||||||
|
active={community.id === state.community.active}
|
||||||
onCommunityClick={onCommunityClick}
|
onCommunityClick={onCommunityClick}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="p-3 h-full">
|
<div class="bg-stone-950 w-18 h-full shadow-panel z-30 flex flex-col p-2 gap-2">
|
||||||
<div class="bg-stone-950 w-20 h-full rounded-full shadow-panel z-30 flex flex-col p-3 gap-3">
|
{communityIds().map(mapCommunity)}
|
||||||
{communityIds().map(mapCommunity)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,68 @@
|
||||||
import type { Component } from "solid-js";
|
import { createEffect, createMemo, type Component } from "solid-js";
|
||||||
|
import { dispatch, state } from "../../store/state";
|
||||||
|
import { CommunityActionTypes } from "../../store/community";
|
||||||
|
import { UserActionTypes } from "../../store/user";
|
||||||
|
import { Member } from "../../components/Member";
|
||||||
|
|
||||||
const MemberView: Component = () => {
|
const MemberView: Component = () => {
|
||||||
return <div class="bg-stone-900 w-64 shadow-panel z-20"></div>;
|
const memberIds = createMemo(() => {
|
||||||
|
const activeCommunityId = state.community.active;
|
||||||
|
if (!activeCommunityId) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const community = state.community.communities[activeCommunityId];
|
||||||
|
if (!community) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return community.members ?? [];
|
||||||
|
});
|
||||||
|
|
||||||
|
createEffect(() => {
|
||||||
|
if (state.community.active) {
|
||||||
|
dispatch({
|
||||||
|
type: CommunityActionTypes.FETCH_COMMUNITY_MEMBERS_START,
|
||||||
|
payload: state.community.active,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const onMemberClick = (id: string) => {
|
||||||
|
dispatch({
|
||||||
|
type: UserActionTypes.FETCH_USER_START,
|
||||||
|
payload: id,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapMember = (memberId: string) => {
|
||||||
|
const member = state.user.users[memberId];
|
||||||
|
if (!member) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Member
|
||||||
|
id={member.id}
|
||||||
|
username={member.username ?? ""}
|
||||||
|
avatar={
|
||||||
|
"https://img.daisyui.com/images/profile/demo/yellingcat@192.webp"
|
||||||
|
}
|
||||||
|
active={false}
|
||||||
|
onMemberClick={onMemberClick}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class="bg-stone-900 w-64 shadow-panel z-20 relative">
|
||||||
|
<div class="h-full">
|
||||||
|
<ul class="h-full list flex flex-col p-2 gap-1 overflow-y-auto scrollbar-thin scrollbar-thumb-gray-500 scrollbar-track-gray-800">
|
||||||
|
{memberIds().map(mapMember)}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export { MemberView };
|
export { MemberView };
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue