Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 30 additions & 28 deletions apps/admin/src/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,36 +31,38 @@ import StatusMonitor from "./StatusMonitor";
import { MdDarkMode, MdLightMode, MdPalette } from "react-icons/md";
import ColorProfileSelector from "./ColorProfileSelector";
import { useColorTheme } from "@/contexts/ColorThemeContext";
import { Role } from "@rp/shared";

const linkMap = {
Dashboard: "/",
Stats: "/stats",
Events: "/events",
Meetings: "/meetings",
Roles: "/roles",
Sponsors: "/sponsors",
Speakers: "/speakers",
Shifts: "/shifts",
"Check-in": "/checkin",
Massmailer: "/massmailer",
Leaderboard: "/leaderboard-view",
Attendance: "/attendance-view"
const linkMap: Record<string, { path: string; role: Role }> = {
Dashboard: { path: "/", role: "STAFF" },
Stats: { path: "/stats", role: "ADMIN" },
Events: { path: "/events", role: "ADMIN" },
Meetings: { path: "/meetings", role: "ADMIN" },
Roles: { path: "/roles", role: "SUPER_ADMIN" },
Sponsors: { path: "/sponsors", role: "ADMIN" },
Speakers: { path: "/speakers", role: "ADMIN" },
Shifts: { path: "/shifts", role: "ADMIN" },
"Check-in": { path: "/checkin", role: "ADMIN" },
Massmailer: { path: "/massmailer", role: "SUPER_ADMIN" },
Leaderboard: { path: "/leaderboard-view", role: "ADMIN" },
Attendance: { path: "/attendance-view", role: "ADMIN" }
};

const getLinks = (roles: string[], loading: boolean): string[] => {
const getLinks = (roles: string[], loading: boolean) => {
if (loading) {
return [];
}

if (roles.includes("ADMIN")) {
return Object.keys(linkMap);
}

if (roles.includes("STAFF")) {
return ["Dashboard"];
}
const accessible = Object.entries(linkMap)
.filter(([, { role }]) => roles.includes(role))
.map(([name, { path }]) => {
return {
name,
path
};
});

return [];
return accessible;
};

const Settings = ({ displayName }: { displayName?: string }) => {
Expand Down Expand Up @@ -313,9 +315,9 @@ const Navbar: React.FC<NavbarProps> = ({ roles, loading, displayName }) => {
height="100%"
overflowY="auto"
>
{getLinks(roles, loading).map((link) => (
<NavbarLink key={link} href={linkMap[link as keyof typeof linkMap]}>
{link}
{getLinks(roles, loading).map(({ name, path }) => (
<NavbarLink key={name} href={path}>
{name}
</NavbarLink>
))}
</VStack>
Expand Down Expand Up @@ -348,9 +350,9 @@ const Navbar: React.FC<NavbarProps> = ({ roles, loading, displayName }) => {
h="100%"
maxH="calc(100% - calc(100px - 42px))"
>
{getLinks(roles, loading).map((link) => (
<NavbarLink key={link} href={linkMap[link as keyof typeof linkMap]}>
{link}
{getLinks(roles, loading).map(({ name, path }) => (
<NavbarLink key={name} href={path}>
{name}
</NavbarLink>
))}
<HStack
Expand Down
60 changes: 35 additions & 25 deletions apps/admin/src/components/Roles/RolesCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,8 @@ const RolesCard: React.FC<RolesCardProps> = () => {

const getRoleIcon = (userRole: Role) => {
switch (userRole) {
case "SUPER_ADMIN":
return <StarIcon color="yellow.500" />;
case "ADMIN":
return <StarIcon color="red.500" />;
case "STAFF":
Expand All @@ -229,6 +231,8 @@ const RolesCard: React.FC<RolesCardProps> = () => {

const getRoleColor = (userRole: Role) => {
switch (userRole) {
case "SUPER_ADMIN":
return "yellow";
case "ADMIN":
return "red";
case "STAFF":
Expand Down Expand Up @@ -422,8 +426,10 @@ const RolesCard: React.FC<RolesCardProps> = () => {
}
}}
isDisabled={
userRole === "STAFF" &&
user.roles.includes("ADMIN")
(userRole === "STAFF" &&
user.roles.includes("ADMIN")) ||
(userRole === "ADMIN" &&
user.roles.includes("SUPER_ADMIN"))
}
_hover={{
bg: "red.100"
Expand All @@ -433,29 +439,33 @@ const RolesCard: React.FC<RolesCardProps> = () => {
))}

{/* Add role button - only show for users with userId (logged in users) */}
{user.userId && !user.roles.includes("ADMIN") && (
<IconButton
size="xs"
icon={<AddIcon />}
aria-label="Add role"
colorScheme="green"
variant="outline"
onClick={() => {
// For now, just add ADMIN role
// Could be expanded to show a dropdown of available roles
if (
!user.roles.includes("ADMIN") &&
user.userId
) {
addRole("ADMIN", user.userId);
}
}}
isDisabled={user.roles.includes("ADMIN")}
_hover={{
bg: "green.50"
}}
/>
)}
{user.userId &&
(!user.roles.includes("ADMIN") ||
!user.roles.includes("SUPER_ADMIN")) && (
<IconButton
size="xs"
icon={<AddIcon />}
aria-label="Add role"
colorScheme="green"
variant="outline"
onClick={() => {
// For now, just add ADMIN/SUPER_ADMIN role
// Could be expanded to show a dropdown of available roles
if (!user.userId) return;

if (!user.roles.includes("ADMIN")) {
addRole("ADMIN", user.userId);
} else if (
!user.roles.includes("SUPER_ADMIN")
) {
addRole("SUPER_ADMIN", user.userId);
}
}}
_hover={{
bg: "green.50"
}}
/>
)}
</HStack>
</VStack>
</Flex>
Expand Down
3 changes: 2 additions & 1 deletion shared/src/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@ export type Role =
| "ADMIN"
| "CORPORATE"
| "PUZZLEBANG"
| "PENDING";
| "PENDING"
| "SUPER_ADMIN";

export type RoleObject = {
userId?: string;
Expand Down
Loading