dej611/spid-react-button

View on GitHub
src/shared/ProviderButton.tsx

Summary

Maintainability
A
35 mins
Test Coverage
A
91%
import React, { useRef, useEffect } from 'react';

import { isGetMethod } from './utils';

import type { TranslateFn } from './i18n';
import type { RegisteredProviderRecord, SPIDButtonProps, Types } from './types';

import styles from './ProviderButton.module.css';

type ProviderButtonProps = Required<
  Pick<SPIDButtonProps, 'url' | 'mapping' | 'configuration' | 'type'>
> &
  Pick<SPIDButtonProps, 'onProviderClicked'> & {
    idp: RegisteredProviderRecord;
    isActive: boolean;
    i18n: TranslateFn;
    className: string;
    firstFocus: boolean;
  };
export const SharedProviderButton = ({
  idp,
  configuration,
  url,
  isActive,
  mapping,
  i18n,
  onProviderClicked,
  className,
  type,
  firstFocus
}: ProviderButtonProps) => {
  const idpRef = useRef<HTMLAnchorElement | HTMLButtonElement | null>(null);
  const entityID =
    idp.entityID in mapping ? mapping[idp.entityID] : idp.entityID;
  const actionURL = url.replace('{{idp}}', encodeURIComponent(entityID));
  const linkTitle = isActive
    ? i18n('accedi_con_idp', idp.entityName)
    : i18n('idp_disabled');

  const loginURL = isActive ? actionURL : undefined;

  useEffect(() => {
    if (firstFocus && idpRef.current) {
      idpRef.current.focus();
    }
  }, [idpRef]);

  if (isGetMethod(configuration)) {
    return (
      <a
        ref={(el) => (idpRef.current = el)}
        title={linkTitle}
        href={loginURL}
        // @ts-expect-error
        disabled={!isActive}
        className={type === 'modal' ? '' : className}
        onClick={(e) =>
          onProviderClicked && onProviderClicked(idp, loginURL, e)
        }
        role='link'
        id={entityID}
      >
        <ProviderButtonContent idp={idp} title={linkTitle} type={type} />
      </a>
    );
  }
  return (
    <form name='spid_idp_access' action={actionURL} method='POST'>
      <button
        ref={(el) => (idpRef.current = el)}
        className={className}
        id={entityID}
        name={linkTitle}
        title={linkTitle}
        type='submit'
        onClick={(e) => {
          if (!isActive) {
            e.preventDefault();
          }
          return onProviderClicked && onProviderClicked(idp, loginURL, e);
        }}
        disabled={!isActive}
      >
        <ProviderButtonContent idp={idp} title={linkTitle} type={type} />
      </button>
      <input type='hidden' name={configuration.fieldName} value={entityID} />
      {Object.entries(configuration.extraFields || {}).map(
        ([inputName, inputValue]) => {
          return (
            <input
              key={inputName}
              type='hidden'
              name={inputName}
              value={inputValue}
            />
          );
        }
      )}
    </form>
  );
};

const ProviderButtonContent = ({
  idp,
  title,
  type
}: {
  idp: RegisteredProviderRecord;
  title: string;
  type: Types;
}) => {
  if (idp.logo == null) {
    return <span>{idp.entityName}</span>;
  }
  return (
    <span>
      <span className={styles.srOnly}>{title}</span>
      <img
        src={idp.logo}
        alt={idp.entityName}
        title={idp.entityName}
        style={type === 'modal' ? { maxWidth: '90%' } : {}}
      />
    </span>
  );
};