Repository: freeCodeCamp/freeCodeCamp
File: client/src/components/settings/certification.tsx (TypeScript)

Code before:
          </li>
          <li>{t('certification.title.Front End Development Libraries')}</li>
          <li>{t('certification.title.Data Visualization')}</li>
          <li>{t('certification.title.Back End Development and APIs')}</li>
          <li>
            {t(
              'certification.title.Legacy Information Security and Quality Assurance'
            )}
          </li>
        </ul>
      </div>

      <div>
        {fullStackClaimable ? (
          <Button
            size='small'
            block={true}
            href={certLocation}
            id={'button-' + certSlug}
            // This floating promise is acceptable
            onClick={void createClickHandler(certSlug)}
            target='_blank'
          >
            {isFullStackCert ? t('buttons.show-cert') : t('buttons.claim-cert')}
          </Button>
        ) : (
          <Button
            size='small'
            block={true}
            disabled={true}
            id={'button-' + certSlug}
            target='_blank'
          >
            {t('buttons.claim-cert')}
          </Button>
        )}
      </div>
      <Spacer size='medium' />
    </FullWidthRow>
  );
};

function CertificationSettings(props: CertificationSettingsProps) {
  const [projectTitle, setProjectTitle] = useState('');
  const [challengeFiles, setChallengeFiles] = useState<
    CompletedChallenge['challengeFiles'] | null
  >(null);
  const [challengeData, setChallengeData] = useState<CompletedChallenge | null>(
    null
  );
  const [solution, setSolution] = useState<string | null>();

Review comment (performance):
ESLint complained as `createClickHandler()` returns a promise but we don't handle it (line 190). This floating promise is acceptable, I think, so I added the `void` keyword before the function call.

https://github.com/freeCodeCamp/freeCodeCamp/blob/575aa172ad2c4db55a02a42ebf5206a1e6759ac8/client/src/components/settings/certification.tsx#L185-L195

I'm keeping this as-is to avoid scope creep, but I personally would refactor this and split the button into two as we are trying to use a single button for 2 different cases: 
1. As a link if the user already claimed the cert
2. As a button if the user hasn't claimed the cert

This adds complexity to `createClickHandler()` as the function has to perform programmatic navigation, which is redundant for a link element and causes the floating promise issue. 

There could also be some accessibility issues here as the button is rendered as a link but we don't guarantee that the user will be directed to the link destination, and this could be disoriented for non-sighted users. One scenario I can think of is:
- The user has not claimed the cert
- The user clicks the Claim cert button (screen readers will announce this as a link to non-sighted users)
- The verify cert action is triggered, but for some reason the process isn't successful
- The user doesn't get directed to the cert page

---
I'll cut an issue for further discussion.

Code after:
        <ul>
          <li>{t('certification.title.Responsive Web Design')}</li>
          <li>
            {t('certification.title.JavaScript Algorithms and Data Structures')}
          </li>
          <li>{t('certification.title.Front End Development Libraries')}</li>
          <li>{t('certification.title.Data Visualization')}</li>
          <li>{t('certification.title.Back End Development and APIs')}</li>
          <li>
            {t(
              'certification.title.Legacy Information Security and Quality Assurance'
            )}
          </li>
        </ul>
      </div>

      <div>
        {fullStackClaimable ? (
          <Button
            size='small'
            variant='primary'
            block={true}
            href={certLocation}
            id={'button-' + certSlug}
            // This floating promise is acceptable
            onClick={void createClickHandler(certSlug)}
            target='_blank'
          >
            {isFullStackCert ? t('buttons.show-cert') : t('buttons.claim-cert')}
          </Button>
        ) : (
          <Button
            size='small'
            variant='primary'
            block={true}
            disabled={true}
            id={'button-' + certSlug}
          >
            {t('buttons.claim-cert')}
          </Button>
        )}
      </div>
      <Spacer size='medium' />
    </FullWidthRow>
  );
};

function CertificationSettings(props: CertificationSettingsProps) {
  const [projectTitle, setProjectTitle] = useState('');
  const [challengeFiles, setChallengeFiles] = useState<
    CompletedChallenge['challengeFiles'] | null