Files
web/components/Common/LanguageDropdown.jsx
Husanjonazamov 64af77101f classify web
2026-02-24 12:52:49 +05:00

219 lines
7.1 KiB
JavaScript

"use client";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import {
CurrentLanguageData,
setCurrentLanguage,
} from "@/redux/reducer/languageSlice";
import { getCityData, saveCity } from "@/redux/reducer/locationSlice";
import { getIsPaidApi, settingsData } from "@/redux/reducer/settingSlice";
import { isEmptyObject, updateStickyNoteTranslations } from "@/utils";
import { getLanguageApi, getLocationApi } from "@/utils/api";
import {
setHasFetchedCategories,
setHasFetchedSystemSettings,
} from "@/utils/getFetcherStatus";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { toast } from "sonner";
import CustomImage from "./CustomImage";
const LanguageDropdown = () => {
const IsPaidApi = useSelector(getIsPaidApi);
const router = useRouter();
const dispatch = useDispatch();
const pathname = usePathname();
const location = useSelector(getCityData);
const settings = useSelector(settingsData);
const CurrentLanguage = useSelector(CurrentLanguageData);
const currentLangCode = CurrentLanguage?.code;
const languages = settings && settings?.languages;
const isRTL = CurrentLanguage.rtl;
const searchParams = useSearchParams();
const langCode = searchParams?.get("lang");
const params = new URLSearchParams(searchParams.toString());
const setDefaultLanguage = async () => {
try {
params.set("lang", settings?.default_language.toLowerCase());
router.push(`${pathname}?${params.toString()}`, { scroll: false });
const language_code = settings?.default_language;
const res = await getLanguageApi.getLanguage({
language_code,
type: "web",
});
if (res?.data?.error === false) {
dispatch(setCurrentLanguage(res?.data?.data));
document.documentElement.lang =
res?.data?.data?.code?.toLowerCase() ||
settings?.default_language.toLowerCase();
} else {
toast.error(res?.data?.message);
}
} catch (error) {
console.log(error);
}
};
useEffect(() => {
// Check if Redux language is empty or invalid
if (isEmptyObject(CurrentLanguage)) {
setDefaultLanguage();
return;
}
// If URL has lang parameter and languages are loaded, check if valid and update if needed
if (langCode && languages.length > 0) {
const urlLang = languages.find(
(lang) => lang.code?.toUpperCase() === langCode.toUpperCase()
);
if (
urlLang &&
currentLangCode?.toUpperCase() !== urlLang.code.toUpperCase()
) {
getLanguageData(urlLang.code);
return;
}
}
// Check if current language code is no longer valid (language was removed from settings)
if (languages && !languages.some((lang) => lang.code === currentLangCode)) {
setDefaultLanguage();
return;
}
if (!langCode) {
params.set("lang", currentLangCode);
router.push(`${pathname}?${params.toString()}`, { scroll: false });
}
}, [langCode]);
const getLanguageData = async (
language_code = settings?.default_language
) => {
try {
const res = await getLanguageApi.getLanguage({
language_code,
type: "web",
});
if (res?.data?.error === false) {
dispatch(setCurrentLanguage(res?.data?.data));
getLocationAfterLanguageChange(language_code);
document.documentElement.lang =
res?.data?.data?.code?.toLowerCase() || "en";
setHasFetchedSystemSettings(false);
setHasFetchedCategories(false);
updateStickyNoteTranslations();
} else {
toast.error(res?.data?.message);
}
} catch (error) {
console.log(error);
}
};
const getLocationAfterLanguageChange = async (language_code) => {
if (IsPaidApi) {
return;
}
// If no country/state/city/area stored, skip API call
if (
!location?.country &&
!location?.state &&
!location?.city &&
!location?.area
) {
return;
}
const response = await getLocationApi.getLocation({
lat: location?.lat,
lng: location?.long,
lang: language_code,
});
if (response?.data.error === false) {
const result = response?.data?.data;
const updatedLocation = {};
if (location?.country) updatedLocation.country = result?.country;
if (location?.state) updatedLocation.state = result?.state;
if (location?.city) updatedLocation.city = result?.city;
if (location?.area) {
updatedLocation.area = result?.area;
updatedLocation.areaId = result?.area_id;
}
updatedLocation.lat = location?.lat;
updatedLocation.long = location?.long;
// ✅ Dynamically build formattedAddress only with existing parts
const parts = [];
if (location?.area) parts.push(result?.area_translation);
if (location?.city) parts.push(result?.city_translation);
if (location?.state) parts.push(result?.state_translation);
if (location?.country) parts.push(result?.country_translation);
updatedLocation.address_translated = parts.filter(Boolean).join(", ");
saveCity(updatedLocation);
}
};
const handleLanguageSelect = (id) => {
const lang = languages?.find((item) => item.id === Number(id));
if (CurrentLanguage.id === lang.id) {
return;
}
params.set("lang", lang.code.toLowerCase()); // Store language code
// Push new URL with lang param
router.push(`${pathname}?${params.toString()}`, { scroll: false });
getLanguageData(lang?.code);
};
return (
<DropdownMenu>
<DropdownMenuTrigger className="border rounded-full py-2 px-4">
<div className="flex items-center gap-1">
<CustomImage
key={CurrentLanguage?.id}
src={CurrentLanguage?.image}
alt={CurrentLanguage?.name || "language"}
width={20}
height={20}
className="rounded-full"
/>
<span>{CurrentLanguage?.code}</span>
</div>
</DropdownMenuTrigger>
<DropdownMenuContent
className="min-w-0 max-h-[250px] overflow-y-auto"
align={isRTL ? "start" : "end"}
>
{languages &&
languages.map((lang) => (
<DropdownMenuItem
key={lang?.id}
onClick={() => handleLanguageSelect(lang.id)}
className="cursor-pointer"
>
<CustomImage
src={lang?.image}
alt={lang.name || "english"}
width={20}
height={20}
className="rounded-full"
/>
<span>{lang.code}</span>
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
);
};
export default LanguageDropdown;