Skip to content

Commit

Permalink
feat(RoleReward): improve edition UI + allow reward creation
Browse files Browse the repository at this point in the history
  • Loading branch information
ZRunner committed Oct 21, 2024
1 parent 6f7bb38 commit f012983
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import AddIcon from "@mui/icons-material/Add";
import { Autocomplete, Stack, TextField } from "@mui/material";

import { useFetchGuildRolesQuery } from "../../../../repository/redux/api/api";
import { GuildRole } from "../../../../repository/types/guild";
import RoleMention from "../../../common/RoleMention";

interface AddRoleRewardButtonProps {
guildId: string,
existingRoleIds: string[],
addNewReward: (roleId: string) => void
}
export default function AddRoleRewardButton({ guildId, existingRoleIds, addNewReward }: AddRoleRewardButtonProps) {
const { data, error } = useFetchGuildRolesQuery({ guildId });

if (error) {
console.error("Failed to fetch roles", error);
}
if (!data) {
return null;
}

const roles = data.filter(role => !role.managed && role.id !== guildId && !existingRoleIds.includes(role.id));

const onChange = (role: GuildRole | null) => {
if (role) {
addNewReward(role.id);
}
};

return (
<Stack direction="row" gap={1} alignItems="center">
<AddIcon color="primary" />
<Autocomplete
openOnFocus
blurOnSelect
options={roles}
onChange={(_, newValue) => onChange(newValue)}
sx={{ width: 250 }}
isOptionEqualToValue={(opt, value) => opt.id === value.id}
getOptionLabel={(role) => role.name}
renderInput={(params) => (
<TextField
{...params}
variant="standard"
placeholder="Add a role reward" />
)}
renderOption={(props, opt) => (
<li {...props} key={opt.id}>
<RoleMention name={opt.name} color={opt.color} />
</li>
)}
/>
</Stack>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,7 @@ function RoleRewardRow({ roleReward, role, editRewardLevel, deleteReward }: Role

return (
<Stack direction="row" height="48px" alignItems="center">
<Stack direction="row" py={1} minWidth="18rem" alignItems="first baseline">
<RoleMention name={role?.name ?? roleReward.roleId} color={role?.color ?? 0} />
<Typography color="gray" whiteSpace="preserve"> given at level </Typography>
<Stack direction="row" py={1} gap={1} minWidth="18rem" alignItems="first baseline">
{isEditing
? <NumericInput
value={roleReward.level}
Expand All @@ -74,8 +72,9 @@ function RoleRewardRow({ roleReward, role, editRewardLevel, deleteReward }: Role
autoFocus
onBlur={() => setIsEditing(false)}
/>
: <Typography fontWeight="bold">{roleReward.level}</Typography>
: <Typography fontWeight="bold" minWidth="4.5rem">LVL {roleReward.level}</Typography>
}
<RoleMention name={role?.name ?? roleReward.roleId} color={role?.color ?? 0} />
</Stack>
{!isEditing && <>
<Tooltip title="Edit" arrow>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useFetchGuildConfigCategory } from "../../../../repository/commands/use
import { useGuildConfigRoleRewardsEditionContext } from "../../../../repository/context/GuildConfigEditionContext";
import { useFetchGuildConfigQuery, useFetchGuildRoleRewardsQuery } from "../../../../repository/redux/api/api";
import { ExternalRoutesURLs } from "../../../../router/router";
import AddRoleRewardButton from "./AddRoleRewardButton";
import DownloadLeaderboardButton from "./DownloadLeaderboardButton";
import RoleRewardsList from "./RoleRewardsList";
import UploadLeaderboardButton from "./UploadLeaderboardButton";
Expand Down Expand Up @@ -81,6 +82,7 @@ function RolesRewardsSection({ guildId }: { guildId: string }) {
title = `Role Rewards (${roleRewards.length})`;
}
}
const canAddMoreRoles = maxRoles !== undefined && roleRewards !== undefined && roleRewards.length < maxRoles;

const editRewardLevel = (roleRewardId: string, level: number) => {
if (!roleRewards) return;
Expand All @@ -102,6 +104,16 @@ function RolesRewardsSection({ guildId }: { guildId: string }) {
}
};

const addRoleReward = (roleId: string) => {
if (!roleRewards) return;
const newRewards = [...roleRewards, { roleId, level: findNextUnusedLevel()?.toString(), id: roleId }];
if (roleRewardsFromApi !== undefined && compareRoleRewards(newRewards, roleRewardsFromApi)) {
resetValue();
} else {
setValue(newRewards);
}
};

return (
<Fragment>
<DividerWithMargins />
Expand All @@ -111,6 +123,7 @@ function RolesRewardsSection({ guildId }: { guildId: string }) {
Roles rewards are roles given to your members when they reach a certain level of XP. This is a great way to encourage your members to be active! <Link href={`${ExternalRoutesURLs.documentation}/en/latest/xp.html#roles-rewards`} target="_blank" sx={{ fontStyle: "normal" }}>[Read more]</Link>
</Description>
<RoleRewardsList guildId={guildId} roleRewards={roleRewards ?? []} editRewardLevel={editRewardLevel} deleteReward={deleteRoleReward} />
{canAddMoreRoles && <AddRoleRewardButton guildId={guildId} existingRoleIds={roleRewards.map(rr => rr.roleId)} addNewReward={addRoleReward} />}
</Stack>
</Fragment>
);
Expand All @@ -121,6 +134,15 @@ function RolesRewardsSection({ guildId }: { guildId: string }) {
if (b.some((rr => !a.find(rr2 => rr2.roleId === rr.roleId && rr2.level === rr.level)))) return false;
return true;
}

function findNextUnusedLevel() {
for (let i = 1; i <= 100; i++) {
if (!roleRewards?.some(rr => rr.level === String(i))) {
return i;
}
}
return 1;
}
}

const Description = styled(Typography)(({ theme }) => ({
Expand Down

0 comments on commit f012983

Please sign in to comment.