121 lines
5.8 KiB
TypeScript
121 lines
5.8 KiB
TypeScript
import React, { useState, useEffect } from 'react';
|
|
import { API } from '../../api/API';
|
|
import { toast } from 'sonner';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import { Plus, Edit2, Calendar, CheckCircle, XCircle } from 'lucide-react';
|
|
import { format } from 'date-fns';
|
|
|
|
interface QuestionnaireVersion {
|
|
id: string;
|
|
version: string;
|
|
isActive: boolean;
|
|
createdAt: string;
|
|
}
|
|
|
|
const QuestionnaireList: React.FC = () => {
|
|
const [versions, setVersions] = useState<QuestionnaireVersion[]>([]);
|
|
const [loading, setLoading] = useState(true);
|
|
const navigate = useNavigate();
|
|
|
|
useEffect(() => {
|
|
fetchVersions();
|
|
}, []);
|
|
|
|
const fetchVersions = async () => {
|
|
try {
|
|
setLoading(true);
|
|
const response = await API.getAllQuestionnaires() as any;
|
|
if (response.data?.success) {
|
|
setVersions(response.data.data);
|
|
} else {
|
|
toast.error('Failed to load questionnaire versions');
|
|
}
|
|
} catch (error) {
|
|
console.error(error);
|
|
toast.error('Error fetching versions');
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="p-6">
|
|
<div className="flex justify-between items-center mb-6">
|
|
<div>
|
|
<h2 className="text-2xl font-bold text-slate-900">Questionnaire Versions</h2>
|
|
<p className="text-slate-500">Manage your questionnaire templates and versions</p>
|
|
</div>
|
|
<button
|
|
onClick={() => navigate('/questionnaire-builder')}
|
|
className="bg-amber-600 text-white px-4 py-2 rounded-lg flex items-center gap-2 hover:bg-amber-700 transition"
|
|
>
|
|
<Plus size={20} /> Create New Version
|
|
</button>
|
|
</div>
|
|
|
|
{loading ? (
|
|
<div className="flex justify-center p-12">
|
|
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-amber-600"></div>
|
|
</div>
|
|
) : versions.length === 0 ? (
|
|
<div className="text-center p-12 bg-white rounded-lg shadow-sm border border-slate-200">
|
|
<p className="text-slate-500 mb-4">No questionnaire versions found.</p>
|
|
<button
|
|
onClick={() => navigate('/questionnaire-builder')}
|
|
className="text-amber-600 font-medium hover:underline"
|
|
>
|
|
Create your first version
|
|
</button>
|
|
</div>
|
|
) : (
|
|
<div className="bg-white rounded-lg shadow-sm border border-slate-200 overflow-hidden">
|
|
<table className="w-full text-left">
|
|
<thead className="bg-slate-50 border-b border-slate-100">
|
|
<tr>
|
|
<th className="p-4 font-medium text-slate-600">Version Name</th>
|
|
<th className="p-4 font-medium text-slate-600">Status</th>
|
|
<th className="p-4 font-medium text-slate-600">Created At</th>
|
|
<th className="p-4 font-medium text-slate-600 text-right">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody className="divide-y divide-slate-100">
|
|
{versions.map((v) => (
|
|
<tr key={v.id} className="hover:bg-slate-50 transition">
|
|
<td className="p-4 font-medium text-slate-900">{v.version}</td>
|
|
<td className="p-4">
|
|
{v.isActive ? (
|
|
<span className="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium bg-green-100 text-green-700 border border-green-200">
|
|
<CheckCircle size={12} /> Active
|
|
</span>
|
|
) : (
|
|
<span className="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium bg-slate-100 text-slate-600 border border-slate-200">
|
|
<XCircle size={12} /> Inactive
|
|
</span>
|
|
)}
|
|
</td>
|
|
<td className="p-4 text-slate-600 text-sm">
|
|
<div className="flex items-center gap-2">
|
|
<Calendar size={14} className="text-slate-400" />
|
|
{format(new Date(v.createdAt), 'MMM dd, yyyy HH:mm')}
|
|
</div>
|
|
</td>
|
|
<td className="p-4 text-right">
|
|
<button
|
|
onClick={() => navigate(`/questionnaire-builder/${v.id}`)}
|
|
className="inline-flex items-center gap-1.5 px-3 py-1.5 rounded text-sm font-medium text-slate-600 hover:text-amber-600 hover:bg-amber-50 transition border border-slate-200 hover:border-amber-200"
|
|
>
|
|
<Edit2 size={14} /> Edit / Clone
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default QuestionnaireList;
|