~3,470 new keys (5,770 total, EN=ES), ~115 more files wired. - nav + chromeUi: header, More menu, burger menu, footer, map toolbar widgets (sort/trust/weather), spot-type label helper. - placesUi: events, shops, tours, food. socialUi: crews, DMs, notifications, collectives, crew chat/coordinator. settingsUi: settings, auth/signup, onboarding, profile edit, legal. walletUi: wallet/Cashu, stash, mints, app shop, newsletter, community stats, leaderboards, profile. - Fixed 738 usages where an agent dropped the socialUi. prefix (caught by check:i18n).
103 lines
2.9 KiB
TypeScript
103 lines
2.9 KiB
TypeScript
import { ArrowUpDown, Clock, TrendingUp, MapPin, Zap, Shield } from 'lucide-react';
|
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
|
import { cn } from '@/lib/utils';
|
|
import { useTranslation } from '@/contexts/language';
|
|
|
|
export type SortOption =
|
|
| 'recent'
|
|
| 'trust'
|
|
| 'proximity'
|
|
| 'popular'
|
|
| 'zaps';
|
|
|
|
interface SortDropdownProps {
|
|
value: SortOption;
|
|
onChange: (value: SortOption) => void;
|
|
className?: string;
|
|
showProximity?: boolean; // Only show if geolocation available
|
|
contentType?: 'spots' | 'events' | 'coaches' | 'generic';
|
|
}
|
|
|
|
const SORT_OPTIONS = {
|
|
recent: {
|
|
labelKey: 'chromeUi.sort.recent',
|
|
descKey: 'chromeUi.sort.recentDesc',
|
|
icon: Clock,
|
|
},
|
|
trust: {
|
|
labelKey: 'chromeUi.sort.trust',
|
|
descKey: 'chromeUi.sort.trustDesc',
|
|
icon: Shield,
|
|
},
|
|
proximity: {
|
|
labelKey: 'chromeUi.sort.proximity',
|
|
descKey: 'chromeUi.sort.proximityDesc',
|
|
icon: MapPin,
|
|
},
|
|
popular: {
|
|
labelKey: 'chromeUi.sort.popular',
|
|
descKey: 'chromeUi.sort.popularDesc',
|
|
icon: TrendingUp,
|
|
},
|
|
zaps: {
|
|
labelKey: 'chromeUi.sort.zaps',
|
|
descKey: 'chromeUi.sort.zapsDesc',
|
|
icon: Zap,
|
|
},
|
|
};
|
|
|
|
export function SortDropdown({
|
|
value,
|
|
onChange,
|
|
className,
|
|
showProximity = false,
|
|
}: SortDropdownProps) {
|
|
const { t } = useTranslation();
|
|
const selectedOption = SORT_OPTIONS[value];
|
|
const Icon = selectedOption.icon;
|
|
|
|
// Determine which sort options to show based on content type
|
|
const availableOptions: SortOption[] = ['recent', 'trust'];
|
|
|
|
if (showProximity) {
|
|
availableOptions.push('proximity');
|
|
}
|
|
|
|
// Popular sorting available for all content types
|
|
availableOptions.push('popular');
|
|
|
|
// Zaps available for all content
|
|
availableOptions.push('zaps');
|
|
|
|
return (
|
|
<Select value={value} onValueChange={(v) => onChange(v as SortOption)}>
|
|
<SelectTrigger className={cn("w-[200px] gap-2", className)}>
|
|
<ArrowUpDown className="h-4 w-4 text-muted-foreground" />
|
|
<SelectValue>
|
|
<span className="flex items-center gap-2">
|
|
<Icon className="h-4 w-4" />
|
|
{t(selectedOption.labelKey)}
|
|
</span>
|
|
</SelectValue>
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{availableOptions.map((option) => {
|
|
const opt = SORT_OPTIONS[option];
|
|
const OptionIcon = opt.icon;
|
|
|
|
return (
|
|
<SelectItem key={option} value={option}>
|
|
<div className="flex items-center gap-2 w-full">
|
|
<OptionIcon className="h-4 w-4 text-muted-foreground" />
|
|
<div className="flex-1">
|
|
<div className="font-medium">{t(opt.labelKey)}</div>
|
|
<div className="text-xs text-muted-foreground">{t(opt.descKey)}</div>
|
|
</div>
|
|
</div>
|
|
</SelectItem>
|
|
);
|
|
})}
|
|
</SelectContent>
|
|
</Select>
|
|
);
|
|
}
|