forked from cardosofelipe/fast-next-template
- 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.
206 lines
6.6 KiB
TypeScript
206 lines
6.6 KiB
TypeScript
/**
|
|
* Agent Type Detail/Edit Page
|
|
*
|
|
* Displays agent type details with options to edit, duplicate, or deactivate.
|
|
* Handles 'new' as a special ID to show the create form.
|
|
*/
|
|
|
|
'use client';
|
|
|
|
import { useCallback, useState } from 'react';
|
|
import { useParams } from 'next/navigation';
|
|
import { useRouter } from '@/lib/i18n/routing';
|
|
import { toast } from 'sonner';
|
|
import { AgentTypeDetail, AgentTypeForm } from '@/components/agents';
|
|
import {
|
|
useAgentType,
|
|
useCreateAgentType,
|
|
useUpdateAgentType,
|
|
useDeactivateAgentType,
|
|
useDuplicateAgentType,
|
|
} from '@/lib/api/hooks/useAgentTypes';
|
|
import type { AgentTypeCreateFormValues } from '@/lib/validations/agentType';
|
|
|
|
type ViewMode = 'detail' | 'edit' | 'create';
|
|
|
|
export default function AgentTypeDetailPage() {
|
|
const router = useRouter();
|
|
const params = useParams();
|
|
const id = params.id as string;
|
|
|
|
// Determine initial view mode
|
|
const isNew = id === 'new';
|
|
const [viewMode, setViewMode] = useState<ViewMode>(isNew ? 'create' : 'detail');
|
|
|
|
// Fetch agent type data (skip if creating new)
|
|
const { data: agentType, isLoading, error } = useAgentType(isNew ? null : id);
|
|
|
|
// Mutations
|
|
const createMutation = useCreateAgentType();
|
|
const updateMutation = useUpdateAgentType();
|
|
const deactivateMutation = useDeactivateAgentType();
|
|
const duplicateMutation = useDuplicateAgentType();
|
|
|
|
// Handle navigation back to list
|
|
const handleBack = useCallback(() => {
|
|
if (viewMode === 'edit') {
|
|
setViewMode('detail');
|
|
} else {
|
|
router.push('/agents');
|
|
}
|
|
}, [router, viewMode]);
|
|
|
|
// Handle edit button click
|
|
const handleEdit = useCallback(() => {
|
|
setViewMode('edit');
|
|
}, []);
|
|
|
|
// Handle form submission for create/update
|
|
const handleSubmit = useCallback(
|
|
async (data: AgentTypeCreateFormValues) => {
|
|
try {
|
|
if (isNew || viewMode === 'create') {
|
|
// Create new agent type
|
|
const result = await createMutation.mutateAsync({
|
|
name: data.name,
|
|
slug: data.slug,
|
|
description: data.description,
|
|
expertise: data.expertise,
|
|
personality_prompt: data.personality_prompt,
|
|
primary_model: data.primary_model,
|
|
fallback_models: data.fallback_models,
|
|
model_params: data.model_params,
|
|
mcp_servers: data.mcp_servers,
|
|
tool_permissions: data.tool_permissions,
|
|
is_active: data.is_active,
|
|
// Category and display fields
|
|
category: data.category,
|
|
icon: data.icon,
|
|
color: data.color,
|
|
sort_order: data.sort_order,
|
|
typical_tasks: data.typical_tasks,
|
|
collaboration_hints: data.collaboration_hints,
|
|
});
|
|
toast.success('Agent type created', {
|
|
description: `${result.name} has been created successfully`,
|
|
});
|
|
router.push(`/agents/${result.id}`);
|
|
} else {
|
|
// Update existing agent type
|
|
const result = await updateMutation.mutateAsync({
|
|
id,
|
|
data: {
|
|
name: data.name,
|
|
slug: data.slug,
|
|
description: data.description,
|
|
expertise: data.expertise,
|
|
personality_prompt: data.personality_prompt,
|
|
primary_model: data.primary_model,
|
|
fallback_models: data.fallback_models,
|
|
model_params: data.model_params,
|
|
mcp_servers: data.mcp_servers,
|
|
tool_permissions: data.tool_permissions,
|
|
is_active: data.is_active,
|
|
// Category and display fields
|
|
category: data.category,
|
|
icon: data.icon,
|
|
color: data.color,
|
|
sort_order: data.sort_order,
|
|
typical_tasks: data.typical_tasks,
|
|
collaboration_hints: data.collaboration_hints,
|
|
},
|
|
});
|
|
toast.success('Agent type updated', {
|
|
description: `${result.name} has been updated successfully`,
|
|
});
|
|
setViewMode('detail');
|
|
}
|
|
} catch (err) {
|
|
const message = err instanceof Error ? err.message : 'An error occurred';
|
|
toast.error('Failed to save agent type', { description: message });
|
|
}
|
|
},
|
|
[id, isNew, viewMode, createMutation, updateMutation, router]
|
|
);
|
|
|
|
// Handle duplicate
|
|
const handleDuplicate = useCallback(async () => {
|
|
if (!agentType) return;
|
|
|
|
try {
|
|
const result = await duplicateMutation.mutateAsync(agentType);
|
|
toast.success('Agent type duplicated', {
|
|
description: `${result.name} has been created`,
|
|
});
|
|
router.push(`/agents/${result.id}`);
|
|
} catch (err) {
|
|
const message = err instanceof Error ? err.message : 'An error occurred';
|
|
toast.error('Failed to duplicate agent type', { description: message });
|
|
}
|
|
}, [agentType, duplicateMutation, router]);
|
|
|
|
// Handle deactivate
|
|
const handleDeactivate = useCallback(async () => {
|
|
try {
|
|
await deactivateMutation.mutateAsync(id);
|
|
toast.success('Agent type deactivated', {
|
|
description: 'The agent type has been deactivated',
|
|
});
|
|
router.push('/agents');
|
|
} catch (err) {
|
|
const message = err instanceof Error ? err.message : 'An error occurred';
|
|
toast.error('Failed to deactivate agent type', { description: message });
|
|
}
|
|
}, [id, deactivateMutation, router]);
|
|
|
|
// Handle cancel from form
|
|
const handleCancel = useCallback(() => {
|
|
if (isNew) {
|
|
router.push('/agents');
|
|
} else {
|
|
setViewMode('detail');
|
|
}
|
|
}, [isNew, router]);
|
|
|
|
// Show error state
|
|
if (error && !isNew) {
|
|
return (
|
|
<div className="container mx-auto px-4 py-6">
|
|
<AgentTypeDetail
|
|
agentType={null}
|
|
onBack={handleBack}
|
|
onEdit={handleEdit}
|
|
onDuplicate={handleDuplicate}
|
|
onDeactivate={handleDeactivate}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// Render based on view mode
|
|
return (
|
|
<div className="container mx-auto px-4 py-6">
|
|
{(viewMode === 'create' || viewMode === 'edit') && (
|
|
<AgentTypeForm
|
|
agentType={viewMode === 'edit' ? (agentType ?? undefined) : undefined}
|
|
onSubmit={handleSubmit}
|
|
onCancel={handleCancel}
|
|
isSubmitting={createMutation.isPending || updateMutation.isPending}
|
|
/>
|
|
)}
|
|
|
|
{viewMode === 'detail' && (
|
|
<AgentTypeDetail
|
|
agentType={agentType ?? null}
|
|
isLoading={isLoading}
|
|
onBack={handleBack}
|
|
onEdit={handleEdit}
|
|
onDuplicate={handleDuplicate}
|
|
onDeactivate={handleDeactivate}
|
|
isDeactivating={deactivateMutation.isPending}
|
|
/>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|