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: Find member includes all appropriate members in results #401

Merged
merged 2 commits into from
Jan 12, 2024
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
109 changes: 70 additions & 39 deletions packages/client/src/pages/admin/pluggables/FindMember.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/

import {
always,
api,
CAPMemberContact,
CAPMemberContactPriority,
Expand All @@ -33,7 +34,8 @@ import {
Maybe,
NHQ,
pipe,
stringifyMemberReference,
ShortNHQDutyPosition,
stringifyMemberReference
} from 'common-lib';
import React, { ReactElement, useCallback } from 'react';
import { Provider, useDispatch, useSelector } from 'react-redux';
Expand All @@ -59,6 +61,7 @@ import Loader from '../../../components/Loader';
import { FetchAPIProps, withFetchApi } from '../../../globals';
import { TFetchAPI } from '../../../lib/apis';
import { PageProps } from '../../Page';
import { MemberSearchResult } from 'common-lib/dist/typings/apis/member';

interface MemberSearchStateLoaded {
state: 'LOADED';
Expand Down Expand Up @@ -351,28 +354,28 @@ export function configureStore(fetchApi: TFetchAPI): Store<MemberSearchState, Me
| MemberSearchToggleIncludeAssistants =>
(action.type === 'FIRST_NAME_SEARCH_UPDATE' &&
state$.value.unitNameInput.length +
state$.value.lastNameInput.length +
state$.value.dutyNameInput.length +
action.payload.length >=
3) ||
state$.value.lastNameInput.length +
state$.value.dutyNameInput.length +
action.payload.length >=
3) ||
(action.type === 'LAST_NAME_SEARCH_UPDATE' &&
state$.value.unitNameInput.length +
state$.value.firstNameInput.length +
state$.value.dutyNameInput.length +
action.payload.length >=
3) ||
state$.value.firstNameInput.length +
state$.value.dutyNameInput.length +
action.payload.length >=
3) ||
(action.type === 'UNIT_NAME_SEARCH_UPDATE' &&
state$.value.firstNameInput.length +
state$.value.lastNameInput.length +
state$.value.dutyNameInput.length +
action.payload.length >=
3) ||
state$.value.lastNameInput.length +
state$.value.dutyNameInput.length +
action.payload.length >=
3) ||
(action.type === 'DUTY_NAME_SEARCH_UPDATE' &&
state$.value.firstNameInput.length +
state$.value.lastNameInput.length +
state$.value.unitNameInput.length +
action.payload.length >=
3) ||
state$.value.lastNameInput.length +
state$.value.unitNameInput.length +
action.payload.length >=
3) ||
action.type === 'TOGGLE_INCLUDE_ASSISTANTS',
);

Expand Down Expand Up @@ -417,28 +420,28 @@ export function configureStore(fetchApi: TFetchAPI): Store<MemberSearchState, Me
| MemberSearchDutyNameSearchInputAction =>
(action.type === 'FIRST_NAME_SEARCH_UPDATE' &&
state$.value.unitNameInput.length +
state$.value.lastNameInput.length +
state$.value.dutyNameInput.length +
action.payload.length <
3) ||
state$.value.lastNameInput.length +
state$.value.dutyNameInput.length +
action.payload.length <
3) ||
(action.type === 'LAST_NAME_SEARCH_UPDATE' &&
state$.value.unitNameInput.length +
state$.value.firstNameInput.length +
state$.value.dutyNameInput.length +
action.payload.length <
3) ||
state$.value.firstNameInput.length +
state$.value.dutyNameInput.length +
action.payload.length <
3) ||
(action.type === 'UNIT_NAME_SEARCH_UPDATE' &&
state$.value.firstNameInput.length +
state$.value.lastNameInput.length +
state$.value.dutyNameInput.length +
action.payload.length <
3) ||
state$.value.lastNameInput.length +
state$.value.dutyNameInput.length +
action.payload.length <
3) ||
(action.type === 'DUTY_NAME_SEARCH_UPDATE' &&
state$.value.firstNameInput.length +
state$.value.lastNameInput.length +
state$.value.unitNameInput.length +
action.payload.length <
3),
state$.value.lastNameInput.length +
state$.value.unitNameInput.length +
action.payload.length <
3),
),
mapTo(clearMembers()),
);
Expand Down Expand Up @@ -579,6 +582,9 @@ const MemberSearchRenderSearchedMembers = (): ReactElement => {
const inputHasBeenEntered = useSelector<MemberSearchState, boolean>(
state => state.inputHasBeenEntered,
);
const dutyInput = useSelector<MemberSearchState, string>(
state => state.dutyNameInput
);
const currentMember = useSelector<MemberSearchState, api.member.MemberSearchResult | null>(
state => state.memberViewed,
(a, b) =>
Expand All @@ -595,8 +601,8 @@ const MemberSearchRenderSearchedMembers = (): ReactElement => {
state.state === 'ERROR'
? { state: 'ERROR', message: state.message }
: state.state === 'LOADED'
? { state: 'LOADED', members: state.members }
: { state: 'LOADING' },
? { state: 'LOADED', members: state.members }
: { state: 'LOADING' },
(a, b) =>
a.state === b.state ||
(a.state === 'LOADED' && b.state === 'LOADED' && a.members.length === b.members.length),
Expand All @@ -618,13 +624,23 @@ const MemberSearchRenderSearchedMembers = (): ReactElement => {
maxHeight: 400,
}}
>
{dataState.members.map(val => (
<li
{dataState.members.map(val => {
const dutyDisplay = val.member.dutyPositions
.filter((duty): duty is ShortNHQDutyPosition => duty.duty === dutyInput && duty.type === 'NHQ')
.map(duty => {
const dutyOrg = duty.orgid === val.member.orgid
? val.organization
: Maybe.fromValue(val.dutyOrgs.find(({ ORGID }) => ORGID === duty.orgid));

return `${duty.assistant ? ', Asst' : ', Pri'} ${Maybe.cata<NHQ.Organization, string>(always(''))(org => 'for [' + org.Wing + '-' + org.Unit + ']')(dutyOrg)}`
});

return <li
key={stringifyMemberReference(val.member)}
onClick={() => updateMember(val)}
className={
!!currentMember &&
stringifyMemberReference(val.member) ===
stringifyMemberReference(val.member) ===
stringifyMemberReference(currentMember.member)
? 'selected'
: ''
Expand All @@ -636,8 +652,9 @@ const MemberSearchRenderSearchedMembers = (): ReactElement => {
val.organization,
),
)}
{dutyDisplay.join('')}
</li>
))}
})}
</ul>
) : (
<div className="selector-values" style={{ padding: '10px' }}>
Expand Down Expand Up @@ -672,6 +689,19 @@ const MemberSearchRenderCurrentMemberInfo = (): ReactElement => {
Maybe.orSome<ReactElement | null>(null),
);


const dutyDisplay = ({ member, dutyOrgs, organization }: MemberSearchResult): React.ReactNode[] =>
member.dutyPositions.map(duty => (
duty.type === 'NHQ'
? <li key={`${duty.duty}-${duty.orgid}`}>
{duty.assistant ? 'Assistant ' : ''}{duty.duty}:
{Maybe.orSome('')(Maybe.map((org: NHQ.Organization) => ` [${org.Wing}-${org.Unit}]`)(
member.orgid === duty.orgid ? organization : Maybe.fromValue(dutyOrgs.find(({ ORGID }) => ORGID === duty.orgid))
))}
</li>
: null
));

const orgDisplay =
currentMember && Maybe.isSome(currentMember.organization)
? ` (${currentMember.organization.value.Name})`
Expand Down Expand Up @@ -775,6 +805,7 @@ const MemberSearchRenderCurrentMemberInfo = (): ReactElement => {
'CADETPARENTPHONE',
'EMERGENCY',
)(currentMember.member.contact)}
{dutyDisplay(currentMember)}
</ul>
</div>
) : (
Expand Down
109 changes: 72 additions & 37 deletions packages/common-lib/src/consts/dutyPositions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,76 +23,111 @@

export const dutyPositions = [
'Cadet Safety NCO',
'Cadet Aerospace Education Officer',
'Cadet Deputy Commander for Operations',
'Cadet Operations Officer',
'Cadet Recruiting Officer',
'Cadet Leadership Officer',
'Cadet WCAC Assistant',
'Cadet Commander',
'Cadet Historian Officer',
'Cadet Safety Officer',
'Cadet Deputy Commander for Support',
'Cadet Activities NCO',
'Cadet Activities Officer',
'Cadet Administrative NCO',
'Cadet Administrative Officer',
'Cadet Aerospace Education NCO',
'Cadet Aerospace Education Officer',
'Cadet Commander',
'Cadet Communications NCO',
'Cadet Deputy Commander for Operations',
'Cadet Deputy Commander for Support',
'Cadet Drug Demand Reduction NCO',
'Cadet Element Leader',
'Cadet Emergency Services NCO',
'Cadet Emergency Services Officer',
'Cadet First Sergeant',
'Cadet Flight Commander',
'Cadet Flight Sergeant',
'Cadet Historian NCO',
'Cadet Historian Officer',
'Cadet IT Officer NCO',
'Cadet IT Officer',
'Cadet Leadership NCO',
'Cadet Leadership Officer',
'Cadet Logistics NCO',
'Cadet Operations NCO',
'Cadet Operations Officer',
'Cadet Public Affairs NCO',
'Cadet Public Affairs Officer',
'Cadet Recruiting NCO',
'Cadet Recruiting Officer',
'Cadet Safety Officer',
'Cadet Supply NCO',
'Cadet Activities Officer',
'Cadet Public Affairs Officer',
'Cadet Supply Officer',
'Cadet Administrative Officer',
'Cadet Flight Commander',
'Cadet IT Officer',
'Cadet IT Officer NCO',
'Cadet WCAC Assistant',
'Cadet WCAC Representative',
'Cadet Flight Sergeant',
'Cadet Emergency Services Officer',
'Cadet First Sergeant',
'Cadet Element Leader',
'Finance Officer',
'Health Services Officer',
'Safety Officer',
'Aerospace Education Officer',
'Operations Officer',
'Standardization/Evaluation Officer',
'Character Development Instructor',
'Communications Officer ',
'Drug Demand Reduction Officer',
'Activities Officer',
'Administrative Officer',
'Advisor to the Commander',
'Aerospace Education Officer',
'Alerting Officer',
'Cadet Activities Officer',
'Cadet Programs Development Officer',
'Chaplain',
'Character Development Instructor',
'Chief of Staff',
'CIS Officer',
'Command NCO',
'Commander',
'Communications Engineering Officer',
'Communications Licensing Officer',
'Communications Officer ',
'Communications Training Officer',
'Counterdrug Officer',
'Cyber Education Officer',
'Deputy Commander',
'Deputy Commander for Cadets',
'Deputy Commander for Seniors',
'Director of Administration',
'Director of Aerospace Education',
'Director of Cadet Programs',
'Director of Communications',
'Director of Development',
'Director of Education and Training',
'Director of Emergency Services',
'Director of Finance',
'Director of IT',
'Director of Logistics',
'Director of Operations',
'Director of Recruiting',
'Director of Safety',
'Disaster Preparedness Officer',
'Disaster Relief Officer',
'Diversity Officer',
'Drug Demand Reduction Officer',
'Education and Training Officer',
'Emergency Services Officer',
'Emergency Services Training Officer',
'External Aerospace Education Officer',
'Finance Officer',
'Fitness Officer',
'Government Relations Advisor',
'Health Services Officer',
'Historian',
'Homeland Security Officer',
'Information Technologies Officer',
'Inspector General',
'Internal Aerospace Education Officer',
'Legal Officer',
'Logistics Officer',
'Maintenance Officer',
'Operations Officer',
'Personnel Officer',
'Professional Development Officer',
'Plans and Programs Officer',
'Public Affairs Officer',
'Recruiting & Retention Officer',
'Recruiting Officer',
'Safety Officer',
'Search and Rescue Officer',
'Squadron Activities Officer',
'Squadron Leadership Officer',
'Squadron NCO',
'Standardization/Evaluation Officer',
'Supply Officer',
'Testing Officer',
'Transportation Officer',
'Vice Commander',
'Web Security Administrator',
'Maintenance Officer',
'Cadet Activities Officer',
'Commander',
'Deputy Commander for Seniors',
'Squadron Leadership Officer',
'Supply Officer',
];
];
1 change: 1 addition & 0 deletions packages/common-lib/src/typings/apis/member/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ export interface MemberGet {
export interface MemberSearchResult {
member: Member;
organization: MaybeObj<NHQ.Organization>;
dutyOrgs: NHQ.Organization[];
}

/**
Expand Down
Loading