Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fixed admin/officer/add page #261

Open
wants to merge 1 commit into
base: next
Choose a base branch
from
Open
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
168 changes: 103 additions & 65 deletions components/admin/MakeUserOfficerCard.tsx
Original file line number Diff line number Diff line change
@@ -1,72 +1,110 @@
import { Disclosure } from "@headlessui/react";
import { Checkbox } from "@mui/material";
import Button from "components/Button";
import { useState } from "react";
import { gqlQueries } from "src/api";
import { Disclosure } from '@headlessui/react';
import { Checkbox } from '@mui/material';
import Button from 'components/Button';
import { useState } from 'react';
import { gqlQueries } from 'src/api';

interface MakeUserOfficerCardProps {
firstName: string;
lastName: string;
netid: string;
profileId: string;
divisions: Array<{ id: string; deptName: string }>;
firstName: string;
lastName: string;
netid: string;
profileId: string;
divisions: Array<{ id: string; deptName: string }>;
}

export default function MakeUserOfficerCard({ firstName, lastName, netid, profileId, divisions }: MakeUserOfficerCardProps) {
const [divisionStatus, setDivisionStatus] = useState<boolean[]>(Array<boolean>(divisions.length).fill(false));
const updateDivisionStatusAtIndex = (index: number, newStatus: boolean) => {
setDivisionStatus((prev) => prev.map((status, listIndex) => {
if (index === listIndex) return newStatus;
return status;
}));
}
export default function MakeUserOfficerCard({
firstName,
lastName,
netid,
profileId,
divisions,
}: MakeUserOfficerCardProps) {
const [divisionStatus, setDivisionStatus] = useState<boolean[]>(
Array<boolean>(divisions.length).fill(false),
);
const updateDivisionStatusAtIndex = (index: number, newStatus: boolean) => {
setDivisionStatus((prev) =>
prev.map((status, listIndex) => {
if (index === listIndex) return newStatus;
return status;
}),
);
};

return <Disclosure>
{({ open }) => (
<>
<Disclosure.Button className="flex w-full justify-between rounded-lg bg-gray-200/5 px-4 py-2 text-left text-sm font-medium text-gray-100 hover:bg-gray-100 focus:outline-none focus-visible:ring focus-visible:ring-purple-500 focus-visible:ring-opacity-75 hover:text-black">
<span>{`${firstName} ${lastName} (${netid})`}</span>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className={`${
open ? 'rotate-180 transform' : ''
} h-5 w-5 text-gray-100`}
>
<path strokeLinecap="round" strokeLinejoin="round" d="M4.5 15.75l7.5-7.5 7.5 7.5" />
</svg>
</Disclosure.Button>
<Disclosure.Panel className="px-4 pt-4 pb-2 text-sm text-gray-100">
Check all division you want to add this user to:
{divisions.map((division, index) => (
<div className="flex gap-x-2 items-center" key={index} >
<Checkbox color="default" sx={{ color: "white"}} checked={divisionStatus[index]} onChange={(e) => updateDivisionStatusAtIndex(index, e.target.checked)}/>
<h1 className="text-gray-100">{division.deptName}</h1>
</div>
))}
<Button onClick={async() => {
await Promise.all(divisions.map(async (division, index) => {
if (divisionStatus[index]) await gqlQueries.addUserToDivision({
data: {
return (
<Disclosure>
{({ open }) => (
<>
<Disclosure.Button className="flex w-full justify-between rounded-lg bg-gray-200/5 px-4 py-2 text-left text-sm font-medium text-gray-100 hover:bg-gray-100 focus:outline-none focus-visible:ring focus-visible:ring-purple-500 focus-visible:ring-opacity-75 hover:text-black">
<span>{`${firstName} ${lastName} (${netid})`}</span>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className={`${open ? 'rotate-180 transform' : ''} h-5 w-5 text-gray-100`}
>
<path strokeLinecap="round" strokeLinejoin="round" d="M4.5 15.75l7.5-7.5 7.5 7.5" />
</svg>
</Disclosure.Button>
<Disclosure.Panel className="px-4 pt-4 pb-2 text-sm text-gray-100">
Check all division you want to add this user to:
{divisions.map((division, index) => (
<div className="flex gap-x-2 items-center" key={index}>
<Checkbox
color="default"
sx={{ color: 'white' }}
checked={divisionStatus[index]}
onChange={(e) => updateDivisionStatusAtIndex(index, e.target.checked)}
/>
<h1 className="text-gray-100">{division.deptName}</h1>
</div>
))}
<Button
onClick={async () => {
await Promise.all(
divisions.map(async (division, index) => {
if (divisionStatus[index])
await gqlQueries.addUserToDivision({
where: {
profileId,
},
create: {
profile: {
connect: {
id: profileId,
},
},
divisions: {
connect: [{
id: division.id
}]
}
connect: [
{
id: division.id,
},
],
},
},
where: {
profileId
}
})
}));
alert("Successfully added user to checked division(s)");
setDivisionStatus((prev) => prev.map(() => false));
}}>click to add user to checked division</Button>
</Disclosure.Panel>
</>
)}
</Disclosure>
}
update: {
divisions: {
connect: [
{
id: division.id,
},
],
},
},
});
}),
);
alert('Successfully added user to checked division(s)');
setDivisionStatus((prev) => prev.map(() => false));
}}
>
click to add user to checked division
</Button>
</Disclosure.Panel>
</>
)}
</Disclosure>
);
}
33 changes: 24 additions & 9 deletions lib/generated/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2284,6 +2284,7 @@ export type Mutation = {
updateOneScoreEntry?: Maybe<ScoreEntry>;
updateOneTypeformApplication?: Maybe<TypeformApplication>;
upsertOneDirector: Director;
upsertOneOfficer: Officer;
upsertOneParticipant: Participant;
upsertOneProfile: Profile;
};
Expand Down Expand Up @@ -2418,6 +2419,13 @@ export type MutationUpsertOneDirectorArgs = {
};


export type MutationUpsertOneOfficerArgs = {
create: OfficerCreateInput;
update: OfficerUpdateInput;
where: OfficerWhereUniqueInput;
};


export type MutationUpsertOneParticipantArgs = {
create: ParticipantCreateInput;
update: ParticipantUpdateInput;
Expand Down Expand Up @@ -2567,6 +2575,14 @@ export type OfficerCountDivisionsArgs = {
where?: InputMaybe<DivisionWhereInput>;
};

export type OfficerCreateInput = {
director?: InputMaybe<DirectorCreateNestedOneWithoutOfficerInput>;
divisions?: InputMaybe<DivisionCreateNestedManyWithoutOfficersInput>;
dummy?: InputMaybe<Scalars['String']['input']>;
id?: InputMaybe<Scalars['String']['input']>;
profile: ProfileCreateNestedOneWithoutOfficerInput;
};

export type OfficerCreateNestedManyWithoutDivisionsInput = {
connect?: InputMaybe<Array<OfficerWhereUniqueInput>>;
connectOrCreate?: InputMaybe<Array<OfficerCreateOrConnectWithoutDivisionsInput>>;
Expand Down Expand Up @@ -5327,12 +5343,13 @@ export type GetAddOfficerPageDataQueryVariables = Exact<{ [key: string]: never;
export type GetAddOfficerPageDataQuery = { __typename?: 'Query', me: { __typename?: 'User', profile?: { __typename?: 'Profile', officer?: { __typename?: 'Officer', divisions: Array<{ __typename?: 'Division', id: string, deptName: string }> } | null } | null }, officerEligibleProfiles: Array<{ __typename?: 'Profile', lastName: string, firstName: string, netid: string, id: string }> };

export type AddUserToDivisionMutationVariables = Exact<{
data: OfficerUpdateInput;
where: OfficerWhereUniqueInput;
create: OfficerCreateInput;
update: OfficerUpdateInput;
}>;


export type AddUserToDivisionMutation = { __typename?: 'Mutation', updateOneOfficer?: { __typename?: 'Officer', profile: { __typename?: 'Profile', firstName: string, lastName: string, officer?: { __typename?: 'Officer', divisions: Array<{ __typename?: 'Division', deptName: string }> } | null } } | null };
export type AddUserToDivisionMutation = { __typename?: 'Mutation', upsertOneOfficer: { __typename?: 'Officer', profile: { __typename?: 'Profile', firstName: string, lastName: string }, divisions: Array<{ __typename?: 'Division', deptName: string }> } };

export type GetAddParticipantPageDataQueryVariables = Exact<{ [key: string]: never; }>;

Expand Down Expand Up @@ -5913,16 +5930,14 @@ export const GetAddOfficerPageDataDocument = gql`
}
`;
export const AddUserToDivisionDocument = gql`
mutation addUserToDivision($data: OfficerUpdateInput!, $where: OfficerWhereUniqueInput!) {
updateOneOfficer(data: $data, where: $where) {
mutation addUserToDivision($where: OfficerWhereUniqueInput!, $create: OfficerCreateInput!, $update: OfficerUpdateInput!) {
upsertOneOfficer(where: $where, create: $create, update: $update) {
profile {
firstName
lastName
officer {
divisions {
deptName
}
}
}
divisions {
deptName
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion lib/graphql/typegraphql-prisma/exposedResolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
CreateOneScoreEntryResolver,
DeleteOneScoreEntryResolver,
UpdateOneScoreEntryResolver,
UpsertOneOfficerResolver
} from '@generated/type-graphql';

export const exposedResolvers: NonEmptyArray<Function> = [
Expand Down Expand Up @@ -100,5 +101,6 @@ export const exposedResolvers: NonEmptyArray<Function> = [
FindManyDivisionResolver,
FindManyEventResolver,
UpdateOneOfficerResolver,
UpdateOneScoreEntryResolver
UpdateOneScoreEntryResolver,
UpsertOneOfficerResolver
];
17 changes: 9 additions & 8 deletions pages/admin/officer/add.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import MakeUserOfficerCard from 'components/admin/MakeUserOfficerCard';
import { OfficerStatusContext } from 'components/context/OfficerStatus';
import { useRouter } from 'next/router';
import AdminOnlyComponent from 'components/admin/AdminOnly';
import Fuse from 'fuse.js';

export default function AddOfficerPage() {
// Need to get logged in user profile
Expand All @@ -21,16 +22,16 @@ export default function AddOfficerPage() {
{ enabled: status === 'authenticated' && officerStatusData.isOfficer },
);
const [searchQuery, setSearchQuery] = useState<string>('');
const [profiles, setProfiles] = useState<GetAddOfficerPageDataQuery['officerEligibleProfiles']>([]);
const [profiles, setProfiles] = useState<GetAddOfficerPageDataQuery['officerEligibleProfiles']>(
[],
);
let filteredProfiles = profiles;
if (searchQuery !== '') {
filteredProfiles = profiles.filter(
(profile) =>
profile.netid === searchQuery ||
`${profile.firstName} ${profile.lastName}`.toLowerCase() === searchQuery.toLowerCase() ||
profile.firstName.toLowerCase() === searchQuery.toLowerCase() ||
profile.lastName.toLowerCase() === searchQuery.toLowerCase(),
);
const fuse = new Fuse(profiles, {
keys: ['firstName', 'lastName'],
});
const result = fuse.search(searchQuery);
filteredProfiles = result.map((data) => data.item);
} else {
filteredProfiles = [];
}
Expand Down
14 changes: 6 additions & 8 deletions src/graphql/officer.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,14 @@ query getAddOfficerPageData {
}
}

mutation addUserToDivision($data: OfficerUpdateInput!, $where: OfficerWhereUniqueInput!) {
updateOneOfficer(data: $data, where: $where) {
mutation addUserToDivision($where: OfficerWhereUniqueInput!, $create: OfficerCreateInput!, $update: OfficerUpdateInput!) {
upsertOneOfficer(where: $where, create: $create, update: $update) {
profile {
firstName
lastName
officer {
divisions {
deptName
}
}
}
divisions {
deptName
}
}
}
}