Files
ToBePlayed-Frontend/src/components/PreferencesCard.jsx
T
lobo 3712e3905f
Build, Test & Push Frontend / quality-check (push) Successful in 40s
Build, Test & Push Frontend / docker (push) Successful in 29s
feat(nav): simplify navigation and terms (#57)
One glossary (docs/GLOSSARY.md) for all de and en texts.
Five nav items; phones get a bottom bar with labels.
Community page with following, followers, player search and stats.
The bell is the one place for notes, news and open questions.
Settings in tabs; auto-save is silent and rolls back on error.
Questions page explains itself; removed games are a library filter.
Own profile: menu link, public chip, copy link, private hint.
Points page starts with a short summary; stats use status colors.
2026-10-21 14:54:48 +02:00

80 lines
3.9 KiB
React

import {useTranslation} from 'react-i18next';
import {SlidersHorizontal} from 'lucide-react';
import {Card, CardContent, CardHeader, CardTitle} from '@/components/ui/card';
import {Label} from '@/components/ui/label';
import {Select, SelectContent, SelectItem, SelectTrigger, SelectValue} from '@/components/ui/select';
import {useCurrentUserContext} from '../context/CurrentUserContext.jsx';
import {usePreferences} from '../context/PreferencesContext.jsx';
import usePersistSettings from '../hooks/usePersistSettings.js';
import useSaveResponse from '../hooks/useSaveResponse.js';
import {FAVORITE_PLATFORMS, saveFavoritePlatform} from '../utils/platforms.js';
import {LANGUAGES} from '../utils/settings.js';
// Radix Select has no empty value.
const NO_FAVORITE = 'NONE';
export default function PreferencesCard() {
const {t, i18n} = useTranslation();
const {user: profile, updateUser: updateProfile} = useCurrentUserContext();
const {setLanguage} = usePreferences();
const persistSettings = usePersistSettings();
const runSave = useSaveResponse();
const handleLanguageChange = async (next) => {
const previous = i18n.language;
const {ok} = await persistSettings(() => setLanguage(next), {silent: true});
if (!ok) i18n.changeLanguage(previous);
};
const handleFavoritePlatformChange = async (value) => {
const platform = value === NO_FAVORITE ? null : value;
const previous = profile?.settings?.favoritePlatform ?? null;
const setPlatform = (next) => updateProfile((p) => ({...p, settings: {...p.settings, favoritePlatform: next}}));
setPlatform(platform);
if (!await runSave(() => saveFavoritePlatform(platform))) setPlatform(previous);
};
return (
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2"><SlidersHorizontal className="size-4 text-primary"/>{t('SETTINGS.PREFERENCES')}</CardTitle>
</CardHeader>
<CardContent className="space-y-6">
<div className="flex items-center justify-between gap-4">
<Label htmlFor="language">{t('SETTINGS.LANGUAGE')}</Label>
<Select value={i18n.language} onValueChange={handleLanguageChange}>
<SelectTrigger id="language" className="w-40">
<SelectValue/>
</SelectTrigger>
<SelectContent>
{LANGUAGES.map((lang) => (
<SelectItem key={lang} value={lang}>
{t(`SETTINGS.LANGUAGE_OPTIONS.${lang.toUpperCase()}`)}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className="flex items-center justify-between gap-4">
<div className="space-y-1">
<Label htmlFor="favoritePlatform">{t('SETTINGS.FAVORITE_PLATFORM')}</Label>
<p className="text-xs text-muted-foreground">{t('SETTINGS.FAVORITE_PLATFORM_HINT')}</p>
</div>
<Select value={profile?.settings?.favoritePlatform ?? NO_FAVORITE} onValueChange={handleFavoritePlatformChange}>
<SelectTrigger id="favoritePlatform" className="w-48">
<SelectValue/>
</SelectTrigger>
<SelectContent>
<SelectItem value={NO_FAVORITE}>{t('SETTINGS.FAVORITE_PLATFORM_NONE')}</SelectItem>
{FAVORITE_PLATFORMS.map((platform) => (
<SelectItem key={platform.value} value={platform.value}>{platform.label}</SelectItem>
))}
</SelectContent>
</Select>
</div>
</CardContent>
</Card>
);
}