revite/src/pages/settings/server/Members.tsx

158 lines
7.3 KiB
TypeScript
Raw Normal View History

import { ChevronDown } from "@styled-icons/boxicons-regular";
import { isEqual } from "lodash";
2021-06-19 22:37:12 +01:00
import { Servers } from "revolt.js/dist/api/objects";
2021-07-05 11:23:23 +01:00
import styles from "./Panes.module.scss";
import { Text } from "preact-i18n";
2021-07-05 11:23:23 +01:00
import { useEffect, useState } from "preact/hooks";
2021-06-19 22:37:12 +01:00
import { useForceUpdate, useUsers } from "../../../context/revoltjs/hooks";
import UserIcon from "../../../components/common/user/UserIcon";
import Button from "../../../components/ui/Button";
import Checkbox from "../../../components/ui/Checkbox";
import IconButton from "../../../components/ui/IconButton";
import Overline from "../../../components/ui/Overline";
2021-06-19 22:37:12 +01:00
interface Props {
2021-07-05 11:25:20 +01:00
server: Servers.Server;
2021-06-19 22:37:12 +01:00
}
export function Members({ server }: Props) {
2021-07-05 11:25:20 +01:00
const [members, setMembers] = useState<Servers.Member[] | undefined>(
undefined,
);
2021-07-01 17:36:34 +01:00
2021-07-05 11:25:20 +01:00
const ctx = useForceUpdate();
const [selected, setSelected] = useState<undefined | string>();
2021-07-05 11:25:20 +01:00
const users = useUsers(members?.map((x) => x._id.user) ?? [], ctx);
2021-06-19 22:37:12 +01:00
2021-07-05 11:25:20 +01:00
useEffect(() => {
ctx.client.servers.members
.fetchMembers(server._id)
.then((members) => setMembers(members));
}, []);
2021-06-19 22:37:12 +01:00
const [roles, setRoles] = useState<string[]>([]);
useEffect(() => {
if (selected) {
setRoles(
members!.find((x) => x._id.user === selected)?.roles ?? [],
);
}
}, [selected]);
2021-07-05 11:25:20 +01:00
return (
<div className={styles.userList}>
2021-07-05 11:25:20 +01:00
<div className={styles.subtitle}>
{members?.length ?? 0} Members
</div>
{members &&
members.length > 0 &&
members
.map((x) => {
return {
member: x,
user: users.find((y) => y?._id === x._id.user),
};
})
.map(({ member, user }) => (
<>
<div
key={member._id.user}
className={styles.member}
data-open={selected === member._id.user}
onClick={() =>
setSelected(
selected === member._id.user
? undefined
: member._id.user,
)
}>
<span>
<UserIcon target={user} size={24} />{" "}
{user?.username ?? (
<Text id="app.main.channel.unknown_user" />
)}
</span>
<IconButton className={styles.chevron}>
<ChevronDown size={24} />
</IconButton>
2021-07-05 11:25:20 +01:00
</div>
{selected === member._id.user && (
<div
key={"drop_" + member._id.user}
className={styles.memberView}>
<Overline type="subtle">Roles</Overline>
{Object.keys(server.roles ?? {}).map(
(key) => {
let role = server.roles![key];
return (
<Checkbox
checked={
roles.includes(key) ??
false
}
onChange={(v) => {
if (v) {
setRoles([
...roles,
key,
]);
} else {
setRoles(
roles.filter(
(x) =>
x !==
key,
),
);
}
}}>
<span
style={{
color: role.colour,
}}>
{role.name}
</span>
</Checkbox>
);
},
)}
<Button
compact
disabled={isEqual(
member.roles ?? [],
roles,
)}
onClick={async () => {
await ctx.client.servers.members.editMember(
server._id,
member._id.user,
{
roles,
},
);
setMembers(
members.map((x) =>
x._id.user ===
member._id.user
? {
...x,
roles,
}
: x,
),
);
}}>
<Text id="app.special.modals.actions.save" />
</Button>
</div>
)}
</>
))}
2021-07-05 11:25:20 +01:00
</div>
);
2021-06-19 22:37:12 +01:00
}