Spaces:
Running
Running
Update components/ResultsTable.tsx
Browse files- components/ResultsTable.tsx +376 -29
components/ResultsTable.tsx
CHANGED
@@ -33,51 +33,261 @@ const QAReportModal: React.FC<{ report: DetailedQaReport; onClose: () => void }>
|
|
33 |
<p><span className="font-semibold text-gray-400">Grade:</span> <span className="text-gray-200">{data.grade}</span></p>
|
34 |
<p><span className="font-semibold text-gray-400">Pass:</span> <span className={`font-medium ${data.pass ? 'text-green-400' : 'text-red-400'}`}>{data.pass ? 'Yes' : 'No'}</span></p>
|
35 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
<div className="pl-9 mt-3 text-sm">
|
37 |
<p className="font-semibold text-gray-400">Errors:</p>
|
38 |
<ul className="list-disc list-inside text-gray-300 pl-2 mt-1 space-y-1">
|
39 |
{data.errors.map((err, i) => <li key={i}>{err}</li>)}
|
40 |
</ul>
|
41 |
</div>
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
</div>
|
67 |
);
|
68 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
return (
|
70 |
<div className="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center p-4 z-50" onClick={onClose}>
|
71 |
-
<div className="bg-gray-800 rounded-lg shadow-xl p-6 max-w-
|
72 |
<div className="flex justify-between items-center mb-4 pb-4 border-b border-gray-700">
|
73 |
-
<h3 className="text-2xl font-bold text-white">QA Report Details</h3>
|
74 |
<button onClick={onClose} className="text-gray-400 hover:text-white text-3xl font-bold">×</button>
|
75 |
</div>
|
76 |
<div className="space-y-2">
|
|
|
77 |
<Section title="Title" data={report.title} />
|
78 |
<Section title="Meta Description" data={report.meta} />
|
79 |
<Section title="H1" data={report.h1} />
|
80 |
<Section title="Copy" data={report.copy} />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
</div>
|
82 |
</div>
|
83 |
</div>
|
@@ -124,19 +334,48 @@ const ResultsTable: React.FC<ResultsTableProps> = ({ results }) => {
|
|
124 |
'Generated Copy': row.generatedCopy,
|
125 |
'Overall Pass': row.overallPass,
|
126 |
'Overall Grade': row.overallGrade,
|
|
|
|
|
|
|
|
|
|
|
127 |
'Title Pass': report?.title.pass,
|
128 |
'Title Grade': report?.title.grade,
|
129 |
'Title Errors': report?.title.errors.join('; '),
|
|
|
|
|
|
|
|
|
|
|
130 |
'Meta Pass': report?.meta.pass,
|
131 |
'Meta Grade': report?.meta.grade,
|
132 |
'Meta Errors': report?.meta.errors.join('; '),
|
|
|
|
|
|
|
|
|
|
|
133 |
'H1 Pass': report?.h1.pass,
|
134 |
'H1 Grade': report?.h1.grade,
|
135 |
'H1 Errors': report?.h1.errors.join('; '),
|
|
|
|
|
|
|
|
|
|
|
136 |
'Copy Pass': report?.copy.pass,
|
137 |
'Copy Grade': report?.copy.grade,
|
138 |
'Copy Errors': report?.copy.errors.join('; '),
|
139 |
-
'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
};
|
141 |
});
|
142 |
|
@@ -298,16 +537,124 @@ const ResultsTable: React.FC<ResultsTableProps> = ({ results }) => {
|
|
298 |
pdf.setFont('helvetica', 'normal');
|
299 |
currentY = addWrappedText(`Errors: ${section.errors.join(', ')}`, margin + 10, currentY, maxLineWidth - 10, 8);
|
300 |
|
301 |
-
|
302 |
-
|
303 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
304 |
currentY += 4;
|
305 |
};
|
306 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
307 |
addQaSection('Title', row.detailedQaReport.title);
|
308 |
addQaSection('Meta', row.detailedQaReport.meta);
|
309 |
addQaSection('H1', row.detailedQaReport.h1);
|
310 |
addQaSection('Copy', row.detailedQaReport.copy);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
311 |
}
|
312 |
|
313 |
currentY += sectionSpacing * 2; // Extra spacing between entries
|
|
|
33 |
<p><span className="font-semibold text-gray-400">Grade:</span> <span className="text-gray-200">{data.grade}</span></p>
|
34 |
<p><span className="font-semibold text-gray-400">Pass:</span> <span className={`font-medium ${data.pass ? 'text-green-400' : 'text-red-400'}`}>{data.pass ? 'Yes' : 'No'}</span></p>
|
35 |
</div>
|
36 |
+
|
37 |
+
{/* Enhanced Content Display */}
|
38 |
+
{data.detailedAssessment && (
|
39 |
+
<div className="pl-9 mt-3 text-sm">
|
40 |
+
<p className="font-semibold text-gray-400">Detailed Assessment:</p>
|
41 |
+
<div className="text-gray-300 text-xs mt-1 bg-gray-950/50 p-3 rounded-md border border-gray-600/50">
|
42 |
+
<ReactMarkdown
|
43 |
+
components={{
|
44 |
+
p: ({ children }) => <p className="mb-2 last:mb-0 text-gray-300">{children}</p>,
|
45 |
+
ul: ({ children }) => <ul className="list-disc ml-4 mb-2 text-gray-300">{children}</ul>,
|
46 |
+
ol: ({ children }) => <ol className="list-decimal ml-4 mb-2 text-gray-300">{children}</ol>,
|
47 |
+
li: ({ children }) => <li className="mb-1 text-gray-300">{children}</li>,
|
48 |
+
code: ({ children }) => <code className="bg-gray-800 px-1 py-0.5 rounded text-blue-300 text-xs">{children}</code>,
|
49 |
+
strong: ({ children }) => <strong className="font-semibold text-white">{children}</strong>,
|
50 |
+
em: ({ children }) => <em className="italic text-gray-200">{children}</em>,
|
51 |
+
}}
|
52 |
+
>
|
53 |
+
{data.detailedAssessment}
|
54 |
+
</ReactMarkdown>
|
55 |
+
</div>
|
56 |
+
</div>
|
57 |
+
)}
|
58 |
+
|
59 |
+
{data.keyStrengths && data.keyStrengths.length > 0 && (
|
60 |
+
<div className="pl-9 mt-3 text-sm">
|
61 |
+
<p className="font-semibold text-gray-400">Key Strengths:</p>
|
62 |
+
<ul className="list-disc list-inside text-gray-300 pl-2 mt-1 space-y-1">
|
63 |
+
{data.keyStrengths.map((strength, i) => <li key={i}>{strength}</li>)}
|
64 |
+
</ul>
|
65 |
+
</div>
|
66 |
+
)}
|
67 |
+
|
68 |
+
{data.recommendations && data.recommendations.length > 0 && (
|
69 |
+
<div className="pl-9 mt-3 text-sm">
|
70 |
+
<p className="font-semibold text-gray-400">Recommendations:</p>
|
71 |
+
<ul className="list-disc list-inside text-gray-300 pl-2 mt-1 space-y-1">
|
72 |
+
{data.recommendations.map((rec, i) => <li key={i}>{rec}</li>)}
|
73 |
+
</ul>
|
74 |
+
</div>
|
75 |
+
)}
|
76 |
+
|
77 |
+
{data.explanations && (
|
78 |
+
<div className="pl-9 mt-3 text-sm">
|
79 |
+
<p className="font-semibold text-gray-400">Explanations:</p>
|
80 |
+
<div className="text-gray-300 text-xs mt-1 bg-gray-950/50 p-3 rounded-md border border-gray-600/50">
|
81 |
+
<ReactMarkdown
|
82 |
+
components={{
|
83 |
+
p: ({ children }) => <p className="mb-2 last:mb-0 text-gray-300">{children}</p>,
|
84 |
+
ul: ({ children }) => <ul className="list-disc ml-4 mb-2 text-gray-300">{children}</ul>,
|
85 |
+
ol: ({ children }) => <ol className="list-decimal ml-4 mb-2 text-gray-300">{children}</ol>,
|
86 |
+
li: ({ children }) => <li className="mb-1 text-gray-300">{children}</li>,
|
87 |
+
code: ({ children }) => <code className="bg-gray-800 px-1 py-0.5 rounded text-blue-300 text-xs">{children}</code>,
|
88 |
+
strong: ({ children }) => <strong className="font-semibold text-white">{children}</strong>,
|
89 |
+
em: ({ children }) => <em className="italic text-gray-200">{children}</em>,
|
90 |
+
}}
|
91 |
+
>
|
92 |
+
{data.explanations}
|
93 |
+
</ReactMarkdown>
|
94 |
+
</div>
|
95 |
+
</div>
|
96 |
+
)}
|
97 |
+
|
98 |
<div className="pl-9 mt-3 text-sm">
|
99 |
<p className="font-semibold text-gray-400">Errors:</p>
|
100 |
<ul className="list-disc list-inside text-gray-300 pl-2 mt-1 space-y-1">
|
101 |
{data.errors.map((err, i) => <li key={i}>{err}</li>)}
|
102 |
</ul>
|
103 |
</div>
|
104 |
+
|
105 |
+
{data.corrected && (
|
106 |
+
<div className="pl-9 mt-3 text-sm">
|
107 |
+
<p className="font-semibold text-gray-400">Corrected Content:</p>
|
108 |
+
<div className="text-gray-300 text-xs mt-1 bg-gray-950/50 p-3 rounded-md border border-gray-600/50 overflow-auto max-h-48">
|
109 |
+
<div className="prose prose-sm prose-invert max-w-none">
|
110 |
+
<ReactMarkdown
|
111 |
+
components={{
|
112 |
+
p: ({ children }) => <p className="mb-2 last:mb-0 text-gray-300">{children}</p>,
|
113 |
+
ul: ({ children }) => <ul className="list-disc ml-4 mb-2 text-gray-300">{children}</ul>,
|
114 |
+
ol: ({ children }) => <ol className="list-decimal ml-4 mb-2 text-gray-300">{children}</ol>,
|
115 |
+
li: ({ children }) => <li className="mb-1 text-gray-300">{children}</li>,
|
116 |
+
code: ({ children }) => <code className="bg-gray-800 px-1 py-0.5 rounded text-blue-300 text-xs">{children}</code>,
|
117 |
+
strong: ({ children }) => <strong className="font-semibold text-white">{children}</strong>,
|
118 |
+
em: ({ children }) => <em className="italic text-gray-200">{children}</em>,
|
119 |
+
h1: ({ children }) => <h1 className="text-lg font-bold mb-2 text-white">{children}</h1>,
|
120 |
+
h2: ({ children }) => <h2 className="text-base font-semibold mb-2 text-white">{children}</h2>,
|
121 |
+
h3: ({ children }) => <h3 className="text-sm font-semibold mb-1 text-white">{children}</h3>,
|
122 |
+
}}
|
123 |
+
>
|
124 |
+
{data.corrected}
|
125 |
+
</ReactMarkdown>
|
126 |
+
</div>
|
127 |
+
</div>
|
128 |
+
</div>
|
129 |
+
)}
|
130 |
+
|
131 |
+
{/* Raw Content for complete transparency */}
|
132 |
+
{data.rawContent && (
|
133 |
+
<div className="pl-9 mt-3 text-sm">
|
134 |
+
<p className="font-semibold text-gray-400">Raw QA Content:</p>
|
135 |
+
<div className="text-gray-300 text-xs mt-1 bg-gray-950/50 p-3 rounded-md border border-gray-600/50 overflow-auto max-h-32">
|
136 |
+
<pre className="whitespace-pre-wrap text-gray-400">{data.rawContent}</pre>
|
137 |
+
</div>
|
138 |
+
</div>
|
139 |
+
)}
|
140 |
+
</div>
|
141 |
+
);
|
142 |
+
|
143 |
+
const OverallSection: React.FC<{ data: DetailedQaReport['overall'] }> = ({ data }) => (
|
144 |
+
<div className="bg-gray-900/70 p-4 rounded-lg mb-4 border border-gray-700">
|
145 |
+
<h4 className="text-lg font-semibold text-white mb-3 flex items-center gap-3">
|
146 |
+
{data.pass
|
147 |
+
? <CheckCircleIcon className="w-6 h-6 text-green-400 flex-shrink-0" />
|
148 |
+
: <XCircleIcon className="w-6 h-6 text-red-400 flex-shrink-0" />
|
149 |
+
}
|
150 |
+
Overall Assessment
|
151 |
+
</h4>
|
152 |
+
<div className="grid grid-cols-1 sm:grid-cols-2 gap-x-4 gap-y-2 text-sm pl-9">
|
153 |
+
<p><span className="font-semibold text-gray-400">Grade:</span> <span className="text-gray-200">{data.grade}</span></p>
|
154 |
+
<p><span className="font-semibold text-gray-400">Pass:</span> <span className={`font-medium ${data.pass ? 'text-green-400' : 'text-red-400'}`}>{data.pass ? 'Yes' : 'No'}</span></p>
|
155 |
</div>
|
156 |
+
|
157 |
+
<div className="pl-9 mt-3 text-sm">
|
158 |
+
<p className="font-semibold text-gray-400">Primary Issue:</p>
|
159 |
+
<p className="text-gray-300 mt-1">{data.primaryIssue}</p>
|
160 |
+
</div>
|
161 |
+
|
162 |
+
{/* Enhanced Overall Content Display */}
|
163 |
+
{data.detailedAssessment && (
|
164 |
+
<div className="pl-9 mt-3 text-sm">
|
165 |
+
<p className="font-semibold text-gray-400">Detailed Assessment:</p>
|
166 |
+
<div className="text-gray-300 text-xs mt-1 bg-gray-950/50 p-3 rounded-md border border-gray-600/50">
|
167 |
+
<ReactMarkdown
|
168 |
+
components={{
|
169 |
+
p: ({ children }) => <p className="mb-2 last:mb-0 text-gray-300">{children}</p>,
|
170 |
+
ul: ({ children }) => <ul className="list-disc ml-4 mb-2 text-gray-300">{children}</ul>,
|
171 |
+
ol: ({ children }) => <ol className="list-decimal ml-4 mb-2 text-gray-300">{children}</ol>,
|
172 |
+
li: ({ children }) => <li className="mb-1 text-gray-300">{children}</li>,
|
173 |
+
code: ({ children }) => <code className="bg-gray-800 px-1 py-0.5 rounded text-blue-300 text-xs">{children}</code>,
|
174 |
+
strong: ({ children }) => <strong className="font-semibold text-white">{children}</strong>,
|
175 |
+
em: ({ children }) => <em className="italic text-gray-200">{children}</em>,
|
176 |
+
}}
|
177 |
+
>
|
178 |
+
{data.detailedAssessment}
|
179 |
+
</ReactMarkdown>
|
180 |
+
</div>
|
181 |
+
</div>
|
182 |
+
)}
|
183 |
+
|
184 |
+
{data.keyStrengths && data.keyStrengths.length > 0 && (
|
185 |
+
<div className="pl-9 mt-3 text-sm">
|
186 |
+
<p className="font-semibold text-gray-400">Key Strengths:</p>
|
187 |
+
<ul className="list-disc list-inside text-gray-300 pl-2 mt-1 space-y-1">
|
188 |
+
{data.keyStrengths.map((strength, i) => <li key={i}>{strength}</li>)}
|
189 |
+
</ul>
|
190 |
+
</div>
|
191 |
+
)}
|
192 |
+
|
193 |
+
{data.recommendations && data.recommendations.length > 0 && (
|
194 |
+
<div className="pl-9 mt-3 text-sm">
|
195 |
+
<p className="font-semibold text-gray-400">Recommendations:</p>
|
196 |
+
<ul className="list-disc list-inside text-gray-300 pl-2 mt-1 space-y-1">
|
197 |
+
{data.recommendations.map((rec, i) => <li key={i}>{rec}</li>)}
|
198 |
+
</ul>
|
199 |
+
</div>
|
200 |
+
)}
|
201 |
+
|
202 |
+
{data.explanations && (
|
203 |
+
<div className="pl-9 mt-3 text-sm">
|
204 |
+
<p className="font-semibold text-gray-400">Explanations:</p>
|
205 |
+
<div className="text-gray-300 text-xs mt-1 bg-gray-950/50 p-3 rounded-md border border-gray-600/50">
|
206 |
+
<ReactMarkdown
|
207 |
+
components={{
|
208 |
+
p: ({ children }) => <p className="mb-2 last:mb-0 text-gray-300">{children}</p>,
|
209 |
+
ul: ({ children }) => <ul className="list-disc ml-4 mb-2 text-gray-300">{children}</ul>,
|
210 |
+
ol: ({ children }) => <ol className="list-decimal ml-4 mb-2 text-gray-300">{children}</ol>,
|
211 |
+
li: ({ children }) => <li className="mb-1 text-gray-300">{children}</li>,
|
212 |
+
code: ({ children }) => <code className="bg-gray-800 px-1 py-0.5 rounded text-blue-300 text-xs">{children}</code>,
|
213 |
+
strong: ({ children }) => <strong className="font-semibold text-white">{children}</strong>,
|
214 |
+
em: ({ children }) => <em className="italic text-gray-200">{children}</em>,
|
215 |
+
}}
|
216 |
+
>
|
217 |
+
{data.explanations}
|
218 |
+
</ReactMarkdown>
|
219 |
+
</div>
|
220 |
+
</div>
|
221 |
+
)}
|
222 |
+
|
223 |
+
{/* Raw Content for complete transparency */}
|
224 |
+
{data.rawContent && (
|
225 |
+
<div className="pl-9 mt-3 text-sm">
|
226 |
+
<p className="font-semibold text-gray-400">Raw Overall Content:</p>
|
227 |
+
<div className="text-gray-300 text-xs mt-1 bg-gray-950/50 p-3 rounded-md border border-gray-600/50 overflow-auto max-h-32">
|
228 |
+
<pre className="whitespace-pre-wrap text-gray-400">{data.rawContent}</pre>
|
229 |
+
</div>
|
230 |
+
</div>
|
231 |
+
)}
|
232 |
</div>
|
233 |
);
|
234 |
|
235 |
+
const AdditionalSections: React.FC<{ sections: DetailedQaReport['additionalSections'] }> = ({ sections }) => {
|
236 |
+
if (!sections) return null;
|
237 |
+
|
238 |
+
return (
|
239 |
+
<div className="bg-gray-900/70 p-4 rounded-lg mb-4 border border-gray-700">
|
240 |
+
<h4 className="text-lg font-semibold text-white mb-3">Additional QA Sections</h4>
|
241 |
+
<div className="space-y-3">
|
242 |
+
{Object.entries(sections).map(([sectionName, sectionData]) => (
|
243 |
+
<div key={sectionName} className="border-l-2 border-gray-600 pl-3">
|
244 |
+
<h5 className="text-sm font-semibold text-gray-300 mb-2 capitalize">{sectionName}</h5>
|
245 |
+
<div className="text-gray-300 text-xs bg-gray-950/50 p-3 rounded-md border border-gray-600/50 overflow-auto max-h-32">
|
246 |
+
<ReactMarkdown
|
247 |
+
components={{
|
248 |
+
p: ({ children }) => <p className="mb-2 last:mb-0 text-gray-300">{children}</p>,
|
249 |
+
ul: ({ children }) => <ul className="list-disc ml-4 mb-2 text-gray-300">{children}</ul>,
|
250 |
+
ol: ({ children }) => <ol className="list-decimal ml-4 mb-2 text-gray-300">{children}</ol>,
|
251 |
+
li: ({ children }) => <li className="mb-1 text-gray-300">{children}</li>,
|
252 |
+
code: ({ children }) => <code className="bg-gray-800 px-1 py-0.5 rounded text-blue-300 text-xs">{children}</code>,
|
253 |
+
strong: ({ children }) => <strong className="font-semibold text-white">{children}</strong>,
|
254 |
+
em: ({ children }) => <em className="italic text-gray-200">{children}</em>,
|
255 |
+
}}
|
256 |
+
>
|
257 |
+
{sectionData.content}
|
258 |
+
</ReactMarkdown>
|
259 |
+
</div>
|
260 |
+
</div>
|
261 |
+
))}
|
262 |
+
</div>
|
263 |
+
</div>
|
264 |
+
);
|
265 |
+
};
|
266 |
+
|
267 |
return (
|
268 |
<div className="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center p-4 z-50" onClick={onClose}>
|
269 |
+
<div className="bg-gray-800 rounded-lg shadow-xl p-6 max-w-6xl w-full max-h-[90vh] overflow-y-auto" onClick={e => e.stopPropagation()}>
|
270 |
<div className="flex justify-between items-center mb-4 pb-4 border-b border-gray-700">
|
271 |
+
<h3 className="text-2xl font-bold text-white">Complete QA Report Details</h3>
|
272 |
<button onClick={onClose} className="text-gray-400 hover:text-white text-3xl font-bold">×</button>
|
273 |
</div>
|
274 |
<div className="space-y-2">
|
275 |
+
<OverallSection data={report.overall} />
|
276 |
<Section title="Title" data={report.title} />
|
277 |
<Section title="Meta Description" data={report.meta} />
|
278 |
<Section title="H1" data={report.h1} />
|
279 |
<Section title="Copy" data={report.copy} />
|
280 |
+
<AdditionalSections sections={report.additionalSections} />
|
281 |
+
|
282 |
+
{/* Complete Raw Report */}
|
283 |
+
{report.completeRawReport && (
|
284 |
+
<div className="bg-gray-900/70 p-4 rounded-lg mb-4 border border-gray-700">
|
285 |
+
<h4 className="text-lg font-semibold text-white mb-3">Complete Raw QA Report</h4>
|
286 |
+
<div className="text-gray-300 text-xs bg-gray-950/50 p-3 rounded-md border border-gray-600/50 overflow-auto max-h-64">
|
287 |
+
<pre className="whitespace-pre-wrap text-gray-400">{report.completeRawReport}</pre>
|
288 |
+
</div>
|
289 |
+
</div>
|
290 |
+
)}
|
291 |
</div>
|
292 |
</div>
|
293 |
</div>
|
|
|
334 |
'Generated Copy': row.generatedCopy,
|
335 |
'Overall Pass': row.overallPass,
|
336 |
'Overall Grade': row.overallGrade,
|
337 |
+
'Overall Primary Issue': report?.overall.primaryIssue,
|
338 |
+
'Overall Detailed Assessment': report?.overall.detailedAssessment,
|
339 |
+
'Overall Key Strengths': report?.overall.keyStrengths?.join('; '),
|
340 |
+
'Overall Recommendations': report?.overall.recommendations?.join('; '),
|
341 |
+
'Overall Explanations': report?.overall.explanations,
|
342 |
'Title Pass': report?.title.pass,
|
343 |
'Title Grade': report?.title.grade,
|
344 |
'Title Errors': report?.title.errors.join('; '),
|
345 |
+
'Title Detailed Assessment': report?.title.detailedAssessment,
|
346 |
+
'Title Key Strengths': report?.title.keyStrengths?.join('; '),
|
347 |
+
'Title Recommendations': report?.title.recommendations?.join('; '),
|
348 |
+
'Title Explanations': report?.title.explanations,
|
349 |
+
'Title Corrected': report?.title.corrected,
|
350 |
'Meta Pass': report?.meta.pass,
|
351 |
'Meta Grade': report?.meta.grade,
|
352 |
'Meta Errors': report?.meta.errors.join('; '),
|
353 |
+
'Meta Detailed Assessment': report?.meta.detailedAssessment,
|
354 |
+
'Meta Key Strengths': report?.meta.keyStrengths?.join('; '),
|
355 |
+
'Meta Recommendations': report?.meta.recommendations?.join('; '),
|
356 |
+
'Meta Explanations': report?.meta.explanations,
|
357 |
+
'Meta Corrected': report?.meta.corrected,
|
358 |
'H1 Pass': report?.h1.pass,
|
359 |
'H1 Grade': report?.h1.grade,
|
360 |
'H1 Errors': report?.h1.errors.join('; '),
|
361 |
+
'H1 Detailed Assessment': report?.h1.detailedAssessment,
|
362 |
+
'H1 Key Strengths': report?.h1.keyStrengths?.join('; '),
|
363 |
+
'H1 Recommendations': report?.h1.recommendations?.join('; '),
|
364 |
+
'H1 Explanations': report?.h1.explanations,
|
365 |
+
'H1 Corrected': report?.h1.corrected,
|
366 |
'Copy Pass': report?.copy.pass,
|
367 |
'Copy Grade': report?.copy.grade,
|
368 |
'Copy Errors': report?.copy.errors.join('; '),
|
369 |
+
'Copy Detailed Assessment': report?.copy.detailedAssessment,
|
370 |
+
'Copy Key Strengths': report?.copy.keyStrengths?.join('; '),
|
371 |
+
'Copy Recommendations': report?.copy.recommendations?.join('; '),
|
372 |
+
'Copy Explanations': report?.copy.explanations,
|
373 |
+
'Copy Corrected': report?.copy.corrected,
|
374 |
+
'Additional QA Sections': report?.additionalSections ?
|
375 |
+
Object.entries(report.additionalSections)
|
376 |
+
.map(([name, data]) => `${name}: ${data.content}`)
|
377 |
+
.join(' | ') : '',
|
378 |
+
'Complete Raw QA Report': report?.completeRawReport || row.qaReport,
|
379 |
};
|
380 |
});
|
381 |
|
|
|
537 |
pdf.setFont('helvetica', 'normal');
|
538 |
currentY = addWrappedText(`Errors: ${section.errors.join(', ')}`, margin + 10, currentY, maxLineWidth - 10, 8);
|
539 |
|
540 |
+
// Enhanced QA content display
|
541 |
+
if (section.detailedAssessment) {
|
542 |
+
currentY = ensureMinSpace(20);
|
543 |
+
pdf.setFont('helvetica', 'bold');
|
544 |
+
currentY = addWrappedText('Detailed Assessment:', margin + 10, currentY, maxLineWidth - 10, 8);
|
545 |
+
pdf.setFont('helvetica', 'normal');
|
546 |
+
currentY = addWrappedText(section.detailedAssessment, margin + 15, currentY, maxLineWidth - 15, 7);
|
547 |
+
}
|
548 |
+
|
549 |
+
if (section.keyStrengths && section.keyStrengths.length > 0) {
|
550 |
+
currentY = ensureMinSpace(20);
|
551 |
+
pdf.setFont('helvetica', 'bold');
|
552 |
+
currentY = addWrappedText('Key Strengths:', margin + 10, currentY, maxLineWidth - 10, 8);
|
553 |
+
pdf.setFont('helvetica', 'normal');
|
554 |
+
section.keyStrengths.forEach(strength => {
|
555 |
+
currentY = addWrappedText(`• ${strength}`, margin + 15, currentY, maxLineWidth - 15, 7);
|
556 |
+
});
|
557 |
+
}
|
558 |
+
|
559 |
+
if (section.recommendations && section.recommendations.length > 0) {
|
560 |
+
currentY = ensureMinSpace(20);
|
561 |
+
pdf.setFont('helvetica', 'bold');
|
562 |
+
currentY = addWrappedText('Recommendations:', margin + 10, currentY, maxLineWidth - 10, 8);
|
563 |
+
pdf.setFont('helvetica', 'normal');
|
564 |
+
section.recommendations.forEach(rec => {
|
565 |
+
currentY = addWrappedText(`• ${rec}`, margin + 15, currentY, maxLineWidth - 15, 7);
|
566 |
+
});
|
567 |
+
}
|
568 |
+
|
569 |
+
if (section.explanations) {
|
570 |
+
currentY = ensureMinSpace(20);
|
571 |
+
pdf.setFont('helvetica', 'bold');
|
572 |
+
currentY = addWrappedText('Explanations:', margin + 10, currentY, maxLineWidth - 10, 8);
|
573 |
+
pdf.setFont('helvetica', 'normal');
|
574 |
+
currentY = addWrappedText(section.explanations, margin + 15, currentY, maxLineWidth - 15, 7);
|
575 |
+
}
|
576 |
+
|
577 |
+
if (section.corrected) {
|
578 |
+
currentY = ensureMinSpace(20);
|
579 |
+
pdf.setFont('helvetica', 'italic');
|
580 |
+
currentY = addWrappedText(`Correction/Analysis: ${section.corrected}`, margin + 10, currentY, maxLineWidth - 10, 8);
|
581 |
+
}
|
582 |
currentY += 4;
|
583 |
};
|
584 |
|
585 |
+
// Add Overall Assessment first
|
586 |
+
const overall = row.detailedQaReport.overall;
|
587 |
+
currentY = ensureMinSpace(40);
|
588 |
+
pdf.setFontSize(11);
|
589 |
+
pdf.setFont('helvetica', 'bold');
|
590 |
+
currentY = addWrappedText('Overall Assessment:', margin + 5, currentY, maxLineWidth - 5, 11);
|
591 |
+
currentY += 2;
|
592 |
+
|
593 |
+
pdf.setFontSize(9);
|
594 |
+
pdf.setFont('helvetica', 'normal');
|
595 |
+
currentY = addWrappedText(`Primary Issue: ${overall.primaryIssue}`, margin + 10, currentY, maxLineWidth - 10, 9);
|
596 |
+
|
597 |
+
if (overall.detailedAssessment) {
|
598 |
+
currentY = ensureMinSpace(20);
|
599 |
+
pdf.setFont('helvetica', 'bold');
|
600 |
+
currentY = addWrappedText('Detailed Assessment:', margin + 10, currentY, maxLineWidth - 10, 8);
|
601 |
+
pdf.setFont('helvetica', 'normal');
|
602 |
+
currentY = addWrappedText(overall.detailedAssessment, margin + 15, currentY, maxLineWidth - 15, 7);
|
603 |
+
}
|
604 |
+
|
605 |
+
if (overall.keyStrengths && overall.keyStrengths.length > 0) {
|
606 |
+
currentY = ensureMinSpace(20);
|
607 |
+
pdf.setFont('helvetica', 'bold');
|
608 |
+
currentY = addWrappedText('Key Strengths:', margin + 10, currentY, maxLineWidth - 10, 8);
|
609 |
+
pdf.setFont('helvetica', 'normal');
|
610 |
+
overall.keyStrengths.forEach(strength => {
|
611 |
+
currentY = addWrappedText(`• ${strength}`, margin + 15, currentY, maxLineWidth - 15, 7);
|
612 |
+
});
|
613 |
+
}
|
614 |
+
|
615 |
+
if (overall.recommendations && overall.recommendations.length > 0) {
|
616 |
+
currentY = ensureMinSpace(20);
|
617 |
+
pdf.setFont('helvetica', 'bold');
|
618 |
+
currentY = addWrappedText('Recommendations:', margin + 10, currentY, maxLineWidth - 10, 8);
|
619 |
+
pdf.setFont('helvetica', 'normal');
|
620 |
+
overall.recommendations.forEach(rec => {
|
621 |
+
currentY = addWrappedText(`• ${rec}`, margin + 15, currentY, maxLineWidth - 15, 7);
|
622 |
+
});
|
623 |
+
}
|
624 |
+
|
625 |
+
if (overall.explanations) {
|
626 |
+
currentY = ensureMinSpace(20);
|
627 |
+
pdf.setFont('helvetica', 'bold');
|
628 |
+
currentY = addWrappedText('Explanations:', margin + 10, currentY, maxLineWidth - 10, 8);
|
629 |
+
pdf.setFont('helvetica', 'normal');
|
630 |
+
currentY = addWrappedText(overall.explanations, margin + 15, currentY, maxLineWidth - 15, 7);
|
631 |
+
}
|
632 |
+
|
633 |
+
currentY += 5;
|
634 |
+
|
635 |
addQaSection('Title', row.detailedQaReport.title);
|
636 |
addQaSection('Meta', row.detailedQaReport.meta);
|
637 |
addQaSection('H1', row.detailedQaReport.h1);
|
638 |
addQaSection('Copy', row.detailedQaReport.copy);
|
639 |
+
|
640 |
+
// Add Additional Sections if available
|
641 |
+
if (row.detailedQaReport.additionalSections) {
|
642 |
+
currentY = ensureMinSpace(30);
|
643 |
+
pdf.setFontSize(10);
|
644 |
+
pdf.setFont('helvetica', 'bold');
|
645 |
+
currentY = addWrappedText('Additional QA Sections:', margin + 5, currentY, maxLineWidth - 5, 10);
|
646 |
+
currentY += 2;
|
647 |
+
|
648 |
+
Object.entries(row.detailedQaReport.additionalSections).forEach(([sectionName, sectionData]) => {
|
649 |
+
currentY = ensureMinSpace(25);
|
650 |
+
pdf.setFontSize(9);
|
651 |
+
pdf.setFont('helvetica', 'bold');
|
652 |
+
currentY = addWrappedText(`${sectionName}:`, margin + 10, currentY, maxLineWidth - 10, 9);
|
653 |
+
pdf.setFont('helvetica', 'normal');
|
654 |
+
currentY = addWrappedText(sectionData.content, margin + 15, currentY, maxLineWidth - 15, 7);
|
655 |
+
currentY += 2;
|
656 |
+
});
|
657 |
+
}
|
658 |
}
|
659 |
|
660 |
currentY += sectionSpacing * 2; // Extra spacing between entries
|