Add 'activeLocale'
This change tracks the "active locale" in memory, and when the language is changed a re-render occurs. After this change, the URL does not change in the process of changing language
This commit is contained in:
parent
a03dcae2d7
commit
e802d6ef19
3 changed files with 40 additions and 30 deletions
|
@ -2,32 +2,40 @@ import { Quran, TLocale } from "Quran";
|
||||||
import { Select } from "~/components/Select";
|
import { Select } from "~/components/Select";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
locale: TLocale;
|
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
setIsOpen: (v: boolean) => void;
|
setIsOpen: (v: boolean) => void;
|
||||||
|
activeLocale: TLocale;
|
||||||
|
setActiveLocale: (v: TLocale) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function LanguageSelect({ locale, isOpen, setIsOpen }: Props) {
|
export function LanguageSelect({
|
||||||
|
isOpen,
|
||||||
|
setIsOpen,
|
||||||
|
activeLocale,
|
||||||
|
setActiveLocale,
|
||||||
|
}: Props) {
|
||||||
const locales = Object.values(Quran.locales);
|
const locales = Object.values(Quran.locales);
|
||||||
return (
|
return (
|
||||||
<Select
|
<Select
|
||||||
value={locale.name}
|
value={activeLocale.name}
|
||||||
className="language-select w-20"
|
className="language-select w-20"
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
setIsOpen={setIsOpen}
|
setIsOpen={setIsOpen}
|
||||||
>
|
>
|
||||||
{locales.map((l: TLocale, i: number) => {
|
{locales.map((l: TLocale, i: number) => {
|
||||||
const href = `/${l.name}`;
|
|
||||||
return (
|
return (
|
||||||
<Select.Option
|
<Select.Option
|
||||||
key={i}
|
key={i}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"flex h-5 text-sm w-full items-center justify-center no-underline mb-1 rounded",
|
"flex h-5 text-sm w-full items-center justify-center no-underline mb-1 rounded",
|
||||||
l.direction,
|
l.direction,
|
||||||
l.name === locale.name ? "active" : undefined,
|
l.name === activeLocale.name ? "active" : undefined,
|
||||||
)}
|
)}
|
||||||
value={l.name}
|
value={l.name}
|
||||||
href={l.name === locale.name ? undefined : href}
|
onClick={(e: React.ChangeEvent) => [
|
||||||
|
e.preventDefault(),
|
||||||
|
setActiveLocale(l),
|
||||||
|
]}
|
||||||
>
|
>
|
||||||
{l.displayName}
|
{l.displayName}
|
||||||
</Select.Option>
|
</Select.Option>
|
||||||
|
|
|
@ -4,20 +4,22 @@ import { formatNumber, TFunction } from "~/lib/t";
|
||||||
import { Arrow } from "~/components/Icon";
|
import { Arrow } from "~/components/Icon";
|
||||||
import { Head } from "~/components/Head";
|
import { Head } from "~/components/Head";
|
||||||
import { LanguageSelect, ThemeSelect } from "~/components/Select";
|
import { LanguageSelect, ThemeSelect } from "~/components/Select";
|
||||||
import { Filter } from "./Filter";
|
|
||||||
import "@css/main/SurahIndex.scss";
|
import "@css/main/SurahIndex.scss";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
locale: TLocale;
|
locale: TLocale;
|
||||||
surahs: Surah[];
|
surahs: Record<"string", Surah[]>;
|
||||||
t: TFunction;
|
t: TFunction;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function SurahIndex({ locale, surahs, t }: Props) {
|
export function SurahIndex({ locale, surahs, t }: Props) {
|
||||||
|
const [activeLocale, setActiveLocale] = useState<TLocale>(locale);
|
||||||
|
const index = surahs[activeLocale.name];
|
||||||
|
|
||||||
const [theme, setTheme] = useTheme();
|
const [theme, setTheme] = useTheme();
|
||||||
const [index, setIndex] = useState<Surah[]>(surahs);
|
|
||||||
const [showLangDropdown, setShowLangDropdown] = useState<boolean>(false);
|
const [showLangDropdown, setShowLangDropdown] = useState<boolean>(false);
|
||||||
const [showThemeDropdown, setShowThemeDropdown] = useState<boolean>(false);
|
const [showThemeDropdown, setShowThemeDropdown] = useState<boolean>(false);
|
||||||
|
|
||||||
const rootRef = useRef<HTMLDivElement>(null);
|
const rootRef = useRef<HTMLDivElement>(null);
|
||||||
const activeEl = useMemo(
|
const activeEl = useMemo(
|
||||||
() => document.activeElement,
|
() => document.activeElement,
|
||||||
|
@ -42,15 +44,16 @@ export function SurahIndex({ locale, surahs, t }: Props) {
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"flex flex-col h-full content surah-index theme",
|
"flex flex-col h-full content surah-index theme",
|
||||||
theme,
|
theme,
|
||||||
locale.name,
|
activeLocale.name,
|
||||||
locale.direction,
|
activeLocale.direction,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Head title={t(locale, "TheNobleQuran")} locale={locale}>
|
<Head title={t(activeLocale, "TheNobleQuran")} locale={activeLocale}>
|
||||||
<LanguageSelect
|
<LanguageSelect
|
||||||
isOpen={showLangDropdown}
|
isOpen={showLangDropdown}
|
||||||
setIsOpen={setShowLangDropdown}
|
setIsOpen={setShowLangDropdown}
|
||||||
locale={locale}
|
locale={activeLocale}
|
||||||
|
setActiveLocale={setActiveLocale}
|
||||||
/>
|
/>
|
||||||
<ThemeSelect
|
<ThemeSelect
|
||||||
isOpen={showThemeDropdown}
|
isOpen={showThemeDropdown}
|
||||||
|
@ -63,28 +66,28 @@ export function SurahIndex({ locale, surahs, t }: Props) {
|
||||||
{index.map((surah, key) => (
|
{index.map((surah, key) => (
|
||||||
<li
|
<li
|
||||||
className={classNames("flex justify-center surah", {
|
className={classNames("flex justify-center surah", {
|
||||||
"w-full": locale.direction === "ltr",
|
"w-full": activeLocale.direction === "ltr",
|
||||||
"w-1/2": locale.direction === "rtl",
|
"w-1/2": activeLocale.direction === "rtl",
|
||||||
})}
|
})}
|
||||||
key={key}
|
key={key}
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
className="flex items-center color-primary no-underline rounded w-11/12 h-8"
|
className="flex items-center color-primary no-underline rounded w-11/12 h-8"
|
||||||
href={`/${locale.name}/${surah.id}/`}
|
href={`/${activeLocale.name}/${surah.id}/`}
|
||||||
>
|
>
|
||||||
<span className="background-secondary color-white rounded flex w-8 font-extrabold w-5 mr-3 justify-center text-center">
|
<span className="background-secondary color-white rounded flex w-8 font-extrabold w-5 mr-3 justify-center text-center">
|
||||||
{formatNumber(locale, surah.id)}
|
{formatNumber(activeLocale, surah.id)}
|
||||||
</span>
|
</span>
|
||||||
<span>{surah.name}</span>
|
<span>{surah.name}</span>
|
||||||
{locale.direction === "ltr" && (
|
{activeLocale.direction === "ltr" && (
|
||||||
<div className="flex justify-end grow pr-3">
|
<div className="flex justify-end grow pr-3">
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<span className="transliterated" lang="en">
|
<span className="transliterated" lang="en">
|
||||||
{surah.translitName}
|
{surah.translitName}
|
||||||
</span>
|
</span>
|
||||||
<span className="ayat flex justify-end text-sm">
|
<span className="ayat flex justify-end text-sm">
|
||||||
{formatNumber(locale, surah.numberOfAyah)}{" "}
|
{formatNumber(activeLocale, surah.numberOfAyah)}{" "}
|
||||||
{t(locale, "ayat")}
|
{t(activeLocale, "ayat")}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -96,23 +99,22 @@ export function SurahIndex({ locale, surahs, t }: Props) {
|
||||||
<footer className="flex flex-row justify-between mb-5 h-12">
|
<footer className="flex flex-row justify-between mb-5 h-12">
|
||||||
<a
|
<a
|
||||||
className="flex flex-row items-center no-underline"
|
className="flex flex-row items-center no-underline"
|
||||||
href={`/${locale.name}/random/`}
|
href={`/${activeLocale.name}/random/`}
|
||||||
>
|
>
|
||||||
{locale.direction === "ltr" ? (
|
{activeLocale.direction === "ltr" ? (
|
||||||
<Arrow direction="right" />
|
<Arrow direction="right" />
|
||||||
) : (
|
) : (
|
||||||
<Arrow direction="left" />
|
<Arrow direction="left" />
|
||||||
)}
|
)}
|
||||||
<span
|
<span
|
||||||
className={classNames({
|
className={classNames({
|
||||||
"pl-3": locale.direction === "ltr",
|
"pl-3": activeLocale.direction === "ltr",
|
||||||
"pr-3": locale.direction === "rtl",
|
"pr-3": activeLocale.direction === "rtl",
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{t(locale, "ChooseRandomChapter")}
|
{t(activeLocale, "ChooseRandomChapter")}
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
<Filter t={t} locale={locale} surahs={surahs} setIndex={setIndex} />
|
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -30,25 +30,25 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||||
<SurahIndex
|
<SurahIndex
|
||||||
path="/"
|
path="/"
|
||||||
locale={Quran.locales["en"]}
|
locale={Quran.locales["en"]}
|
||||||
surahs={Quran.surahs["en"]}
|
surahs={Quran.surahs}
|
||||||
t={t}
|
t={t}
|
||||||
/>
|
/>
|
||||||
<SurahIndex
|
<SurahIndex
|
||||||
path="/en"
|
path="/en"
|
||||||
locale={Quran.locales["en"]}
|
locale={Quran.locales["en"]}
|
||||||
surahs={Quran.surahs["en"]}
|
surahs={Quran.surahs}
|
||||||
t={t}
|
t={t}
|
||||||
/>
|
/>
|
||||||
<SurahIndex
|
<SurahIndex
|
||||||
path="/ar"
|
path="/ar"
|
||||||
locale={Quran.locales["ar"]}
|
locale={Quran.locales["ar"]}
|
||||||
surahs={Quran.surahs["ar"]}
|
surahs={Quran.surahs}
|
||||||
t={t}
|
t={t}
|
||||||
/>
|
/>
|
||||||
<SurahIndex
|
<SurahIndex
|
||||||
path="/fa"
|
path="/fa"
|
||||||
locale={Quran.locales["fa"]}
|
locale={Quran.locales["fa"]}
|
||||||
surahs={Quran.surahs["fa"]}
|
surahs={Quran.surahs}
|
||||||
t={t}
|
t={t}
|
||||||
/>
|
/>
|
||||||
<SurahStream path="/:localeId/:surahId" t={t} />
|
<SurahStream path="/:localeId/:surahId" t={t} />
|
||||||
|
|
Loading…
Reference in a new issue