'use client';
import { useState, useEffect } from 'react';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Textarea } from '@/components/ui/textarea';
import { Plus, Edit, Play, AlertTriangle, ShieldAlert, CheckCircle2 } from 'lucide-react';
import { numberingApi, NumberingTemplate } from '@/lib/api/numbering';
import { TemplateEditor } from '@/components/numbering/template-editor';
import { SequenceViewer } from '@/components/numbering/sequence-viewer';
import { TemplateTester } from '@/components/numbering/template-tester';
import { toast } from 'sonner';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { useProjects, useCorrespondenceTypes, useContracts, useDisciplines } from '@/hooks/use-master-data';
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
// --- Sub-components for Tools ---
function ManualOverrideForm({ onSuccess, projectId }: { onSuccess: () => void, projectId: number }) {
const [loading, setLoading] = useState(false);
const [formData, setFormData] = useState({
typeId: '',
disciplineId: '',
year: new Date().getFullYear().toString(),
newSequence: '',
reason: ''
});
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
try {
await numberingApi.manualOverride({
projectId,
correspondenceTypeId: parseInt(formData.typeId) || null,
year: parseInt(formData.year),
newValue: parseInt(formData.newSequence),
});
toast.success("Manual override applied successfully");
onSuccess();
} catch (error) {
toast.error("Failed to apply override");
} finally {
setLoading(false);
}
};
return (
Manual Override
Force set a counter sequence. Use with caution.
Warning
Changing counters manually can cause duplication errors.
)
}
function AdminMetrics() {
// Fetch metrics from /admin/document-numbering/metrics
return (
Generation Success Rate
99.9%
+0.1% from last month
{/* More cards... */}
Recent Audit Logs
Log viewer implementation pending.
)
}
export default function NumberingPage() {
const { data: projects = [] } = useProjects();
const [selectedProjectId, setSelectedProjectId] = useState("1");
const [activeTab, setActiveTab] = useState("templates");
const [templates, setTemplates] = useState([]);
const [loading, setLoading] = useState(true);
// View states
const [isEditing, setIsEditing] = useState(false);
const [activeTemplate, setActiveTemplate] = useState(undefined);
const [isTesting, setIsTesting] = useState(false);
const [testTemplate, setTestTemplate] = useState(null);
const selectedProjectName = projects.find((p: any) => p.id.toString() === selectedProjectId)?.projectName || 'Unknown Project';
// Master Data
const { data: correspondenceTypes = [] } = useCorrespondenceTypes();
const { data: contracts = [] } = useContracts(Number(selectedProjectId));
const contractId = contracts[0]?.id;
const { data: disciplines = [] } = useDisciplines(contractId);
const loadTemplates = async () => {
setLoading(true);
try {
const response = await numberingApi.getTemplates();
// Handle wrapped response { data: [...] } or direct array
const data = Array.isArray(response) ? response : (response as { data?: NumberingTemplate[] })?.data ?? [];
setTemplates(data);
} catch {
toast.error("Failed to load templates");
setTemplates([]);
} finally {
setLoading(false);
}
};
useEffect(() => {
loadTemplates();
}, []);
const handleEdit = (template?: NumberingTemplate) => {
setActiveTemplate(template);
setIsEditing(true);
};
const handleSave = async (data: Partial) => {
try {
await numberingApi.saveTemplate(data);
toast.success(data.id ? "Template updated" : "Template created");
setIsEditing(false);
loadTemplates();
} catch {
toast.error("Failed to save template");
}
};
const handleTest = (template: NumberingTemplate) => {
setTestTemplate(template);
setIsTesting(true);
};
if (isEditing) {
return (
setIsEditing(false)}
/>
);
}
return (
Document Numbering
Manage numbering templates, audit logs, and tools
Templates
Metrics & Audit
Admin Tools
{templates
.filter(t => !t.projectId || t.projectId === Number(selectedProjectId))
.map((template) => (
{template.correspondenceType?.typeName || 'Default Format'}
{template.project?.projectCode || selectedProjectName}
{template.description && {template.description}}
{template.formatTemplate}
Type Code:
{template.correspondenceType?.typeCode || 'DEFAULT'}
Reset:
{template.resetSequenceYearly ? 'Annually' : 'Continuous'}
))}
{}} projectId={Number(selectedProjectId)} />
Void & Replace
Safe voiding of issued numbers.
To void and replace numbers, please use the Correspondences list view actions or edit specific documents directly.
This ensures the void action is linked to the correct document record.
);
}