[Phase 4] Enhanced file statistics with origin breakdown

Resolved 💬 3 comments Opened Nov 7, 2025 by gloos Closed Jan 9, 2026

Description

Enhance the file details page to show detailed statistics about segment origins and processing sources.

Dependencies

None - Can be implemented independently after Phase 1

Requirements

Location: Enhance existing apps/web/src/app/(authenticated)/files/[id]/page.tsx

New Statistics Section:

Display breakdown of segments by origin:

  • MT (Machine Translation)
  • TM (Translation Memory)
  • Manual translations
  • Other sources

Component: apps/web/src/components/files/OriginBreakdownCard.tsx

interface OriginBreakdown {
  origin: string;
  count: number;
  percentage: number;
  avgScore: number | null;
  avgQeScore: number | null;
}

export function OriginBreakdownCard({ fileId }: { fileId: string }) {
  // Server Component - fetch data directly
  const supabase = createRouteHandlerClient();
  const { data } = await supabase.rpc('get_origin_breakdown', { 
    p_file_id: fileId 
  });
  
  return (
    <div className="bg-white rounded-lg shadow p-6">
      <h3 className="text-lg font-semibold mb-4">Segment Origins</h3>
      <div className="space-y-3">
        {data?.map(item => (
          <div key={item.origin} className="flex items-center justify-between">
            <div>
              <span className="font-medium">{item.origin || 'Unknown'}</span>
              <span className="text-sm text-gray-500 ml-2">
                ({item.count} segments, {item.percentage.toFixed(1)}%)
              </span>
            </div>
            <div className="text-right">
              {item.avgScore && (
                <div className="text-sm">
                  TM: {item.avgScore.toFixed(1)}%
                </div>
              )}
              {item.avgQeScore && (
                <div className="text-sm">
                  QE: {item.avgQeScore.toFixed(1)}%
                </div>
              )}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

Required RPC:

CREATE OR REPLACE FUNCTION get_origin_breakdown(p_file_id UUID)
RETURNS TABLE (
  origin TEXT,
  count BIGINT,
  percentage NUMERIC,
  avg_score NUMERIC,
  avg_qe_score NUMERIC
) SECURITY DEFINER AS $$
DECLARE
  total_segments BIGINT;
BEGIN
  -- Verify file access via RLS
  IF NOT EXISTS (
    SELECT 1 FROM files 
    WHERE id = p_file_id AND created_by = auth.uid()
  ) THEN
    RAISE EXCEPTION 'Unauthorized or file not found';
  END IF;
  
  -- Get total count
  SELECT COUNT(*) INTO total_segments
  FROM segments WHERE file_id = p_file_id;
  
  RETURN QUERY
  SELECT 
    COALESCE(s.origin, 'Unknown') as origin,
    COUNT(*)::BIGINT as count,
    (COUNT(*)::NUMERIC / total_segments * 100) as percentage,
    AVG(s.score) as avg_score,
    AVG((r.result->>'qe_score')::NUMERIC) as avg_qe_score
  FROM segments s
  LEFT JOIN results r ON r.segment_id = s.id
  WHERE s.file_id = p_file_id
  GROUP BY s.origin
  ORDER BY count DESC;
END;
$$ LANGUAGE plpgsql;

Integration

Add to file header alongside existing stats:

  • Total segments
  • Approved segments
  • NEW: Origin breakdown expandable section
  • NEW: Average scores by origin

Acceptance Criteria

  • [ ] Origin breakdown displays correctly
  • [ ] Percentages sum to 100%
  • [ ] Handles files with no origin data gracefully
  • [ ] Average scores display only when available
  • [ ] RLS enforced (users only see their own files)

Testing

  • [ ] Test with files having multiple origins
  • [ ] Test with files having null/empty origins
  • [ ] Verify percentages are accurate
  • [ ] Test with large files (1000+ segments)

Phase

Phase 4: Enhanced Processing Metrics

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗