diff --git a/components/contexts/FactoryProvider/index.tsx b/components/contexts/FactoryProvider/index.tsx new file mode 100644 index 0000000..0bd05bf --- /dev/null +++ b/components/contexts/FactoryProvider/index.tsx @@ -0,0 +1,61 @@ +import { createContext, FC, useContext, useMemo } from 'react' +import { EnrichedEntity } from '../../../src/types' +import { ReactNodeLike } from 'prop-types' +import { factories } from './prepare' +import { useLocale } from '../../../src/hooks/useLocale' +import de from '../../../res/translation-de.json' +import nl from '../../../res/translation-nl.json' +import { Dict } from '../../../src/types' + +const factoryNames: Record<'de' | 'nl', Dict> = { + de, + nl +} + +interface Props { + children: ReactNodeLike +} + +interface FactoryContextType { + factories: EnrichedEntity[] + findFactory(uid: string): EnrichedEntity | undefined +} + +const defaultValues: FactoryContextType = { + factories: [], + findFactory() { + return undefined + } +} + +const FactoryContext = createContext(defaultValues) +export const useFactories = () => useContext(FactoryContext) + +export const FactoryProvider: FC = ({ children }) => { + const locale = useLocale() + const internationalizedFactories = useMemo(() => { + if (locale !== 'en') + factories.map( + factory => (factory.name = factoryNames[locale]?.[factory.href] ?? factory.name) + ) + return factories + }, [locale]) + + const findFactory = useMemo(() => { + const detailsMap = Object.fromEntries( + factories.map((detail: EnrichedEntity) => [detail.href, detail]) + ) + return (uid: string): EnrichedEntity | undefined => { + return detailsMap[uid] + } + }, []) + + const value: FactoryContextType = useMemo( + () => ({ + factories: internationalizedFactories, + findFactory + }), + [findFactory, internationalizedFactories] + ) + return {children} +} diff --git a/src/hooks/useFactories.ts b/components/contexts/FactoryProvider/prepare.ts similarity index 52% rename from src/hooks/useFactories.ts rename to components/contexts/FactoryProvider/prepare.ts index 0946b60..937e5d7 100644 --- a/src/hooks/useFactories.ts +++ b/components/contexts/FactoryProvider/prepare.ts @@ -1,7 +1,7 @@ -import { EnrichedEntity, Entity } from '../types' -import details from '../../res/details.json' -import manual from '../../res/manual.json' -import exclude from '../../res/exclude.json' +import { EnrichedEntity, Entity } from '../../../src/types' +import details from '../../../res/details.json' +import manual from '../../../res/manual.json' +import exclude from '../../../res/exclude.json' const manualEntities = manual as Entity[] const manualKeys = new Set(manualEntities.map(entity => entity.href)) @@ -9,7 +9,7 @@ const detailEntities = (details as Entity[]).filter(detail => !manualKeys.has(de const joined = [...detailEntities, ...manualEntities] -const factories = joined +export const factories = joined .map((detail: EnrichedEntity) => { detail.usedBy = joined.filter(f => Object.keys(f.recipe?.prerequisites ?? {}).includes(detail.href) @@ -17,14 +17,3 @@ const factories = joined return detail }) .filter(detail => !(exclude as string[]).includes(detail.href)) - -const detailsMap = Object.fromEntries( - factories.map((detail: EnrichedEntity) => [detail.href, detail]) -) - -export const useFactories = () => ({ - factories, - findFactory: (uid: string): EnrichedEntity | undefined => { - return detailsMap[uid] - } -}) diff --git a/components/home/EntityIcon/EntityIcon.tsx b/components/home/EntityIcon/EntityIcon.tsx index 8be093a..b7cc3b6 100644 --- a/components/home/EntityIcon/EntityIcon.tsx +++ b/components/home/EntityIcon/EntityIcon.tsx @@ -1,8 +1,8 @@ import { FC, HTMLProps, useMemo } from 'react' import { Entity } from '../../../src/types' -import { useFactories } from '../../../src/hooks/useFactories' import styles from './EntityIcon.module.css' import cx from 'classnames' +import { useFactories } from '../../contexts/FactoryProvider' interface Props extends Omit, 'value'> { value: Entity | string diff --git a/components/home/EntitySpan/EntitySpan.tsx b/components/home/EntitySpan/EntitySpan.tsx index 2be29ea..d846771 100644 --- a/components/home/EntitySpan/EntitySpan.tsx +++ b/components/home/EntitySpan/EntitySpan.tsx @@ -1,11 +1,11 @@ import { FC, HTMLProps, memo, useMemo } from 'react' import { EnrichedEntity } from '../../../src/types' -import { useFactories } from '../../../src/hooks/useFactories' import styles from './EntitySpan.module.css' import { RecipeSpan } from '../Recipe/Recipe' import { LeftClickIcon } from '../LeftClickIcon/LeftClickIcon' import cx from 'classnames' import { EntityIcon } from '../EntityIcon/EntityIcon' +import { useFactories } from '../../contexts/FactoryProvider' interface Props extends Omit, 'value'> { value: EnrichedEntity | string diff --git a/components/home/FactorySelect/FactorySelect.tsx b/components/home/FactorySelect/FactorySelect.tsx index 53361dc..fc03377 100644 --- a/components/home/FactorySelect/FactorySelect.tsx +++ b/components/home/FactorySelect/FactorySelect.tsx @@ -2,8 +2,8 @@ import { FC, memo, useCallback, useEffect, useMemo } from 'react' import Select, { ActionMeta, CSSObjectWithLabel } from 'react-select' import { isNonNullable } from '../../../src/utils' import styles from './FactorySelect.module.css' -import { useFactories } from '../../../src/hooks/useFactories' import { EntitySpan } from '../EntitySpan/EntitySpan' +import { useFactories } from '../../contexts/FactoryProvider' interface Props { id: string diff --git a/components/home/GroupBox/GroupBox.tsx b/components/home/GroupBox/GroupBox.tsx index 76007d0..909811e 100644 --- a/components/home/GroupBox/GroupBox.tsx +++ b/components/home/GroupBox/GroupBox.tsx @@ -1,6 +1,5 @@ import { FC, memo, useCallback, useMemo, useState } from 'react' import { FactorySelect } from '../FactorySelect/FactorySelect' -import { useFactories } from '../../../src/hooks/useFactories' import { EnrichedEntity, Group } from '../../../src/types' import styles from './GroupBox.module.css' import { EntitySpan } from '../EntitySpan/EntitySpan' @@ -9,6 +8,7 @@ import { calculateInputs } from '../../../src/calculateInputs' import { fixedEncodeURIComponent, uniquify } from '../../../src/utils' import Link from 'next/link' import { useRouter } from 'next/router' +import { useFactories } from '../../contexts/FactoryProvider' interface Props { group: Group diff --git a/components/home/Home.tsx b/components/home/Home.tsx index 8f964f1..68ad9e7 100644 --- a/components/home/Home.tsx +++ b/components/home/Home.tsx @@ -1,7 +1,6 @@ import { FC, useMemo, useRef, useState } from 'react' import { GroupBox } from './GroupBox/GroupBox' import styles from './Home.module.css' -import { useFactories } from '../../src/hooks/useFactories' import { EnrichedEntity } from '../../src/types' import { EntitySpan } from './EntitySpan/EntitySpan' import { useGroups } from '../contexts/GroupProvider' @@ -10,6 +9,7 @@ import { download, streamToArrayBuffer } from '../../src/download' import Link from 'next/link' import { useRouter } from 'next/router' import { I18n } from '../shared/I18n/I18n' +import { useFactories } from '../contexts/FactoryProvider' export const Home: FC = () => { const { query } = useRouter() diff --git a/components/visualize/PageDetails.tsx b/components/visualize/PageDetails.tsx index 1b6711f..7fbb623 100644 --- a/components/visualize/PageDetails.tsx +++ b/components/visualize/PageDetails.tsx @@ -1,6 +1,5 @@ import { useRouter } from 'next/router' import { useGroups } from '../contexts/GroupProvider' -import { useFactories } from '../../src/hooks/useFactories' import { FC, useMemo } from 'react' import { calculateInputs } from '../../src/calculateInputs' import { DetailGraphNode, NodeDetails } from './NodeDetails/NodeDetails' @@ -9,6 +8,7 @@ import { EnrichedEntity } from '../../src/types' import Head from 'next/head' import { ScrollContainer } from './ScrollContainer/ScrollContainer' import { ProducingGraph } from './ProducingGraph/ProducingGraph' +import { useFactories } from '../contexts/FactoryProvider' export const PageDetails: FC = () => { const { diff --git a/components/visualize/PageOverview.tsx b/components/visualize/PageOverview.tsx index c56ea79..24b9a3f 100644 --- a/components/visualize/PageOverview.tsx +++ b/components/visualize/PageOverview.tsx @@ -1,11 +1,11 @@ import { useGroups } from '../contexts/GroupProvider' -import { useFactories } from '../../src/hooks/useFactories' import { FC, useMemo } from 'react' import { calculateInputs } from '../../src/calculateInputs' import Head from 'next/head' import { ScrollContainer } from './ScrollContainer/ScrollContainer' import { ProducingGraph } from './ProducingGraph/ProducingGraph' import { NodeOverview, OverviewGraphNode } from './NodeOverview/NodeOverview' +import { useFactories } from '../contexts/FactoryProvider' export const PageOverview: FC = () => { const { exportedFactories, baseFactories, groups } = useGroups() diff --git a/pages/_app.tsx b/pages/_app.tsx index 8b6eeaa..309d87f 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -5,17 +5,21 @@ import Head from 'next/head' import { useRouter } from 'next/router' import { IntlProvider } from 'react-intl' import { useMessages } from '../src/i18n' +import { FactoryProvider } from '../components/contexts/FactoryProvider' +import { useLocale } from '../src/hooks/useLocale' const MyApp: FC = ({ Component, pageProps }) => { - const { basePath, locale: _locale } = useRouter() + const { basePath } = useRouter() const messages = useMessages() - const locale = _locale ?? '' in messages ? (_locale as keyof typeof messages) : 'en' + const locale = useLocale() return ( - - - - + + + + + + ) } diff --git a/src/hooks/useLocale.ts b/src/hooks/useLocale.ts new file mode 100644 index 0000000..5a79a0f --- /dev/null +++ b/src/hooks/useLocale.ts @@ -0,0 +1,8 @@ +import { useRouter } from 'next/router' +import { useMessages } from '../i18n' + +export const useLocale = () => { + const { locale: _locale } = useRouter() + const messages = useMessages() + return _locale ?? '' in messages ? (_locale as keyof typeof messages) : 'en' +}