Fixed error with compliance page
This commit is contained in:
@@ -5,22 +5,15 @@ import {
|
||||
ShieldAlert,
|
||||
AlertTriangle,
|
||||
Users,
|
||||
CheckCircle2,
|
||||
TrendingUp,
|
||||
Target,
|
||||
Clock,
|
||||
Coins,
|
||||
AlertCircle,
|
||||
Sparkles,
|
||||
CheckCircle2,
|
||||
} from 'lucide-react';
|
||||
import { Modal } from '../ui/Modal';
|
||||
import { HelpTooltip } from '../ui/HelpTooltip';
|
||||
import { ComplianceStatusBadge } from '../ui/StatusBadge';
|
||||
import {
|
||||
Project,
|
||||
Programme,
|
||||
ComplianceItem,
|
||||
Beneficiary,
|
||||
Outcome,
|
||||
ComplianceStatus,
|
||||
ApprovalStatus,
|
||||
@@ -38,8 +31,6 @@ import {
|
||||
formatDate,
|
||||
formatZAR,
|
||||
getRiskScoreColor,
|
||||
getIndustrySectorLabel,
|
||||
getProjectTypeLabel,
|
||||
} from '../../lib/formatters';
|
||||
|
||||
interface ProjectComplianceModalProps {
|
||||
@@ -94,8 +85,6 @@ export const ProjectComplianceModal: React.FC<ProjectComplianceModalProps> = ({
|
||||
enabled: isOpen && !!projectId,
|
||||
});
|
||||
|
||||
// Beneficiaries already filtered by project
|
||||
|
||||
// Beneficiary outcomes query
|
||||
const { data: outcomes = [], isLoading: loadingOutcomes } = useQuery({
|
||||
queryKey: ['beneficiaryOutcomes', projectBeneficiaries.map((b) => b.id)],
|
||||
@@ -283,7 +272,9 @@ export const ProjectComplianceModal: React.FC<ProjectComplianceModalProps> = ({
|
||||
({risks.filter((r) => (Number(r.likelihood) || 1) * (Number(r.impact) || 1) >= 12).length} High)
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-[10px] text-slate-500">ISO 31000 risk register</span>
|
||||
<span className="text-[10px] text-slate-500 flex items-center gap-1">
|
||||
<CheckCircle2 className="w-3 h-3 text-cyan-400 inline" /> Milestones: {milestoneProgress}%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -326,14 +317,14 @@ export const ProjectComplianceModal: React.FC<ProjectComplianceModalProps> = ({
|
||||
);
|
||||
return (
|
||||
<tr key={ci.id} className="hover:bg-slate-900/30 transition">
|
||||
<td className="py-2.5 px-4 font-semibold text-white">{ci.title}</td>
|
||||
<td className="py-2.5 px-4 font-semibold text-white">{ci.title || 'Untitled Item'}</td>
|
||||
<td className="py-2.5 px-4 text-slate-300 max-w-sm truncate" title={ci.requirements || ''}>
|
||||
{ci.requirements || 'N/A'}
|
||||
</td>
|
||||
<td className="py-2.5 px-4 text-slate-300">
|
||||
{linkedBen ? (
|
||||
<span className="px-2 py-0.5 rounded bg-blue-500/10 border border-blue-500/20 text-blue-300 text-[11px]">
|
||||
{linkedBen.name}
|
||||
{linkedBen.name || 'Beneficiary'}
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-slate-500 italic">Project-Wide</span>
|
||||
@@ -386,18 +377,18 @@ export const ProjectComplianceModal: React.FC<ProjectComplianceModalProps> = ({
|
||||
>
|
||||
<div className="flex items-center justify-between flex-wrap gap-2">
|
||||
<div>
|
||||
<span className="font-bold text-white text-xs mr-2">{b.name}</span>
|
||||
<span className="font-bold text-white text-xs mr-2">{b.name || 'Beneficiary Group'}</span>
|
||||
<span className="text-[11px] text-slate-400 bg-slate-800 px-2 py-0.5 rounded border border-slate-700/60">
|
||||
{b.category} • {b.location}
|
||||
{b.category || 'General'}{b.location ? ` • ${b.location}` : ''}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-3 text-xs font-mono">
|
||||
<span className="text-slate-400">
|
||||
Target: <strong className="text-white">{b.targetCount}</strong>
|
||||
Target: <strong className="text-white">{b.targetCount ?? 0}</strong>
|
||||
</span>
|
||||
<span className="text-slate-600">•</span>
|
||||
<span className="text-slate-400">
|
||||
Reached: <strong className="text-emerald-400">{b.reachedCount}</strong>
|
||||
Reached: <strong className="text-emerald-400">{b.reachedCount ?? 0}</strong>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -417,8 +408,8 @@ export const ProjectComplianceModal: React.FC<ProjectComplianceModalProps> = ({
|
||||
className="p-2.5 rounded-lg bg-slate-950/60 border border-slate-800/80 flex items-start justify-between gap-2"
|
||||
>
|
||||
<div className="min-w-0">
|
||||
<span className="font-semibold text-slate-200 text-xs block truncate">{o.name}</span>
|
||||
<span className="text-[10px] text-slate-400 line-clamp-1">{o.description}</span>
|
||||
<span className="font-semibold text-slate-200 text-xs block truncate">{o.name || 'Outcome'}</span>
|
||||
<span className="text-[10px] text-slate-400 line-clamp-1">{o.description || 'No description'}</span>
|
||||
</div>
|
||||
<ComplianceStatusBadge status={o.status} />
|
||||
</div>
|
||||
@@ -456,8 +447,8 @@ export const ProjectComplianceModal: React.FC<ProjectComplianceModalProps> = ({
|
||||
<table className="w-full text-left text-xs border-collapse">
|
||||
<thead>
|
||||
<tr className="bg-slate-900/60 border-b border-slate-800 text-slate-400 text-[11px] font-semibold">
|
||||
<th className="py-2.5 px-4">Risk Title</th>
|
||||
<th className="py-2.5 px-4">Category</th>
|
||||
<th className="py-2.5 px-4">Risk Name</th>
|
||||
<th className="py-2.5 px-4">Category / Status</th>
|
||||
<th className="py-2.5 px-4 text-center">Score</th>
|
||||
<th className="py-2.5 px-4">Mitigation Strategy</th>
|
||||
</tr>
|
||||
@@ -465,25 +456,20 @@ export const ProjectComplianceModal: React.FC<ProjectComplianceModalProps> = ({
|
||||
<tbody className="divide-y divide-slate-800/60">
|
||||
{risks.map((r) => {
|
||||
const score = (Number(r.likelihood) || 1) * (Number(r.impact) || 1);
|
||||
const scoreColor = getRiskScoreColor(r.likelihood, r.impact);
|
||||
return (
|
||||
<tr key={r.id} className="hover:bg-slate-900/30 transition">
|
||||
<td className="py-2.5 px-4 font-semibold text-white">{r.title}</td>
|
||||
<td className="py-2.5 px-4 text-slate-300">{r.category || 'Operational'}</td>
|
||||
<td className="py-2.5 px-4 font-semibold text-white">{r.name || r.title || 'Unnamed Risk'}</td>
|
||||
<td className="py-2.5 px-4 text-slate-300">{r.category || r.status || 'Operational'}</td>
|
||||
<td className="py-2.5 px-4 text-center">
|
||||
<span
|
||||
className={`px-2 py-0.5 rounded text-[10px] font-bold ${
|
||||
score >= 12
|
||||
? 'bg-rose-500/20 text-rose-300 border border-rose-500/30'
|
||||
: score >= 8
|
||||
? 'bg-amber-500/20 text-amber-300 border border-amber-500/30'
|
||||
: 'bg-emerald-500/20 text-emerald-300 border border-emerald-500/30'
|
||||
}`}
|
||||
className={`px-2 py-0.5 rounded text-[10px] font-bold ${scoreColor.badge}`}
|
||||
>
|
||||
Score: {score}
|
||||
{scoreColor.level} ({score})
|
||||
</span>
|
||||
</td>
|
||||
<td className="py-2.5 px-4 text-slate-300 max-w-sm truncate" title={r.mitigation || ''}>
|
||||
{r.mitigation || 'No mitigation recorded'}
|
||||
<td className="py-2.5 px-4 text-slate-300 max-w-sm truncate" title={r.mitigationAction || r.mitigation || r.description || ''}>
|
||||
{r.mitigationAction || r.mitigation || r.description || 'No mitigation recorded'}
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user