Dealer_Onboard_Frontend/src/features/onboarding/components/QuestionnaireResponseView.tsx

128 lines
6.9 KiB
TypeScript

import React from 'react';
import { Badge } from '@/components/ui/badge';
import { ClipboardList } from 'lucide-react';
interface QuestionnaireResponseViewProps {
application: any;
}
const QuestionnaireResponseView: React.FC<QuestionnaireResponseViewProps> = ({ application }) => {
// If no responses or empty array
if (!application.questionnaireResponses || application.questionnaireResponses.length === 0) {
return (
<div
className="flex flex-col items-center justify-center py-12 text-slate-500 bg-slate-50 rounded-lg border border-dashed border-slate-300"
data-testid="onboarding-questionnaire-empty"
>
<ClipboardList className="w-12 h-12 mb-3 text-slate-300" />
<h3 className="text-lg font-medium text-slate-700">Response is Pending</h3>
<p className="text-sm">The applicant has not submitted the questionnaire yet.</p>
</div>
);
}
// Sort responses by question order if possible, or just index
// Assuming backend returns them in some order, better to sort by question.order if available
const responses = [...application.questionnaireResponses].sort((a, b) => {
return (a.question?.order || 0) - (b.question?.order || 0);
});
const totalScore = application.score || application.questionnaireMarks || 0; // Fallback mapping
return (
<div className="space-y-6" data-testid="onboarding-questionnaire-view">
<div className="flex items-center justify-between mb-4">
<div className="flex items-center gap-3">
<ClipboardList className="w-5 h-5 text-amber-600" />
<h3 className="text-slate-900">Questionnaire Responses</h3>
</div>
{totalScore !== undefined && (
<Badge className="bg-amber-600" data-testid="onboarding-questionnaire-total-score">Score: {totalScore}/100</Badge>
)}
</div>
<div className="space-y-6">
{responses.map((resp: any, index: number) => {
const question = resp.question;
const questionText = question?.questionText || 'Unknown Question';
const answer = resp.responseValue || 'No Answer';
const section = question?.sectionName || 'General';
const options = question?.questionOptions || [];
// Match answer to find score
// Note: This relies on exact string match.
const matchedOption = options.find((opt: any) => opt.optionText === answer);
const score = matchedOption ? matchedOption.score : 0;
const maxScore = Math.max(...options.map((o: any) => o.score || 0), 0);
const isFile = typeof answer === 'string' && answer.startsWith('data:');
const isImage = isFile && answer.startsWith('data:image');
return (
<div
key={resp.id}
className="border border-slate-200 rounded-lg p-5 hover:border-amber-300 transition-colors"
data-testid={`onboarding-questionnaire-item-${index}`}
>
<div className="flex items-start gap-3 mb-3">
<div className="w-8 h-8 rounded-full bg-amber-100 flex items-center justify-center flex-shrink-0">
<span className="text-amber-600">{index + 1}</span>
</div>
<div className="flex-1">
<div className="flex items-center gap-2 mb-2">
<Badge variant="outline" className="text-slate-600 bg-slate-50" data-testid={`onboarding-questionnaire-item-section-${index}`}>
{section}
</Badge>
{(options.length > 0 && maxScore > 0) && (
<Badge
className={score > 0 ? "bg-green-600" : "bg-slate-400"}
data-testid={`onboarding-questionnaire-item-score-${index}`}
>
{score}/{maxScore}
</Badge>
)}
</div>
<h4 className="text-slate-900 font-medium" data-testid={`onboarding-questionnaire-item-text-${index}`}>{questionText}</h4>
</div>
</div>
<div className="ml-11">
{isImage ? (
<div className="mt-2" data-testid={`onboarding-questionnaire-item-image-${index}`}>
<img
src={answer}
alt="Response Attachment"
className="max-w-full h-auto max-h-64 rounded border p-1 object-contain"
/>
</div>
) : isFile ? (
<a
href={answer}
download={`upload_${index}.pdf`}
className="text-blue-600 underline text-sm break-all"
data-testid={`onboarding-questionnaire-item-download-${index}`}
>
Download Attachment
</a>
) : (
<div className="text-slate-600 leading-relaxed break-words whitespace-pre-wrap" data-testid={`onboarding-questionnaire-item-answer-${index}`}>
{resp.attachmentUrl ? (
<a href={resp.attachmentUrl} target="_blank" rel="noreferrer" className="text-blue-600 underline" data-testid={`onboarding-questionnaire-item-attachment-${index}`}>
View Attachment
</a>
) : (
answer
)}
</div>
)}
</div>
</div>
);
})}
</div>
</div>
);
};
export default QuestionnaireResponseView;