tutorbookapp/tutorbook

View on GitHub
lib/intl/utils.ts

Summary

Maintainability
A
0 mins
Test Coverage
import { ObjectWithObjectID, SearchResponse } from '@algolia/client-search';
import algoliasearch from 'algoliasearch/lite';

import { Subject } from 'lib/model/subject';
import { Option } from 'lib/model/query/base';

const algoliaId = process.env.NEXT_PUBLIC_ALGOLIA_APP_ID as string;
const algoliaKey = process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_KEY as string;

const client = algoliasearch(algoliaId, algoliaKey);
const searchIndex = client.initIndex('langs');

type LangHit = ObjectWithObjectID & {
  [key: string]: { name: string; synonyms: string[] };
};

/**
 * Converts a given array of locale codes into an array of `Option<string>`
 * that include the language's label (i.e. `en` -> `English`) by fetching the
 * labels from our Algolia search index.
 */
export async function langsToOptions(
  langs: string[],
  locale = 'en'
): Promise<Option<string>[]> {
  if (!langs.length) return [];
  const res: SearchResponse<LangHit> = await searchIndex.search('', {
    filters: langs.map((lang: string) => `objectID:${lang}`).join(' OR '),
  });
  return res.hits.map((lang: LangHit) => ({
    label: lang[locale].name,
    value: lang.objectID,
    key: lang.objectID,
  }));
}

/**
 * Converts an array of subject codes into their `Option<string>` values by
 * fetching their labels from our Algolia search index.
 * @todo Actually add i18n to subjects.
 */
export async function subjectsToOptions(
  subjects: Subject[],
  locale = 'en'
): Promise<Option<string>[]> {
  return subjects.map((subject) => ({
    label: subject.name,
    value: subject.id.toString(),
    key: subject.id.toString(),
  }));
}

export async function getSubjectLabels(
  subjects: Subject[],
  locale = 'en'
): Promise<string[]> {
  return (await subjectsToOptions(subjects, locale)).map((o) => o.label);
}

export async function getLangLabels(
  langs: string[],
  locale = 'en'
): Promise<string[]> {
  return (await langsToOptions(langs, locale)).map((o) => o.label);
}