Files
syndarix/frontend/src/app/[locale]/(authenticated)/agents/page.tsx
Felipe Cardoso 8623eb56f5 feat(agents): add sorting by sort_order and include category & display fields in agent actions
- Implemented sorting of agent types by `sort_order` in Agents page.
- Added support for category, icon, color, sort_order, typical_tasks, and collaboration_hints fields in agent creation and update actions.
2026-01-06 18:20:04 +01:00

117 lines
3.5 KiB
TypeScript

/**
* Agent Types List Page
*
* Displays a list of agent types with search, status, and category filters.
* Supports grid and list view modes with user preference persistence.
*/
'use client';
import { useState, useCallback, useMemo } from 'react';
import { useRouter } from '@/lib/i18n/routing';
import { toast } from 'sonner';
import { AgentTypeList, type ViewMode } from '@/components/agents';
import { useAgentTypes } from '@/lib/api/hooks/useAgentTypes';
import { useDebounce } from '@/lib/hooks/useDebounce';
import type { AgentTypeCategory } from '@/lib/api/types/agentTypes';
export default function AgentTypesPage() {
const router = useRouter();
// Filter state
const [searchQuery, setSearchQuery] = useState('');
const [statusFilter, setStatusFilter] = useState('all');
const [categoryFilter, setCategoryFilter] = useState('all');
const [viewMode, setViewMode] = useState<ViewMode>('grid');
// Debounce search for API calls
const debouncedSearch = useDebounce(searchQuery, 300);
// Determine is_active filter value
const isActiveFilter = useMemo(() => {
if (statusFilter === 'active') return true;
if (statusFilter === 'inactive') return false;
return undefined; // 'all' returns undefined to not filter
}, [statusFilter]);
// Determine category filter value
const categoryFilterValue = useMemo(() => {
if (categoryFilter === 'all') return undefined;
return categoryFilter as AgentTypeCategory;
}, [categoryFilter]);
// Fetch agent types
const { data, isLoading, error } = useAgentTypes({
search: debouncedSearch || undefined,
is_active: isActiveFilter,
category: categoryFilterValue,
page: 1,
limit: 50,
});
// Get filtered and sorted agent types (sort by sort_order ascending - smaller first)
const filteredAgentTypes = useMemo(() => {
if (!data?.data) return [];
return [...data.data].sort((a, b) => a.sort_order - b.sort_order);
}, [data?.data]);
// Handle navigation to agent type detail
const handleSelect = useCallback(
(id: string) => {
router.push(`/agents/${id}`);
},
[router]
);
// Handle navigation to create page
const handleCreate = useCallback(() => {
router.push('/agents/new');
}, [router]);
// Handle search change
const handleSearchChange = useCallback((query: string) => {
setSearchQuery(query);
}, []);
// Handle status filter change
const handleStatusFilterChange = useCallback((status: string) => {
setStatusFilter(status);
}, []);
// Handle category filter change
const handleCategoryFilterChange = useCallback((category: string) => {
setCategoryFilter(category);
}, []);
// Handle view mode change
const handleViewModeChange = useCallback((mode: ViewMode) => {
setViewMode(mode);
}, []);
// Show error toast if fetch fails
if (error) {
toast.error('Failed to load agent types', {
description: 'Please try again later',
});
}
return (
<div className="container mx-auto px-4 py-6">
<AgentTypeList
agentTypes={filteredAgentTypes}
isLoading={isLoading}
searchQuery={searchQuery}
onSearchChange={handleSearchChange}
statusFilter={statusFilter}
onStatusFilterChange={handleStatusFilterChange}
categoryFilter={categoryFilter}
onCategoryFilterChange={handleCategoryFilterChange}
viewMode={viewMode}
onViewModeChange={handleViewModeChange}
onSelect={handleSelect}
onCreate={handleCreate}
/>
</div>
);
}