ldc-groupe/resources/ts/back/Components/Layout/AppSettings.tsx
2026-02-12 16:13:54 +01:00

159 lines
6.3 KiB
TypeScript

// * Packages
import { SettingsIcon, MoonIcon, SunIcon } from "lucide-react";
import { route } from "ziggy-js";
import { FormEvent } from "react";
import { useForm, usePage } from "@inertiajs/react";
// * Components shadcn
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
// * Other
import { AppEnv, Theme } from "@/back/types/global";
import { useTheme } from "@/back/providers/ThemeProvider";
import useTrans from "@/hooks/use-translations";
import { cn, GetTranslation } from "@/lib/utils";
type AppSettingsProps = {
className?: string;
};
export default function AppSettings({ className = "" }: AppSettingsProps) {
const { locale, locales } = usePage().props.appEnv as AppEnv;
const { setTheme, theme } = useTheme();
const { post, setData } = useForm({
lang: "system",
});
const submit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
post(route(`back.lang.set`));
};
const mods = [
{
name: useTrans("back.light"),
theme: "light",
icon: SunIcon,
},
{
name: useTrans("back.dark"),
theme: "dark",
icon: MoonIcon,
},
];
const languages = [
{
name: useTrans("Français"),
locale: "fr",
flag: "fr",
},
{
name: useTrans("English"),
locale: "en",
flag: "us",
},
{
name: useTrans("Spain"),
locale: "es",
flag: "es",
},
{
name: useTrans("Germany"),
locale: "de",
flag: "de",
},
];
const allowedLocales = languages.filter((language) =>
locales.includes(language.locale),
);
return (
<div className={cn(className)}>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button className="text-muted-foreground" variant="ghost">
<SettingsIcon className="h-[1.2rem] w-[1.2rem]" />
<span className="hidden lg:block">
{GetTranslation("back.settings")}
</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent side="bottom" className="w-fit me-1">
<p className="text-center text-muted-foreground text-sm font-medium leading-7">
{GetTranslation("back.mods")}
</p>
<div className="flex flex-row justify-center items-center gap-1">
{mods.map((mod) => {
return (
<DropdownMenuItem
key={mod.name}
className="p-0"
onSelect={(e) => e.preventDefault()}
>
<Button
className={cn("w-full", {
"bg-secondary": theme === mod.theme,
})}
variant="ghost"
onClick={() =>
setTheme(mod.theme as Theme)
}
>
<mod.icon />
{GetTranslation(mod.name)}
</Button>
</DropdownMenuItem>
);
})}
</div>
{allowedLocales.length > 1 && (
<>
<DropdownMenuSeparator />
<p className="text-center text-muted-foreground text-sm font-medium leading-7">
{GetTranslation("back.languages")}
</p>
<form
className="grid grid-cols-2 justify-center items-center gap-1"
onSubmit={submit}
>
{allowedLocales.map((language) => {
return (
<DropdownMenuItem
key={language.name}
className="p-0"
onSelect={(e) => e.preventDefault()}
>
<Button
className={cn("w-full", {
"bg-secondary":
locale ===
language.locale,
})}
variant="ghost"
type="submit"
onClick={() => {
setData(
"lang",
language.locale,
);
}}
>
<span
className={`fi fi-${language.flag}`}
/>
{language.name}
</Button>
</DropdownMenuItem>
);
})}
</form>
</>
)}
</DropdownMenuContent>
</DropdownMenu>
</div>
);
}