All files / libs/lti/components/src/lib/participant-dashboard/end-employment-widget LtiEndEmploymentWidget.tsx

0% Statements 0/95
0% Branches 0/1
0% Functions 0/1
0% Lines 0/95

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96                                                                                                                                                                                               
import { Fragment, memo, useCallback, useMemo } from 'react';
import { FormattedMessage } from 'react-intl';

import { Button, Modal } from '@allshares/studio-design-system';
import { FormikForm } from '@amalia/ext/formik';
import { useBoolState } from '@amalia/ext/react/hooks';
import { useEndEmployment } from '@amalia/lti/state';
import {
  isGrantActiveAtEmploymentEnd,
  ltiEndEmploymentRequestSchema,
  LtiGrantLeaverType,
  type LtiEndEmploymentRequest,
  type LtiParticipantGrants,
} from '@amalia/lti/types';
import { type UserContract } from '@amalia/tenants/users/types';

import { LtiEndEmploymentWidgetForm } from './LtiEndEmploymentWidgetForm';
import { LtiEndEmploymentWidgetText } from './LtiEndEmploymentWidgetText';

interface LtiEndEmploymentWidgetProps {
  readonly grants: LtiParticipantGrants[];
  readonly user: Pick<UserContract, 'employmentEndedAt' | 'id'>;
  readonly onEmploymentEnd?: () => void;
}

export const LtiEndEmploymentWidget = memo(function LtiEndEmploymentWidget({
  grants,
  user,
  onEmploymentEnd,
}: LtiEndEmploymentWidgetProps) {
  const { isModalOpen, setModalOpenFalse, setModalOpenTrue } = useBoolState(false, 'modalOpen');
  const { mutate, isPending } = useEndEmployment();

  const initialValues = useMemo<LtiEndEmploymentRequest>(
    () => ({
      employmentEndedDate: new Date(),
      leaverTypes: Object.fromEntries(grants.map(({ plan }) => [plan.id, LtiGrantLeaverType.BAD_LEAVER])),
    }),
    [grants],
  );

  const handleConfirm = useCallback(
    (values: LtiEndEmploymentRequest) => {
      const activeGrants = grants.filter((grant) => isGrantActiveAtEmploymentEnd(grant, values.employmentEndedDate));

      mutate(
        {
          userId: user.id,
          employmentEndedDate: values.employmentEndedDate,
          leaverTypes: Object.fromEntries(activeGrants.map(({ plan }) => [plan.id, values.leaverTypes[plan.id]])),
        },
        {
          onSuccess: () => {
            setModalOpenFalse();
            onEmploymentEnd?.();
          },
        },
      );
    },
    [grants, mutate, setModalOpenFalse, user, onEmploymentEnd],
  );

  if (user.employmentEndedAt) {
    return <LtiEndEmploymentWidgetText user={user} />;
  }

  return (
    <Fragment>
      <Button
        disabled={!grants.length}
        variant="light"
        onClick={setModalOpenTrue}
      >
        <FormattedMessage defaultMessage="End employment" />
      </Button>

      <Modal
        isOpen={isModalOpen}
        onClose={setModalOpenFalse}
      >
        <FormikForm<LtiEndEmploymentRequest>
          enableReinitialize
          initialValues={initialValues}
          validationSchema={ltiEndEmploymentRequestSchema}
          onSubmit={handleConfirm}
        >
          <LtiEndEmploymentWidgetForm
            grants={grants}
            isPending={isPending}
          />
        </FormikForm>
      </Modal>
    </Fragment>
  );
});