Ctrl K
ComunidadGuías…

components/SortSelector.tsx

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
'use client';

import { useRouter } from 'next/navigation';
import { useTranslations } from 'next-intl';
import { useTransition } from 'react';
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { Button } from '@/components/ui/button';
import { ArrowsUpDownIcon, CheckIcon } from '@heroicons/react/24/outline';
import { cn } from '@/lib/utils';

const sortOptions = [
  { labelKey: 'sortNewestFirst', value: 'created_desc' },
  { labelKey: 'sortOldestFirst', value: 'created_asc' },
  { labelKey: 'sortRecentlyUpdated', value: 'updated_desc' },
  { labelKey: 'sortLongestUnchanged', value: 'updated_asc' },
  { labelKey: 'sortTitleAsc', value: 'title_asc' },
  { labelKey: 'sortTitleDesc', value: 'title_desc' },
  { labelKey: 'sortFavoritesFirst', value: 'favorite_desc' },
];

type SortSelectorProps = {
  sortingParam?: string;
  namespace: string;
  basePath: string;
  onSortChange: (sort: string) => Promise<unknown>;
};

export default function SortSelector({
  sortingParam,
  namespace,
  basePath,
  onSortChange,
}: SortSelectorProps) {
  const t = useTranslations(namespace);
  const router = useRouter();
  const [isPending, startTransition] = useTransition();
  const currentSort = sortingParam || 'created_desc';
  const currentLabel =
    t(sortOptions.find((opt) => opt.value === currentSort)?.labelKey || 'sort');

  const handleSort = async (sort: string) => {
    if (sort === currentSort) return;

    startTransition(async () => {
      await onSortChange(sort);
      router.push(`${basePath}?sort=${sort}`, { scroll: false });
    });
  };

  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <Button
          variant="outline"
          className={cn(
            'h-12 w-12 sm:w-auto rounded-xl px-0 sm:px-4 gap-2 bg-background/50 backdrop-blur-sm border-border hover:bg-muted transition-all shrink-0 font-bold text-[10px] uppercase tracking-widest shadow-sm',
            isPending && 'animate-pulse',
          )}
        >
          <ArrowsUpDownIcon className="h-4 w-4 text-foreground/70 shrink-0" />
          <span className="hidden sm:inline">
            {currentLabel}
          </span>
        </Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent
        align="end"
        className="w-56 rounded-2xl p-2 shadow-2xl border-primary/5"
      >
        {sortOptions.map((option) => (
          <DropdownMenuItem
            key={option.value}
            onClick={() => handleSort(option.value)}
            className={cn(
              'rounded-xl flex items-center justify-between py-2 cursor-pointer focus:bg-primary/5',
              currentSort === option.value &&
                'bg-primary/5 text-primary font-bold',
            )}
          >
            <span className="text-sm">{t(option.labelKey)}</span>
            {currentSort === option.value && <CheckIcon className="h-4 w-4" />}
          </DropdownMenuItem>
        ))}
      </DropdownMenuContent>
    </DropdownMenu>
  );
}