Skip to content

Commit 63de8e2

Browse files
committed
Enable non-voting members in the Admin portal
1 parent 27f2bcd commit 63de8e2

File tree

2 files changed

+68
-15
lines changed

2 files changed

+68
-15
lines changed

src/api/routes/organizations.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -363,14 +363,16 @@ const organizationsPlugin: FastifyPluginAsync = async (fastify, _options) => {
363363
if (add.length > 0) {
364364
try {
365365
const paidMemberships = await Promise.all(
366-
add.map((u) =>
367-
checkPaidMembership({
368-
netId: u.username.replace("@illinois.edu", ""),
369-
logger: request.log,
370-
dynamoClient: fastify.dynamoClient,
371-
redisClient: fastify.redisClient,
372-
}),
373-
),
366+
add
367+
.filter((x) => !x.nonVotingMember)
368+
.map((u) =>
369+
checkPaidMembership({
370+
netId: u.username.replace("@illinois.edu", ""),
371+
logger: request.log,
372+
dynamoClient: fastify.dynamoClient,
373+
redisClient: fastify.redisClient,
374+
}),
375+
),
374376
);
375377
if (paidMemberships.some((p) => !p)) {
376378
throw new ValidationError({

src/ui/pages/organization/ManageOrganizationForm.tsx

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,16 @@ import {
2121
Combobox,
2222
useCombobox,
2323
InputBase,
24+
Checkbox,
2425
} from "@mantine/core";
2526
import { useForm } from "@mantine/form";
2627
import { notifications } from "@mantine/notifications";
27-
import { IconPlus, IconTrash, IconUserPlus } from "@tabler/icons-react";
28+
import {
29+
IconPlus,
30+
IconTrash,
31+
IconUserPlus,
32+
IconAlertTriangle,
33+
} from "@tabler/icons-react";
2834
import {
2935
LeadEntry,
3036
leadTitleSuggestions,
@@ -68,6 +74,7 @@ export const ManageOrganizationForm: React.FC<ManageOrganizationFormProps> = ({
6874
const [newLeadName, setNewLeadName] = useState("");
6975
const [newLeadEmail, setNewLeadEmail] = useState("");
7076
const [newLeadTitle, setNewLeadTitle] = useState("");
77+
const [newLeadNonVoting, setNewLeadNonVoting] = useState(false);
7178

7279
// Combobox for title suggestions
7380
const combobox = useCombobox({
@@ -126,6 +133,7 @@ export const ManageOrganizationForm: React.FC<ManageOrganizationFormProps> = ({
126133
setNewLeadName("");
127134
setNewLeadEmail("");
128135
setNewLeadTitle("");
136+
setNewLeadNonVoting(false);
129137

130138
// Fetch new organization data
131139
fetchOrganizationData();
@@ -169,12 +177,14 @@ export const ManageOrganizationForm: React.FC<ManageOrganizationFormProps> = ({
169177
name: newLeadName.trim(),
170178
username: newLeadEmail.trim(),
171179
title: newLeadTitle.trim(),
180+
nonVotingMember: newLeadNonVoting,
172181
},
173182
]);
174183

175184
setNewLeadName("");
176185
setNewLeadEmail("");
177186
setNewLeadTitle("");
187+
setNewLeadNonVoting(false);
178188
};
179189

180190
const handleQueueRemove = (email: string) => {
@@ -361,9 +371,9 @@ export const ManageOrganizationForm: React.FC<ManageOrganizationFormProps> = ({
361371
Organization Leads
362372
</Title>
363373
<Text size="sm" c="dimmed" mb="md">
364-
These users will be your Executive Council representatives and
365-
will be given management permissions for your org. These users
366-
must be paid members.
374+
These users will be given management permissions for your org.
375+
Voting members must be paid members and will be your org's
376+
represenatives at Executive Council meetings.
367377
</Text>
368378

369379
<Table verticalSpacing="sm" highlightOnHover>
@@ -395,9 +405,20 @@ export const ManageOrganizationForm: React.FC<ManageOrganizationFormProps> = ({
395405
<Group gap="sm">
396406
<Avatar name={lead.name} color="initials" />
397407
<div>
398-
<Text fz="sm" fw={500}>
399-
{lead.name}
400-
</Text>
408+
<Group gap="xs">
409+
<Text fz="sm" fw={500}>
410+
{lead.name}
411+
</Text>
412+
{lead.nonVotingMember && (
413+
<Badge
414+
color="gray"
415+
variant="light"
416+
size="sm"
417+
>
418+
Non-Voting
419+
</Badge>
420+
)}
421+
</Group>
401422
<Text fz="xs" c="dimmed">
402423
{lead.username}
403424
</Text>
@@ -514,6 +535,31 @@ export const ManageOrganizationForm: React.FC<ManageOrganizationFormProps> = ({
514535
</Combobox.Options>
515536
</Combobox.Dropdown>
516537
</Combobox>
538+
539+
<Checkbox
540+
label="Non-voting member"
541+
description="Check this if the lead should not have voting rights in Executive Council"
542+
checked={newLeadNonVoting}
543+
onChange={(e) => setNewLeadNonVoting(e.currentTarget.checked)}
544+
/>
545+
546+
{newLeadNonVoting && (
547+
<Alert
548+
icon={<IconAlertTriangle size={16} />}
549+
color="yellow"
550+
variant="light"
551+
mt="xs"
552+
>
553+
<Text size="sm" fw={500} mb={4}>
554+
Warning: Non-voting member
555+
</Text>
556+
<Text size="sm">
557+
This lead will have management permissions but will not
558+
have voting rights in Executive Council meetings. Use this
559+
designation carefully.
560+
</Text>
561+
</Alert>
562+
)}
517563
</Stack>
518564

519565
<Button
@@ -552,6 +598,11 @@ export const ManageOrganizationForm: React.FC<ManageOrganizationFormProps> = ({
552598
{toAdd.map((lead) => (
553599
<Text key={lead.username} fz="sm">
554600
- {lead.name} ({lead.username}) - {lead.title}
601+
{lead.nonVotingMember && (
602+
<Badge color="gray" variant="light" size="sm" ml="xs">
603+
Non-Voting
604+
</Badge>
605+
)}
555606
</Text>
556607
))}
557608
</Box>

0 commit comments

Comments
 (0)