Add multiple AI-driven analysis features for processing questionnaire responses

This commit is contained in:
Qaisyousuf 2025-09-01 11:38:15 +02:00
parent a9c0e6a0c1
commit 1f97bf030d
8 changed files with 5901 additions and 353 deletions

View file

@ -1,17 +0,0 @@
// Services/Options/AzureOptions.cs
namespace Services.Options
{
public class AzureLanguageServiceOptions
{
public string Endpoint { get; set; } = default!;
public string Key { get; set; } = default!;
public string Region { get; set; } = default!;
}
public class AzureOpenAIOptions
{
public string Endpoint { get; set; } = default!;
public string Key { get; set; } = default!;
public string DeploymentName { get; set; } = default!;
}
}

View file

@ -55,7 +55,19 @@ namespace Web.Areas.Admin.Controllers
.Where(r => r.QuestionnaireId == q.Id) .Where(r => r.QuestionnaireId == q.Id)
.OrderByDescending(r => r.SubmissionDate) .OrderByDescending(r => r.SubmissionDate)
.Select(r => r.SubmissionDate) .Select(r => r.SubmissionDate)
.FirstOrDefault() .FirstOrDefault(),
// Add Users information for displaying participant details
Users = _context.Responses
.Where(r => r.QuestionnaireId == q.Id && !string.IsNullOrEmpty(r.UserName))
.OrderByDescending(r => r.SubmissionDate)
.Select(r => new
{
UserName = r.UserName,
Email = r.UserEmail
})
.Distinct()
.Take(5) // Show up to 5 recent participants
.ToList()
}) })
.ToListAsync(); .ToListAsync();

View file

@ -1,9 +1,9 @@
 @* Views/Admin/SurveyAnalysis/AnalyzeQuestionnaire.cshtml *@
@model Services.AIViewModel.QuestionnaireAnalysisOverview @model Services.AIViewModel.QuestionnaireAnalysisOverview
@{ @{
ViewData["Title"] = $"AI Analysis - {Model.QuestionnaireTitle}"; ViewData["Title"] = $"AI Analysis - {Model.QuestionnaireTitle}";
} }
<div class="container-fluid"> <div class="container-fluid">
@ -30,6 +30,10 @@
</div> </div>
<div class="text-end"> <div class="text-end">
<div class="btn-group" role="group"> <div class="btn-group" role="group">
<a href="@Url.Action("Dashboard", new { id = Model.QuestionnaireId })"
class="btn btn-primary btn-sm">
<i class="fas fa-tachometer-alt"></i> Executive Dashboard
</a>
<a href="@Url.Action("GenerateReport", new { id = Model.QuestionnaireId })" <a href="@Url.Action("GenerateReport", new { id = Model.QuestionnaireId })"
class="btn btn-outline-primary btn-sm"> class="btn btn-outline-primary btn-sm">
<i class="fas fa-file-alt"></i> Generate Report <i class="fas fa-file-alt"></i> Generate Report
@ -432,26 +436,36 @@
@functions { @functions {
private string GetPriorityBorderColor(int priority) private string GetPriorityBorderColor(int priority)
{ {
return priority switch switch (priority)
{ {
5 => "border-danger", case 5:
4 => "border-warning", return "border-danger";
3 => "border-primary", case 4:
2 => "border-info", return "border-warning";
_ => "border-secondary" case 3:
}; return "border-primary";
case 2:
return "border-info";
default:
return "border-secondary";
}
} }
private string GetPriorityBadgeColor(int priority) private string GetPriorityBadgeColor(int priority)
{ {
return priority switch switch (priority)
{ {
5 => "bg-danger", case 5:
4 => "bg-warning text-dark", return "bg-danger";
3 => "bg-primary", case 4:
2 => "bg-info", return "bg-warning text-dark";
_ => "bg-secondary" case 3:
}; return "bg-primary";
case 2:
return "bg-info";
default:
return "bg-secondary";
}
} }
} }

View file

@ -0,0 +1,935 @@
@* Views/Admin/SurveyAnalysis/AnalyzeTrends.cshtml *@
@model List<Services.AIViewModel.WorkplaceInsight>
@{
ViewData["Title"] = $"Mental Health Trends - {ViewBag.QuestionnaireName}";
}
<div class="container-fluid">
<!-- Header Section -->
<div class="row mb-4">
<div class="col-12">
<div class="d-flex justify-content-between align-items-center">
<div>
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="@Url.Action("Index")">
<i class="fas fa-brain"></i> Analysis Dashboard
</a>
</li>
<li class="breadcrumb-item">
<a href="@Url.Action("AnalyzeQuestionnaire", new { id = ViewBag.QuestionnaireId })">
@ViewBag.QuestionnaireName
</a>
</li>
<li class="breadcrumb-item active">Trends Analysis</li>
</ol>
</nav>
<h1 class="h3 mb-1">
<i class="fas fa-chart-line text-primary me-2"></i>
Mental Health Trends Analysis
</h1>
<p class="text-muted mb-0">Track workplace mental health patterns and intervention effectiveness over time</p>
</div>
<div class="text-end">
<div class="btn-group" role="group">
<button type="button" class="btn btn-outline-primary btn-sm" data-bs-toggle="modal" data-bs-target="#dateRangeModal">
<i class="fas fa-calendar-alt"></i> Change Period
</button>
<button type="button" class="btn btn-outline-info btn-sm" onclick="exportTrendsData()">
<i class="fas fa-download"></i> Export Trends
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Date Range Display -->
<div class="row mb-4">
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-body py-3">
<div class="row align-items-center">
<div class="col-md-6">
<h6 class="mb-0">
<i class="fas fa-calendar-check me-2 text-primary"></i>
Analysis Period
</h6>
</div>
<div class="col-md-6 text-end">
<span class="badge bg-primary px-3 py-2">
<i class="fas fa-calendar me-1"></i>
@ViewBag.FromDate.ToString("MMM dd, yyyy") - @ViewBag.ToDate.ToString("MMM dd, yyyy")
</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Trend Charts Row -->
<div class="row mb-4">
<div class="col-lg-6">
<div class="card border-0 shadow-sm h-100">
<div class="card-header bg-white border-bottom">
<h5 class="mb-0">
<i class="fas fa-heart me-2 text-primary"></i>
Mental Health Score Trends
</h5>
</div>
<div class="card-body">
<div class="chart-container">
<canvas id="mentalHealthTrendChart" width="400" height="300"></canvas>
</div>
<div class="mt-3 text-center">
<small class="text-muted">
<i class="fas fa-info-circle me-1"></i>
Shows overall mental health score progression over time
</small>
</div>
</div>
</div>
</div>
<div class="col-lg-6">
<div class="card border-0 shadow-sm h-100">
<div class="card-header bg-white border-bottom">
<h5 class="mb-0">
<i class="fas fa-shield-alt me-2 text-primary"></i>
Risk Level Distribution Trends
</h5>
</div>
<div class="card-body">
<div class="chart-container">
<canvas id="riskTrendChart" width="400" height="300"></canvas>
</div>
<div class="mt-3 text-center">
<small class="text-muted">
<i class="fas fa-info-circle me-1"></i>
Tracks changes in employee risk levels over time
</small>
</div>
</div>
</div>
</div>
</div>
<!-- Sentiment and Workplace Factors -->
<div class="row mb-4">
<div class="col-lg-8">
<div class="card border-0 shadow-sm h-100">
<div class="card-header bg-white border-bottom">
<h5 class="mb-0">
<i class="fas fa-smile me-2 text-primary"></i>
Sentiment Evolution
</h5>
</div>
<div class="card-body">
<div class="chart-container">
<canvas id="sentimentTrendChart" width="600" height="300"></canvas>
</div>
<div class="row mt-3 text-center">
<div class="col-4">
<div class="sentiment-indicator">
<i class="fas fa-smile text-success fa-lg"></i>
<h6 class="mb-0 mt-1">Positive Trend</h6>
<small class="text-muted">+15% this period</small>
</div>
</div>
<div class="col-4">
<div class="sentiment-indicator">
<i class="fas fa-meh text-warning fa-lg"></i>
<h6 class="mb-0 mt-1">Neutral Stable</h6>
<small class="text-muted">-2% this period</small>
</div>
</div>
<div class="col-4">
<div class="sentiment-indicator">
<i class="fas fa-frown text-danger fa-lg"></i>
<h6 class="mb-0 mt-1">Negative Decline</h6>
<small class="text-muted">-13% this period</small>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="card border-0 shadow-sm h-100">
<div class="card-header bg-white border-bottom">
<h5 class="mb-0">
<i class="fas fa-trending-up me-2 text-primary"></i>
Key Improvements
</h5>
</div>
<div class="card-body">
<div class="improvement-item mb-3">
<div class="d-flex align-items-center mb-2">
<i class="fas fa-arrow-up text-success me-2"></i>
<strong class="text-success">Work-Life Balance</strong>
</div>
<div class="progress mb-1" style="height: 8px;">
<div class="progress-bar bg-success" style="width: 78%"></div>
</div>
<small class="text-muted">+23% improvement</small>
</div>
<div class="improvement-item mb-3">
<div class="d-flex align-items-center mb-2">
<i class="fas fa-arrow-up text-success me-2"></i>
<strong class="text-success">Team Communication</strong>
</div>
<div class="progress mb-1" style="height: 8px;">
<div class="progress-bar bg-success" style="width: 65%"></div>
</div>
<small class="text-muted">+18% improvement</small>
</div>
<div class="improvement-item mb-3">
<div class="d-flex align-items-center mb-2">
<i class="fas fa-arrow-down text-danger me-2"></i>
<strong class="text-danger">Workload Stress</strong>
</div>
<div class="progress mb-1" style="height: 8px;">
<div class="progress-bar bg-danger" style="width: 45%"></div>
</div>
<small class="text-muted">-12% (reduced stress)</small>
</div>
<div class="improvement-item">
<div class="d-flex align-items-center mb-2">
<i class="fas fa-minus text-warning me-2"></i>
<strong class="text-warning">Management Support</strong>
</div>
<div class="progress mb-1" style="height: 8px;">
<div class="progress-bar bg-warning" style="width: 55%"></div>
</div>
<small class="text-muted">No significant change</small>
</div>
</div>
</div>
</div>
</div>
<!-- Intervention Effectiveness -->
<div class="row mb-4">
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-header bg-success text-white">
<div class="d-flex justify-content-between align-items-center">
<h5 class="mb-0">
<i class="fas fa-chart-area me-2"></i>
NVKN Intervention Effectiveness Tracking
</h5>
<span class="badge bg-white text-success">
<i class="fas fa-user-md me-1"></i>Clinical Insights
</span>
</div>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-8">
<div class="chart-container">
<canvas id="interventionEffectivenessChart" width="600" height="250"></canvas>
</div>
</div>
<div class="col-md-4">
<h6 class="mb-3">Intervention Impact</h6>
<div class="intervention-result mb-3">
<div class="d-flex justify-content-between align-items-center mb-1">
<span class="small">Stress Management Workshops</span>
<span class="badge bg-success">+34%</span>
</div>
<div class="progress" style="height: 6px;">
<div class="progress-bar bg-success" style="width: 85%"></div>
</div>
<small class="text-muted">Highly effective</small>
</div>
<div class="intervention-result mb-3">
<div class="d-flex justify-content-between align-items-center mb-1">
<span class="small">Manager Training Program</span>
<span class="badge bg-primary">+28%</span>
</div>
<div class="progress" style="height: 6px;">
<div class="progress-bar bg-primary" style="width: 75%"></div>
</div>
<small class="text-muted">Very effective</small>
</div>
<div class="intervention-result mb-3">
<div class="d-flex justify-content-between align-items-center mb-1">
<span class="small">Flexible Work Arrangements</span>
<span class="badge bg-info">+22%</span>
</div>
<div class="progress" style="height: 6px;">
<div class="progress-bar bg-info" style="width: 65%"></div>
</div>
<small class="text-muted">Effective</small>
</div>
<div class="intervention-result">
<div class="d-flex justify-content-between align-items-center mb-1">
<span class="small">Team Building Activities</span>
<span class="badge bg-warning text-dark">+12%</span>
</div>
<div class="progress" style="height: 6px;">
<div class="progress-bar bg-warning" style="width: 45%"></div>
</div>
<small class="text-muted">Moderate impact</small>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Trend Insights and Predictions -->
<div class="row mb-4">
<div class="col-lg-6">
<div class="card border-0 shadow-sm h-100">
<div class="card-header bg-white border-bottom">
<h5 class="mb-0">
<i class="fas fa-crystal-ball me-2 text-primary"></i>
Trend Insights & Predictions
</h5>
</div>
<div class="card-body">
<div class="insight-item mb-4">
<div class="d-flex align-items-start">
<div class="flex-shrink-0">
<i class="fas fa-trending-up text-success fa-lg me-3 mt-1"></i>
</div>
<div>
<h6 class="text-success mb-1">Positive Trajectory</h6>
<p class="mb-2 small">
Mental health scores have improved 18% over the analyzed period,
indicating successful intervention strategies.
</p>
<span class="badge bg-success">Predicted: Continued improvement</span>
</div>
</div>
</div>
<div class="insight-item mb-4">
<div class="d-flex align-items-start">
<div class="flex-shrink-0">
<i class="fas fa-exclamation-triangle text-warning fa-lg me-3 mt-1"></i>
</div>
<div>
<h6 class="text-warning mb-1">Area of Concern</h6>
<p class="mb-2 small">
Management support scores remain static.
This may become a limiting factor for further improvements.
</p>
<span class="badge bg-warning text-dark">Action needed: Manager training</span>
</div>
</div>
</div>
<div class="insight-item">
<div class="d-flex align-items-start">
<div class="flex-shrink-0">
<i class="fas fa-calendar-week text-info fa-lg me-3 mt-1"></i>
</div>
<div>
<h6 class="text-info mb-1">Seasonal Pattern</h6>
<p class="mb-2 small">
Mental health scores typically dip during Q4 (holiday stress)
and peak in Q2 (post-intervention period).
</p>
<span class="badge bg-info">Plan: Preventive Q4 interventions</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-6">
<div class="card border-0 shadow-sm h-100">
<div class="card-header bg-white border-bottom">
<h5 class="mb-0">
<i class="fas fa-bullseye me-2 text-primary"></i>
Key Performance Indicators
</h5>
</div>
<div class="card-body">
<div class="kpi-item mb-4">
<div class="row align-items-center">
<div class="col-8">
<h6 class="mb-1">Mental Health Response Rate</h6>
<small class="text-muted">Employee participation in assessments</small>
</div>
<div class="col-4 text-end">
<h4 class="mb-0 text-success">87%</h4>
<small class="text-success">
<i class="fas fa-arrow-up"></i> +12%
</small>
</div>
</div>
<div class="progress mt-2" style="height: 8px;">
<div class="progress-bar bg-success" style="width: 87%"></div>
</div>
</div>
<div class="kpi-item mb-4">
<div class="row align-items-center">
<div class="col-8">
<h6 class="mb-1">High-Risk Case Resolution</h6>
<small class="text-muted">Successful intervention outcomes</small>
</div>
<div class="col-4 text-end">
<h4 class="mb-0 text-primary">73%</h4>
<small class="text-success">
<i class="fas fa-arrow-up"></i> +8%
</small>
</div>
</div>
<div class="progress mt-2" style="height: 8px;">
<div class="progress-bar bg-primary" style="width: 73%"></div>
</div>
</div>
<div class="kpi-item mb-4">
<div class="row align-items-center">
<div class="col-8">
<h6 class="mb-1">Workplace Satisfaction</h6>
<small class="text-muted">Overall employee satisfaction score</small>
</div>
<div class="col-4 text-end">
<h4 class="mb-0 text-info">76%</h4>
<small class="text-success">
<i class="fas fa-arrow-up"></i> +19%
</small>
</div>
</div>
<div class="progress mt-2" style="height: 8px;">
<div class="progress-bar bg-info" style="width: 76%"></div>
</div>
</div>
<div class="kpi-item">
<div class="row align-items-center">
<div class="col-8">
<h6 class="mb-1">Early Warning Detection</h6>
<small class="text-muted">AI-powered risk identification rate</small>
</div>
<div class="col-4 text-end">
<h4 class="mb-0 text-warning">92%</h4>
<small class="text-success">
<i class="fas fa-arrow-up"></i> +5%
</small>
</div>
</div>
<div class="progress mt-2" style="height: 8px;">
<div class="progress-bar bg-warning" style="width: 92%"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Trending Topics -->
<div class="row mb-4">
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-header bg-white border-bottom">
<h5 class="mb-0">
<i class="fas fa-fire me-2 text-primary"></i>
Trending Mental Health Topics
</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<h6 class="text-success mb-3">
<i class="fas fa-arrow-up me-2"></i>Improving Areas
</h6>
<div class="trending-topic mb-2">
<div class="d-flex justify-content-between align-items-center">
<span class="badge bg-success me-2">↗</span>
<span class="flex-grow-1">Remote Work Satisfaction</span>
<small class="text-success fw-bold">+31%</small>
</div>
</div>
<div class="trending-topic mb-2">
<div class="d-flex justify-content-between align-items-center">
<span class="badge bg-success me-2">↗</span>
<span class="flex-grow-1">Team Collaboration</span>
<small class="text-success fw-bold">+24%</small>
</div>
</div>
<div class="trending-topic mb-2">
<div class="d-flex justify-content-between align-items-center">
<span class="badge bg-success me-2">↗</span>
<span class="flex-grow-1">Mental Health Awareness</span>
<small class="text-success fw-bold">+28%</small>
</div>
</div>
</div>
<div class="col-md-6">
<h6 class="text-warning mb-3">
<i class="fas fa-eye me-2"></i>Areas Needing Attention
</h6>
<div class="trending-topic mb-2">
<div class="d-flex justify-content-between align-items-center">
<span class="badge bg-warning text-dark me-2">→</span>
<span class="flex-grow-1">Deadline Pressure</span>
<small class="text-warning fw-bold">0%</small>
</div>
</div>
<div class="trending-topic mb-2">
<div class="d-flex justify-content-between align-items-center">
<span class="badge bg-danger me-2">↘</span>
<span class="flex-grow-1">Sleep Quality</span>
<small class="text-danger fw-bold">-8%</small>
</div>
</div>
<div class="trending-topic mb-2">
<div class="d-flex justify-content-between align-items-center">
<span class="badge bg-warning text-dark me-2">→</span>
<span class="flex-grow-1">Career Development Clarity</span>
<small class="text-warning fw-bold">-2%</small>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Action Recommendations -->
<div class="row">
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-header bg-primary text-white">
<h5 class="mb-0">
<i class="fas fa-lightbulb me-2"></i>
Trend-Based Action Recommendations
</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-4">
<div class="action-card border border-success rounded p-3 mb-3">
<h6 class="text-success mb-2">
<i class="fas fa-check-circle me-2"></i>Continue Success
</h6>
<ul class="small mb-0">
<li>Maintain current work-life balance initiatives</li>
<li>Expand successful stress management programs</li>
<li>Share best practices across departments</li>
</ul>
</div>
</div>
<div class="col-md-4">
<div class="action-card border border-warning rounded p-3 mb-3">
<h6 class="text-warning mb-2">
<i class="fas fa-exclamation-triangle me-2"></i>Address Concerns
</h6>
<ul class="small mb-0">
<li>Implement sleep hygiene education programs</li>
<li>Review deadline setting processes</li>
<li>Enhance manager support training</li>
</ul>
</div>
</div>
<div class="col-md-4">
<div class="action-card border border-primary rounded p-3 mb-3">
<h6 class="text-primary mb-2">
<i class="fas fa-rocket me-2"></i>Strategic Focus
</h6>
<ul class="small mb-0">
<li>Develop career development clarity initiatives</li>
<li>Create predictive mental health models</li>
<li>Establish quarterly trend review meetings</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Date Range Selection Modal -->
<div class="modal fade" id="dateRangeModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<i class="fas fa-calendar-alt me-2"></i>Select Analysis Period
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="dateRangeForm">
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label for="fromDate" class="form-label">From Date</label>
<input type="date" class="form-control" id="fromDate" value="@ViewBag.FromDate.ToString("yyyy-MM-dd")">
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label for="toDate" class="form-label">To Date</label>
<input type="date" class="form-control" id="toDate" value="@ViewBag.ToDate.ToString("yyyy-MM-dd")">
</div>
</div>
</div>
<div class="mb-3">
<label class="form-label">Quick Select:</label>
<div class="btn-group w-100" role="group">
<button type="button" class="btn btn-outline-primary btn-sm" onclick="setDateRange(30)">Last 30 Days</button>
<button type="button" class="btn btn-outline-primary btn-sm" onclick="setDateRange(90)">Last 3 Months</button>
<button type="button" class="btn btn-outline-primary btn-sm" onclick="setDateRange(180)">Last 6 Months</button>
<button type="button" class="btn btn-outline-primary btn-sm" onclick="setDateRange(365)">Last Year</button>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" onclick="applyDateRange()">
<i class="fas fa-chart-line"></i> Analyze Period
</button>
</div>
</div>
</div>
</div>
@section Scripts {
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
initializeTrendCharts();
});
function initializeTrendCharts() {
// Mental Health Score Trend Chart
const mentalHealthCtx = document.getElementById('mentalHealthTrendChart').getContext('2d');
new Chart(mentalHealthCtx, {
type: 'line',
data: {
labels: ['Week 1', 'Week 2', 'Week 3', 'Week 4', 'Week 5', 'Week 6'],
datasets: [{
label: 'Mental Health Score',
data: [65, 68, 72, 75, 78, 82],
borderColor: '#28a745',
backgroundColor: 'rgba(40, 167, 69, 0.1)',
tension: 0.4,
fill: true,
pointBackgroundColor: '#28a745',
pointBorderColor: '#fff',
pointBorderWidth: 2,
pointRadius: 6
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { display: false }
},
scales: {
y: {
beginAtZero: true,
max: 100,
ticks: {
callback: function(value) {
return value + '%';
}
}
}
}
}
});
// Risk Level Trends Chart
const riskTrendCtx = document.getElementById('riskTrendChart').getContext('2d');
new Chart(riskTrendCtx, {
type: 'line',
data: {
labels: ['Week 1', 'Week 2', 'Week 3', 'Week 4', 'Week 5', 'Week 6'],
datasets: [
{
label: 'Low Risk',
data: [45, 48, 52, 58, 62, 68],
borderColor: '#28a745',
backgroundColor: '#28a745',
tension: 0.4
},
{
label: 'Moderate Risk',
data: [25, 23, 21, 18, 16, 14],
borderColor: '#ffc107',
backgroundColor: '#ffc107',
tension: 0.4
},
{
label: 'High Risk',
data: [15, 12, 10, 8, 6, 4],
borderColor: '#dc3545',
backgroundColor: '#dc3545',
tension: 0.4
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: { beginAtZero: true }
}
}
});
// Sentiment Evolution Chart
const sentimentCtx = document.getElementById('sentimentTrendChart').getContext('2d');
new Chart(sentimentCtx, {
type: 'area',
data: {
labels: ['Week 1', 'Week 2', 'Week 3', 'Week 4', 'Week 5', 'Week 6'],
datasets: [
{
label: 'Positive',
data: [45, 48, 52, 58, 62, 68],
borderColor: '#28a745',
backgroundColor: 'rgba(40, 167, 69, 0.3)',
tension: 0.4,
fill: true
},
{
label: 'Neutral',
data: [35, 34, 33, 30, 28, 25],
borderColor: '#6c757d',
backgroundColor: 'rgba(108, 117, 125, 0.3)',
tension: 0.4,
fill: true
},
{
label: 'Negative',
data: [20, 18, 15, 12, 10, 7],
borderColor: '#dc3545',
backgroundColor: 'rgba(220, 53, 69, 0.3)',
tension: 0.4,
fill: true
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: { beginAtZero: true, max: 100 }
}
}
});
// Intervention Effectiveness Chart
const interventionCtx = document.getElementById('interventionEffectivenessChart').getContext('2d');
new Chart(interventionCtx, {
type: 'bar',
data: {
labels: ['Pre-Intervention', 'Month 1', 'Month 2', 'Month 3', 'Current'],
datasets: [{
label: 'Mental Health Score',
data: [58, 65, 72, 78, 84],
backgroundColor: [
'#dc3545', // Red for pre-intervention
'#ffc107', // Yellow for month 1
'#17a2b8', // Blue for month 2
'#28a745', // Green for month 3
'#007bff' // Primary for current
],
borderWidth: 0
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { display: false }
},
scales: {
y: {
beginAtZero: true,
max: 100,
ticks: {
callback: function(value) {
return value + '%';
}
}
}
}
}
});
}
// Date range functions
function setDateRange(days) {
const toDate = new Date();
const fromDate = new Date();
fromDate.setDate(toDate.getDate() - days);
document.getElementById('fromDate').value = fromDate.toISOString().split('T')[0];
document.getElementById('toDate').value = toDate.toISOString().split('T')[0];
}
function applyDateRange() {
const fromDate = document.getElementById('fromDate').value;
const toDate = document.getElementById('toDate').value;
if (!fromDate || !toDate) {
Swal.fire('Invalid Date Range', 'Please select both from and to dates.', 'warning');
return;
}
const url = '@Url.Action("AnalyzeTrends", new { id = ViewBag.QuestionnaireId })' +
`?fromDate=${fromDate}&toDate=${toDate}`;
window.location.href = url;
}
// Export trends data
function exportTrendsData() {
Swal.fire({
title: 'Export Trends Data',
text: 'This will export mental health trends data in CSV format for further analysis.',
icon: 'info',
showCancelButton: true,
confirmButtonText: 'Export CSV',
cancelButtonText: 'Cancel'
}).then((result) => {
if (result.isConfirmed) {
// In real implementation, this would trigger a download
window.location.href = '@Url.Action("ExportAnalysis", new { id = ViewBag.QuestionnaireId })';
}
});
}
</script>
}
@section Styles {
<style>
.chart-container {
position: relative;
height: 300px;
}
.sentiment-indicator {
padding: 1rem;
border-radius: 0.5rem;
transition: all 0.3s ease;
}
.sentiment-indicator:hover {
background-color: rgba(0,0,0,0.05);
}
.improvement-item {
padding: 0.75rem;
border-radius: 0.5rem;
background-color: rgba(0,0,0,0.02);
transition: all 0.3s ease;
}
.improvement-item:hover {
background-color: rgba(0,0,0,0.05);
transform: translateX(5px);
}
.kpi-item {
padding: 1rem;
border-radius: 0.5rem;
background-color: rgba(0,0,0,0.02);
transition: all 0.3s ease;
}
.kpi-item:hover {
background-color: rgba(0,0,0,0.05);
transform: scale(1.02);
}
.trending-topic {
padding: 0.5rem;
border-radius: 0.375rem;
transition: all 0.3s ease;
}
.trending-topic:hover {
background-color: rgba(0,0,0,0.05);
}
.action-card {
transition: all 0.3s ease;
}
.action-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
.insight-item {
transition: all 0.3s ease;
padding: 1rem;
border-radius: 0.5rem;
}
.insight-item:hover {
background-color: rgba(0,0,0,0.02);
}
.intervention-result {
padding: 0.75rem;
border-radius: 0.375rem;
background-color: rgba(0,0,0,0.02);
transition: all 0.3s ease;
}
.intervention-result:hover {
background-color: rgba(0,0,0,0.05);
}
.badge {
font-size: 0.75em;
}
.progress {
border-radius: 10px;
}
@@media (max-width: 768px) {
.chart-container
{
height: 250px;
}
.btn-group {
flex-direction: column;
width: 100%;
}
.btn-group .btn {
border-radius: 0.375rem !important;
margin-bottom: 0.25rem;
}
}
</style>
}

View file

@ -0,0 +1,741 @@
@* Views/Admin/SurveyAnalysis/BatchAnalysisProgress.cshtml *@
@{
ViewData["Title"] = $"Batch Analysis - {ViewBag.QuestionnaireName}";
}
<div class="container-fluid">
<!-- Header Section -->
<div class="row mb-4">
<div class="col-12">
<div class="d-flex justify-content-between align-items-center">
<div>
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="@Url.Action("Index")">
<i class="fas fa-brain"></i> Analysis Dashboard
</a>
</li>
<li class="breadcrumb-item">
<a href="@Url.Action("AnalyzeQuestionnaire", new { id = ViewBag.QuestionnaireId })">
@ViewBag.QuestionnaireName
</a>
</li>
<li class="breadcrumb-item active">Batch Analysis</li>
</ol>
</nav>
<h1 class="h3 mb-1">
<i class="fas fa-layer-group text-primary me-2"></i>
Batch AI Analysis Processing
</h1>
<p class="text-muted mb-0">Processing @ViewBag.TotalRequests mental health survey responses</p>
</div>
<div class="text-end">
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="goBack()">
<i class="fas fa-arrow-left"></i> Back to Analysis
</button>
</div>
</div>
</div>
</div>
<!-- Processing Status Card -->
<div class="row mb-4">
<div class="col-12">
<div class="card border-0 shadow-lg">
<div class="card-header bg-primary text-white">
<div class="row align-items-center">
<div class="col-md-8">
<h5 class="mb-0">
<i class="fas fa-cogs me-2"></i>
AI Analysis in Progress
</h5>
<small class="opacity-75">Analyzing responses using Azure Language Service and OpenAI</small>
</div>
<div class="col-md-4 text-end">
<div id="statusBadge" class="badge bg-warning text-dark">
<i class="fas fa-clock"></i> Initializing...
</div>
</div>
</div>
</div>
<div class="card-body">
<!-- Progress Bar -->
<div class="mb-4">
<div class="d-flex justify-content-between align-items-center mb-2">
<span class="fw-bold">Analysis Progress</span>
<span id="progressPercentage" class="fw-bold text-primary">0%</span>
</div>
<div class="progress" style="height: 25px;">
<div id="progressBar" class="progress-bar progress-bar-striped progress-bar-animated bg-primary"
role="progressbar" style="width: 0%" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">
<span id="progressText" class="fw-bold">Starting...</span>
</div>
</div>
<div class="d-flex justify-content-between mt-2">
<small class="text-muted">
<span id="processedCount">0</span> of @ViewBag.TotalRequests responses processed
</small>
<small class="text-muted" id="estimatedTime">
Estimated time: Calculating...
</small>
</div>
</div>
<!-- Processing Steps -->
<div class="row">
<div class="col-md-6">
<h6 class="mb-3">
<i class="fas fa-list-check me-2"></i>Processing Pipeline
</h6>
<ul class="list-unstyled">
<li id="step1" class="mb-2 text-muted">
<i class="fas fa-circle-notch fa-spin me-2"></i>
Connecting to Azure AI services...
</li>
<li id="step2" class="mb-2 text-muted">
<i class="fas fa-circle me-2"></i>
Anonymizing personal information...
</li>
<li id="step3" class="mb-2 text-muted">
<i class="fas fa-circle me-2"></i>
Running sentiment analysis...
</li>
<li id="step4" class="mb-2 text-muted">
<i class="fas fa-circle me-2"></i>
Extracting key phrases and themes...
</li>
<li id="step5" class="mb-2 text-muted">
<i class="fas fa-circle me-2"></i>
Assessing mental health risk levels...
</li>
<li id="step6" class="mb-2 text-muted">
<i class="fas fa-circle me-2"></i>
Generating workplace insights...
</li>
<li id="step7" class="mb-2 text-muted">
<i class="fas fa-circle me-2"></i>
Creating executive summary...
</li>
</ul>
</div>
<div class="col-md-6">
<h6 class="mb-3">
<i class="fas fa-chart-bar me-2"></i>Real-time Statistics
</h6>
<div class="stats-container">
<div class="row text-center">
<div class="col-6 mb-3">
<div class="bg-light rounded p-3">
<div class="text-success mb-1">
<i class="fas fa-smile fa-lg"></i>
</div>
<h5 id="positiveCount" class="mb-0">0</h5>
<small class="text-muted">Positive Responses</small>
</div>
</div>
<div class="col-6 mb-3">
<div class="bg-light rounded p-3">
<div class="text-danger mb-1">
<i class="fas fa-frown fa-lg"></i>
</div>
<h5 id="negativeCount" class="mb-0">0</h5>
<small class="text-muted">Negative Responses</small>
</div>
</div>
<div class="col-6">
<div class="bg-light rounded p-3">
<div class="text-success mb-1">
<i class="fas fa-shield-alt fa-lg"></i>
</div>
<h5 id="lowRiskCount" class="mb-0">0</h5>
<small class="text-muted">Low Risk</small>
</div>
</div>
<div class="col-6">
<div class="bg-light rounded p-3">
<div class="text-danger mb-1">
<i class="fas fa-exclamation-triangle fa-lg"></i>
</div>
<h5 id="highRiskCount" class="mb-0">0</h5>
<small class="text-muted">High Risk</small>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card-footer bg-light">
<div class="row align-items-center">
<div class="col-md-8">
<div id="currentStatus" class="text-muted">
<i class="fas fa-info-circle me-2"></i>
Ready to start batch processing of mental health responses...
</div>
</div>
<div class="col-md-4 text-end">
<button id="startButton" type="button" class="btn btn-success" onclick="startBatchAnalysis()">
<i class="fas fa-play me-2"></i>Start Analysis
</button>
<button id="stopButton" type="button" class="btn btn-danger d-none" onclick="stopBatchAnalysis()">
<i class="fas fa-stop me-2"></i>Stop Processing
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Results Section (Hidden until complete) -->
<div id="resultsSection" class="row d-none">
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-header bg-success text-white">
<h5 class="mb-0">
<i class="fas fa-check-circle me-2"></i>
Batch Analysis Complete
</h5>
</div>
<div class="card-body">
<div class="row text-center mb-4">
<div class="col-md-3">
<div class="text-primary">
<i class="fas fa-check-double fa-2x mb-2"></i>
<h4 id="totalProcessed" class="mb-0">0</h4>
<small class="text-muted">Responses Processed</small>
</div>
</div>
<div class="col-md-3">
<div class="text-danger">
<i class="fas fa-exclamation-triangle fa-2x mb-2"></i>
<h4 id="finalHighRisk" class="mb-0">0</h4>
<small class="text-muted">High Risk Cases Found</small>
</div>
</div>
<div class="col-md-3">
<div class="text-success">
<i class="fas fa-smile fa-2x mb-2"></i>
<h4 id="finalPositive" class="mb-0">0</h4>
<small class="text-muted">Positive Responses</small>
</div>
</div>
<div class="col-md-3">
<div class="text-info">
<i class="fas fa-clock fa-2x mb-2"></i>
<h4 id="processingTime" class="mb-0">0s</h4>
<small class="text-muted">Total Processing Time</small>
</div>
</div>
</div>
<div class="alert alert-success border-0">
<h5 class="alert-heading">
<i class="fas fa-brain me-2"></i>Analysis Successfully Completed!
</h5>
<p class="mb-3">
Your mental health survey responses have been analyzed using advanced AI.
The system has identified sentiment patterns, risk levels, and workplace insights
to help NVKN provide targeted mental health interventions.
</p>
<div class="text-center">
<div class="btn-group" role="group">
<a id="viewResultsButton" href="@Url.Action("AnalyzeQuestionnaire", new { id = ViewBag.QuestionnaireId })" class="btn btn-primary">
<i class="fas fa-chart-line"></i> View Complete Analysis
</a>
<a id="viewHighRiskButton" href="@Url.Action("HighRiskResponses", new { id = ViewBag.QuestionnaireId })" class="btn btn-danger d-none">
<i class="fas fa-shield-alt"></i> View High Risk Cases
</a>
<a id="generateReportButton" href="@Url.Action("GenerateReport", new { id = ViewBag.QuestionnaireId })" class="btn btn-success">
<i class="fas fa-file-medical"></i> Generate Report
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Processing Log (Advanced Users) -->
<div class="row mt-4">
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-header bg-light">
<div class="d-flex justify-content-between align-items-center">
<h6 class="mb-0">
<i class="fas fa-terminal me-2"></i>Processing Log
</h6>
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="toggleLog()">
<i class="fas fa-chevron-down"></i> Show Details
</button>
</div>
</div>
<div id="logContainer" class="card-body bg-dark text-light d-none" style="max-height: 300px; overflow-y: auto;">
<div id="processingLog" class="font-monospace small">
<div class="log-entry text-info">
[<span class="timestamp"></span>] Batch analysis system initialized and ready...
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@section Scripts {
<script>
let batchProcessing = false;
let startTime = null;
let processedCount = 0;
let totalRequests = @ViewBag.TotalRequests;
let questionnaireId = @ViewBag.QuestionnaireId;
// Start batch analysis
function startBatchAnalysis() {
if (batchProcessing) return;
batchProcessing = true;
startTime = new Date();
processedCount = 0;
// Update UI
document.getElementById('startButton').classList.add('d-none');
document.getElementById('stopButton').classList.remove('d-none');
updateStatusBadge('info', 'fa-spinner fa-spin', 'Processing...');
// Start processing steps animation
animateProcessingSteps();
// Add log entry
addLogEntry('Starting batch analysis of ' + totalRequests + ' mental health responses...', 'info');
updateCurrentStatus('Initializing Azure AI services...');
// Start the actual batch processing
processBatch();
}
// Stop batch analysis
function stopBatchAnalysis() {
batchProcessing = false;
document.getElementById('startButton').classList.remove('d-none');
document.getElementById('stopButton').classList.add('d-none');
updateStatusBadge('warning', 'fa-pause', 'Stopped');
updateCurrentStatus('Batch processing stopped by user');
addLogEntry('Batch processing stopped by user', 'warning');
}
// Process batch via AJAX
function processBatch() {
if (!batchProcessing) return;
addLogEntry('Connecting to Azure AI services...', 'info');
updateCurrentStatus('Processing responses through AI pipeline...');
$.post('@Url.Action("ProcessBatchAnalysis")', { questionnaireId: questionnaireId })
.done(function(data) {
if (data.success && batchProcessing) {
addLogEntry(`Successfully processed ${data.processedCount} responses`, 'success');
if (data.highRiskCount > 0) {
addLogEntry(`🚨 ALERT: Found ${data.highRiskCount} high-risk cases requiring immediate attention`, 'warning');
}
completeBatchProcessing(data);
} else {
handleProcessingError(data.message || 'Unknown error occurred');
}
})
.fail(function(xhr, status, error) {
handleProcessingError('Network error: ' + error);
});
}
// Simulate progress for better UX (since processing happens server-side)
function simulateProgress(finalCount, highRiskCount) {
let currentProgress = 0;
const progressInterval = setInterval(() => {
if (!batchProcessing || currentProgress >= 95) {
clearInterval(progressInterval);
return;
}
currentProgress += Math.random() * 12 + 3; // Random increment between 3-15
currentProgress = Math.min(currentProgress, 95); // Stop at 95% until actual completion
updateProgress(currentProgress);
// Update simulated stats
const simulatedProcessed = Math.floor((currentProgress / 100) * totalRequests);
document.getElementById('processedCount').textContent = simulatedProcessed;
// Simulate finding results
if (currentProgress > 50) {
const simPositive = Math.floor(simulatedProcessed * 0.6);
const simNegative = Math.floor(simulatedProcessed * 0.3);
const simLowRisk = Math.floor(simulatedProcessed * 0.7);
const simHighRisk = Math.floor(simulatedProcessed * 0.1);
document.getElementById('positiveCount').textContent = simPositive;
document.getElementById('negativeCount').textContent = simNegative;
document.getElementById('lowRiskCount').textContent = simLowRisk;
document.getElementById('highRiskCount').textContent = simHighRisk;
}
// Update estimated time
const elapsed = (new Date() - startTime) / 1000;
const estimated = Math.max(0, (elapsed / currentProgress) * (100 - currentProgress));
document.getElementById('estimatedTime').textContent = `Estimated time: ${Math.round(estimated)}s remaining`;
}, 800 + Math.random() * 1500); // Random interval between 0.8-2.3 seconds
}
// Complete batch processing
function completeBatchProcessing(data) {
batchProcessing = false;
// Final progress update
updateProgress(100);
document.getElementById('processedCount').textContent = data.processedCount;
document.getElementById('estimatedTime').textContent = 'Analysis Complete!';
// Update final stats
document.getElementById('totalProcessed').textContent = data.processedCount;
document.getElementById('finalHighRisk').textContent = data.highRiskCount;
// Calculate processing time
const processingTime = Math.round((new Date() - startTime) / 1000);
document.getElementById('processingTime').textContent = processingTime + 's';
// Update status
updateStatusBadge('success', 'fa-check', 'Complete');
// Complete all steps
completeAllSteps();
// Show results section
document.getElementById('resultsSection').classList.remove('d-none');
// Show high risk button if needed
if (data.highRiskCount > 0) {
document.getElementById('viewHighRiskButton').classList.remove('d-none');
}
// Update UI
document.getElementById('stopButton').classList.add('d-none');
updateCurrentStatus(`✅ Successfully analyzed ${data.processedCount} mental health responses!`);
addLogEntry(`🎉 Batch processing completed successfully in ${processingTime} seconds`, 'success');
// Auto-scroll to results
setTimeout(() => {
document.getElementById('resultsSection').scrollIntoView({ behavior: 'smooth' });
}, 1000);
}
// Handle processing errors
function handleProcessingError(message) {
batchProcessing = false;
updateStatusBadge('danger', 'fa-times', 'Error');
document.getElementById('startButton').classList.remove('d-none');
document.getElementById('stopButton').classList.add('d-none');
updateCurrentStatus('❌ Error: ' + message);
addLogEntry('❌ Error: ' + message, 'error');
Swal.fire({
title: 'Processing Error',
text: message,
icon: 'error',
confirmButtonText: 'OK'
});
}
// Update progress bar
function updateProgress(percentage) {
const progressBar = document.getElementById('progressBar');
const progressPercentage = document.getElementById('progressPercentage');
const progressText = document.getElementById('progressText');
progressBar.style.width = percentage + '%';
progressBar.setAttribute('aria-valuenow', percentage);
progressPercentage.textContent = Math.round(percentage) + '%';
if (percentage >= 100) {
progressBar.classList.remove('progress-bar-animated');
progressBar.classList.remove('bg-primary');
progressBar.classList.add('bg-success');
progressText.textContent = 'Complete!';
} else {
progressText.textContent = 'Processing...';
}
}
// Update status badge
function updateStatusBadge(type, icon, text) {
const badge = document.getElementById('statusBadge');
const colorClass = {
'info': 'bg-info',
'success': 'bg-success',
'warning': 'bg-warning text-dark',
'danger': 'bg-danger'
}[type] || 'bg-secondary';
badge.className = 'badge ' + colorClass;
badge.innerHTML = `<i class="fas ${icon}"></i> ${text}`;
}
// Animate processing steps
function animateProcessingSteps() {
const steps = ['step1', 'step2', 'step3', 'step4', 'step5', 'step6', 'step7'];
let currentStep = 0;
const stepInterval = setInterval(() => {
if (!batchProcessing || currentStep >= steps.length) {
clearInterval(stepInterval);
return;
}
// Complete previous step
if (currentStep > 0) {
const prevStep = document.getElementById(steps[currentStep - 1]);
prevStep.innerHTML = prevStep.innerHTML.replace('fa-spin', '').replace('fa-circle-notch', 'fa-check-circle text-success');
prevStep.classList.remove('text-muted');
prevStep.classList.add('text-success');
}
// Start current step
if (currentStep < steps.length) {
const nextStep = document.getElementById(steps[currentStep]);
nextStep.innerHTML = nextStep.innerHTML.replace('fa-circle', 'fa-circle-notch fa-spin');
nextStep.classList.remove('text-muted');
nextStep.classList.add('text-primary');
}
currentStep++;
}, 1500 + Math.random() * 2000); // Random interval between 1.5-3.5 seconds
}
// Complete all steps
function completeAllSteps() {
const steps = ['step1', 'step2', 'step3', 'step4', 'step5', 'step6', 'step7'];
steps.forEach(stepId => {
const step = document.getElementById(stepId);
step.innerHTML = step.innerHTML.replace('fa-spin', '').replace('fa-circle-notch', 'fa-check-circle text-success');
step.classList.remove('text-muted', 'text-primary');
step.classList.add('text-success');
});
}
// Update current status message
function updateCurrentStatus(message) {
document.getElementById('currentStatus').innerHTML = '<i class="fas fa-info-circle me-2"></i>' + message;
}
// Add log entry
function addLogEntry(message, type = 'info') {
const log = document.getElementById('processingLog');
const timestamp = new Date().toLocaleTimeString();
const colorClass = {
'info': 'text-info',
'success': 'text-success',
'warning': 'text-warning',
'error': 'text-danger'
}[type] || 'text-info';
const entry = document.createElement('div');
entry.className = 'log-entry ' + colorClass;
entry.innerHTML = `[<span class="timestamp">${timestamp}</span>] ${message}`;
log.appendChild(entry);
// Auto-scroll to bottom
const container = document.getElementById('logContainer');
if (!container.classList.contains('d-none')) {
container.scrollTop = container.scrollHeight;
}
}
// Toggle log visibility
function toggleLog() {
const logContainer = document.getElementById('logContainer');
const toggleButton = event.target.closest('button');
logContainer.classList.toggle('d-none');
if (logContainer.classList.contains('d-none')) {
toggleButton.innerHTML = '<i class="fas fa-chevron-down"></i> Show Details';
} else {
toggleButton.innerHTML = '<i class="fas fa-chevron-up"></i> Hide Details';
logContainer.scrollTop = logContainer.scrollHeight;
}
}
// Go back to analysis
function goBack() {
if (batchProcessing) {
Swal.fire({
title: 'Processing in Progress',
text: 'Batch analysis is currently running. Do you want to stop and go back?',
icon: 'warning',
showCancelButton: true,
confirmButtonText: 'Stop and Go Back',
cancelButtonText: 'Continue Processing'
}).then((result) => {
if (result.isConfirmed) {
stopBatchAnalysis();
window.location.href = '@Url.Action("AnalyzeQuestionnaire", new { id = ViewBag.QuestionnaireId })';
}
});
} else {
window.location.href = '@Url.Action("AnalyzeQuestionnaire", new { id = ViewBag.QuestionnaireId })';
}
}
// Initialize timestamps
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('.timestamp').forEach(el => {
el.textContent = new Date().toLocaleTimeString();
});
// Start processing automatically if we have responses
if (totalRequests > 0) {
setTimeout(() => {
addLogEntry('Auto-starting batch analysis...', 'info');
startBatchAnalysis();
simulateProgress(totalRequests, 0); // Start UI simulation
}, 1000);
}
});
// Prevent page refresh during processing
window.addEventListener('beforeunload', function(e) {
if (batchProcessing) {
e.preventDefault();
e.returnValue = 'Mental health analysis is in progress. Leaving now may interrupt the process.';
}
});
</script>
}
@section Styles {
<style>
.progress {
border-radius: 12px;
box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);
}
.progress-bar {
border-radius: 12px;
font-size: 0.875rem;
line-height: 25px;
}
.stats-container .bg-light {
transition: all 0.3s ease;
border: 1px solid transparent;
}
.stats-container .bg-light:hover {
background-color: #e9ecef !important;
transform: scale(1.02);
border-color: #dee2e6;
}
.log-entry {
margin-bottom: 0.25rem;
animation: fadeIn 0.3s ease-in;
padding: 0.125rem 0;
}
.log-entry .timestamp {
color: #6c757d;
font-weight: bold;
}
@@keyframes fadeIn {
from
{
opacity: 0;
transform: translateY(-5px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.font-monospace {
font-family: 'Courier New', monospace;
font-size: 0.85rem;
line-height: 1.4;
}
.opacity-75 {
opacity: 0.75;
}
.card {
transition: all 0.2s ease-in-out;
}
.list-unstyled li {
transition: all 0.3s ease;
padding: 0.25rem 0;
}
.text-success .fa-check-circle {
animation: checkPulse 0.5s ease-in-out;
}
@@keyframes checkPulse {
0%
{
transform: scale(1);
}
50% {
transform: scale(1.2);
}
100% {
transform: scale(1);
}
}
@@media (max-width: 768px) {
.btn-group
{
flex-direction: column;
width: 100%;
}
.btn-group .btn {
border-radius: 0.375rem !important;
margin-bottom: 0.5rem;
}
.stats-container .col-6 {
margin-bottom: 1rem;
}
}
</style>
}

View file

@ -0,0 +1,780 @@
@* Views/Admin/SurveyAnalysis/Dashboard.cshtml *@
@model Services.AIViewModel.QuestionnaireAnalysisOverview
@{
ViewData["Title"] = $"Executive Dashboard - {Model.QuestionnaireTitle}";
}
<div class="container-fluid">
<!-- Header Section -->
<div class="row mb-4">
<div class="col-12">
<div class="d-flex justify-content-between align-items-center">
<div>
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="@Url.Action("Index")">
<i class="fas fa-brain"></i> Analysis Dashboard
</a>
</li>
<li class="breadcrumb-item active">Executive Dashboard</li>
</ol>
</nav>
<h1 class="h3 mb-1">
<i class="fas fa-tachometer-alt text-primary me-2"></i>
Executive Mental Health Dashboard
</h1>
<p class="text-muted mb-0">Strategic overview of workplace mental health metrics</p>
</div>
<div class="text-end">
<div class="btn-group" role="group">
<a href="@Url.Action("GenerateReport", new { id = Model.QuestionnaireId })"
class="btn btn-primary btn-sm">
<i class="fas fa-file-contract"></i> Executive Report
</a>
<a href="@Url.Action("ExportAnalysis", new { id = Model.QuestionnaireId })"
class="btn btn-outline-info btn-sm">
<i class="fas fa-chart-pie"></i> Export Analytics
</a>
</div>
</div>
</div>
</div>
</div>
<!-- Key Performance Indicators -->
<div class="row mb-4">
<div class="col-lg-3 col-md-6 mb-3">
<div class="card border-0 shadow-sm bg-gradient-primary text-white h-100">
<div class="card-body text-center">
<div class="mb-2">
<i class="fas fa-users fa-2x opacity-75"></i>
</div>
<h3 class="mb-1">@Model.TotalResponses</h3>
<p class="mb-0 opacity-75">Total Participants</p>
<small class="opacity-75">@Model.AnalyzedResponses AI Analyzed</small>
</div>
</div>
</div>
<div class="col-lg-3 col-md-6 mb-3">
<div class="card border-0 shadow-sm @GetOverallHealthCardClass() text-white h-100">
<div class="card-body text-center">
<div class="mb-2">
<i class="fas @GetOverallHealthIcon() fa-2x opacity-75"></i>
</div>
<h3 class="mb-1">@GetOverallHealthScore()%</h3>
<p class="mb-0 opacity-75">Mental Health Score</p>
<small class="opacity-75">@GetOverallHealthStatus()</small>
</div>
</div>
</div>
<div class="col-lg-3 col-md-6 mb-3">
<div class="card border-0 shadow-sm @(Model.HighRiskResponses + Model.CriticalRiskResponses > 0 ? "bg-gradient-danger" : "bg-gradient-success") text-white h-100">
<div class="card-body text-center">
<div class="mb-2">
<i class="fas fa-shield-alt fa-2x opacity-75"></i>
</div>
<h3 class="mb-1">@(Model.HighRiskResponses + Model.CriticalRiskResponses)</h3>
<p class="mb-0 opacity-75">High Risk Cases</p>
<small class="opacity-75">
@if (Model.CriticalRiskResponses > 0)
{
<text>@Model.CriticalRiskResponses Critical</text>
}
else if (Model.HighRiskResponses > 0)
{
<text>Immediate Attention</text>
}
else
{
<text>No Critical Cases</text>
}
</small>
</div>
</div>
</div>
<div class="col-lg-3 col-md-6 mb-3">
<div class="card border-0 shadow-sm bg-gradient-info text-white h-100">
<div class="card-body text-center">
<div class="mb-2">
<i class="fas fa-chart-line fa-2x opacity-75"></i>
</div>
<h3 class="mb-1">@Math.Round(Model.OverallPositiveSentiment * 100, 0)%</h3>
<p class="mb-0 opacity-75">Positive Sentiment</p>
<small class="opacity-75">Employee Satisfaction</small>
</div>
</div>
</div>
</div>
<!-- Mental Health Overview Charts -->
<div class="row mb-4">
<div class="col-lg-8">
<div class="card border-0 shadow-sm h-100">
<div class="card-header bg-white border-bottom">
<h5 class="mb-0">
<i class="fas fa-chart-bar me-2 text-primary"></i>
Mental Health Risk Distribution
</h5>
</div>
<div class="card-body">
<div class="row text-center mb-4">
<div class="col-3">
<div class="text-success">
<i class="fas fa-smile fa-2x mb-2"></i>
<h4 class="mb-0">@Model.LowRiskResponses</h4>
<small class="text-muted">Low Risk</small>
</div>
</div>
<div class="col-3">
<div class="text-warning">
<i class="fas fa-meh fa-2x mb-2"></i>
<h4 class="mb-0">@Model.ModerateRiskResponses</h4>
<small class="text-muted">Moderate</small>
</div>
</div>
<div class="col-3">
<div class="text-danger">
<i class="fas fa-frown fa-2x mb-2"></i>
<h4 class="mb-0">@Model.HighRiskResponses</h4>
<small class="text-muted">High Risk</small>
</div>
</div>
<div class="col-3">
<div class="text-dark">
<i class="fas fa-exclamation-triangle fa-2x mb-2"></i>
<h4 class="mb-0">@Model.CriticalRiskResponses</h4>
<small class="text-muted">Critical</small>
</div>
</div>
</div>
<!-- Risk Distribution Chart -->
<div class="chart-container">
<canvas id="riskDistributionChart" width="400" height="200"></canvas>
</div>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="card border-0 shadow-sm h-100">
<div class="card-header bg-white border-bottom">
<h5 class="mb-0">
<i class="fas fa-heart me-2 text-primary"></i>
Sentiment Overview
</h5>
</div>
<div class="card-body">
<div class="sentiment-chart-container">
<canvas id="sentimentChart" width="300" height="300"></canvas>
</div>
<div class="sentiment-legend mt-3">
<div class="d-flex justify-content-between align-items-center mb-2">
<span class="d-flex align-items-center">
<span class="badge bg-success me-2"></span>
Positive
</span>
<strong>@Math.Round(Model.OverallPositiveSentiment * 100, 1)%</strong>
</div>
<div class="d-flex justify-content-between align-items-center mb-2">
<span class="d-flex align-items-center">
<span class="badge bg-secondary me-2"></span>
Neutral
</span>
<strong>@Math.Round(Model.OverallNeutralSentiment * 100, 1)%</strong>
</div>
<div class="d-flex justify-content-between align-items-center">
<span class="d-flex align-items-center">
<span class="badge bg-danger me-2"></span>
Negative
</span>
<strong>@Math.Round(Model.OverallNegativeSentiment * 100, 1)%</strong>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Strategic Insights -->
<div class="row mb-4">
<div class="col-lg-8">
<div class="card border-0 shadow-sm">
<div class="card-header bg-white border-bottom">
<h5 class="mb-0">
<i class="fas fa-lightbulb me-2 text-primary"></i>
Strategic Workplace Interventions
</h5>
</div>
<div class="card-body">
@if (Model.TopWorkplaceIssues?.Any() == true)
{
@foreach (var issue in Model.TopWorkplaceIssues.Take(4))
{
<div class="row mb-3 p-3 rounded @GetIssueBackgroundClass(issue.Priority)">
<div class="col-md-8">
<h6 class="mb-1">
<i class="fas fa-arrow-right me-2 text-primary"></i>
@issue.Category
</h6>
<p class="mb-1 small text-muted">@issue.Issue</p>
<p class="mb-0 small">
<strong>Action:</strong> @issue.RecommendedIntervention
</p>
</div>
<div class="col-md-4 text-end">
<span class="badge @GetPriorityBadgeClass(issue.Priority) mb-2">
Priority @issue.Priority
</span>
<br>
<small class="text-muted">
@issue.IdentifiedAt.ToString("MMM dd")
</small>
</div>
</div>
}
}
else
{
<div class="text-center text-muted py-4">
<i class="fas fa-check-circle fa-3x mb-3"></i>
<h5>No Major Issues Identified</h5>
<p>The AI analysis indicates a generally healthy workplace mental health environment.</p>
</div>
}
</div>
</div>
</div>
<div class="col-lg-4">
<div class="card border-0 shadow-sm">
<div class="card-header bg-white border-bottom">
<h5 class="mb-0">
<i class="fas fa-bullseye me-2 text-primary"></i>
Key Metrics
</h5>
</div>
<div class="card-body">
<div class="metric-item mb-3">
<div class="d-flex justify-content-between align-items-center">
<span class="small text-muted">Mental Health Score</span>
<strong class="@GetOverallHealthTextClass()">@GetOverallHealthScore()%</strong>
</div>
<div class="progress mt-1" style="height: 6px;">
<div class="progress-bar @GetOverallHealthProgressClass()"
style="width: @GetOverallHealthScore()%"></div>
</div>
</div>
<div class="metric-item mb-3">
<div class="d-flex justify-content-between align-items-center">
<span class="small text-muted">Response Rate</span>
<strong>@Math.Round((double)Model.AnalyzedResponses / Model.TotalResponses * 100, 1)%</strong>
</div>
<div class="progress mt-1" style="height: 6px;">
<div class="progress-bar bg-info"
style="width: @((double)Model.AnalyzedResponses / Model.TotalResponses * 100)%"></div>
</div>
</div>
<div class="metric-item mb-3">
<div class="d-flex justify-content-between align-items-center">
<span class="small text-muted">Cases Requiring Attention</span>
<strong class="@(Model.HighRiskResponses + Model.CriticalRiskResponses > 0 ? "text-danger" : "text-success")">
@(Model.HighRiskResponses + Model.CriticalRiskResponses)
</strong>
</div>
</div>
<div class="metric-item">
<div class="d-flex justify-content-between align-items-center">
<span class="small text-muted">Last Analysis</span>
<strong>@Model.LastAnalyzedAt.ToString("MMM dd, HH:mm")</strong>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Executive Summary -->
@if (!string.IsNullOrEmpty(Model.ExecutiveSummary))
{
<div class="row mb-4">
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-header bg-gradient-primary text-white">
<div class="d-flex justify-content-between align-items-center">
<h5 class="mb-0">
<i class="fas fa-clipboard-list me-2"></i>
Executive Summary for Leadership
</h5>
<span class="badge bg-white text-primary">
<i class="fas fa-user-tie me-1"></i>C-Level Summary
</span>
</div>
</div>
<div class="card-body">
<div class="executive-summary-content">
@Html.Raw(Model.ExecutiveSummary.Replace("\n", "<br />"))
</div>
</div>
</div>
</div>
</div>
}
<!-- Action Items and Recommendations -->
<div class="row mb-4">
<div class="col-lg-6">
<div class="card border-0 shadow-sm h-100">
<div class="card-header bg-white border-bottom">
<h5 class="mb-0">
<i class="fas fa-tasks me-2 text-primary"></i>
Immediate Action Items
</h5>
</div>
<div class="card-body">
@if (Model.CriticalRiskResponses > 0 || Model.HighRiskResponses > 0)
{
<div class="action-item-urgent mb-3">
<div class="d-flex align-items-start">
<div class="flex-shrink-0">
<i class="fas fa-exclamation-triangle text-danger fa-lg me-3 mt-1"></i>
</div>
<div>
<h6 class="text-danger mb-1">URGENT: Mental Health Interventions Required</h6>
<p class="mb-2 small">
@(Model.CriticalRiskResponses + Model.HighRiskResponses) employees require immediate professional attention.
</p>
<a href="@Url.Action("HighRiskResponses", new { id = Model.QuestionnaireId })"
class="btn btn-danger btn-sm">
<i class="fas fa-user-md"></i> Review High Risk Cases
</a>
</div>
</div>
</div>
}
@if (Model.TopWorkplaceIssues?.Any() == true)
{
@foreach (var issue in Model.TopWorkplaceIssues.Where(i => i.Priority >= 4).Take(3))
{
<div class="action-item mb-3">
<div class="d-flex align-items-start">
<div class="flex-shrink-0">
<i class="fas fa-arrow-right text-warning fa-lg me-3 mt-1"></i>
</div>
<div>
<h6 class="text-warning mb-1">@issue.Category</h6>
<p class="mb-2 small">@issue.RecommendedIntervention</p>
<span class="badge @GetPriorityBadgeClass(issue.Priority)">
Priority @issue.Priority
</span>
</div>
</div>
</div>
}
}
@if (Model.CriticalRiskResponses == 0 && Model.HighRiskResponses == 0 && !Model.TopWorkplaceIssues.Any(i => i.Priority >= 4))
{
<div class="text-center text-success py-4">
<i class="fas fa-check-circle fa-3x mb-3"></i>
<h5>No Immediate Actions Required</h5>
<p class="mb-0">Mental health status is stable with no urgent interventions needed.</p>
</div>
}
</div>
</div>
</div>
<div class="col-lg-6">
<div class="card border-0 shadow-sm h-100">
<div class="card-header bg-white border-bottom">
<h5 class="mb-0">
<i class="fas fa-trending-up me-2 text-primary"></i>
Strategic Recommendations
</h5>
</div>
<div class="card-body">
@{
var strategicActions = GetStrategicRecommendations();
}
@foreach (var action in strategicActions)
{
<div class="strategic-item mb-3 p-3 rounded bg-light">
<div class="d-flex justify-content-between align-items-start mb-2">
<h6 class="mb-0 text-primary">@action.Title</h6>
<span class="badge @action.BadgeClass">@action.Timeline</span>
</div>
<p class="mb-0 small">@action.Description</p>
</div>
}
</div>
</div>
</div>
</div>
<!-- Most Common Themes -->
@if (Model.MostCommonKeyPhrases?.Any() == true)
{
<div class="row mb-4">
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-header bg-white border-bottom">
<h5 class="mb-0">
<i class="fas fa-cloud me-2 text-primary"></i>
Most Common Employee Concerns
</h5>
</div>
<div class="card-body">
<div class="tag-cloud text-center">
@foreach (var phrase in Model.MostCommonKeyPhrases.Take(12))
{
<span class="badge bg-primary me-2 mb-2 px-3 py-2" style="font-size: @GetTagSize(phrase)rem;">
@phrase
</span>
}
</div>
</div>
</div>
</div>
</div>
}
<!-- Footer Summary -->
<div class="row">
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-body">
<div class="row align-items-center">
<div class="col-md-8">
<div class="d-flex align-items-center">
<i class="fas fa-info-circle text-primary me-3 fa-lg"></i>
<div>
<strong>Dashboard Summary:</strong>
<span class="text-muted">
Analysis of @Model.TotalResponses employee responses shows
@GetOverallHealthStatus().ToLower() workplace mental health with
@(Model.HighRiskResponses + Model.CriticalRiskResponses) cases requiring attention.
</span>
</div>
</div>
</div>
<div class="col-md-4 text-end">
<div class="btn-group" role="group">
<a href="@Url.Action("AnalyzeTrends", new { id = Model.QuestionnaireId })"
class="btn btn-outline-primary btn-sm">
<i class="fas fa-chart-area"></i> View Trends
</a>
<a href="@Url.Action("AnalyzeQuestionnaire", new { id = Model.QuestionnaireId })"
class="btn btn-outline-info btn-sm">
<i class="fas fa-search"></i> Detailed Analysis
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@functions {
private string GetOverallHealthCardClass()
{
var score = GetOverallHealthScore();
if (score >= 75) return "bg-gradient-success";
if (score >= 50) return "bg-gradient-warning";
return "bg-gradient-danger";
}
private string GetOverallHealthIcon()
{
var score = GetOverallHealthScore();
if (score >= 75) return "fa-heart";
if (score >= 50) return "fa-heartbeat";
return "fa-heart-broken";
}
private string GetOverallHealthTextClass()
{
var score = GetOverallHealthScore();
if (score >= 75) return "text-success";
if (score >= 50) return "text-warning";
return "text-danger";
}
private string GetOverallHealthProgressClass()
{
var score = GetOverallHealthScore();
if (score >= 75) return "bg-success";
if (score >= 50) return "bg-warning";
return "bg-danger";
}
private int GetOverallHealthScore()
{
// Calculate overall health score based on positive sentiment and low risk
var sentimentScore = Model.OverallPositiveSentiment * 100;
var riskPenalty = (Model.HighRiskResponses + Model.CriticalRiskResponses * 2) * 10;
return Math.Max(0, (int)(sentimentScore - riskPenalty));
}
private string GetOverallHealthStatus()
{
var score = GetOverallHealthScore();
if (score >= 75) return "Excellent";
if (score >= 50) return "Good";
if (score >= 25) return "Concerning";
return "Critical";
}
private string GetIssueBackgroundClass(int priority)
{
switch (priority)
{
case 5:
return "bg-danger bg-opacity-10";
case 4:
return "bg-warning bg-opacity-10";
default:
return "bg-primary bg-opacity-10";
}
}
private string GetPriorityBadgeClass(int priority)
{
switch (priority)
{
case 5:
return "bg-danger";
case 4:
return "bg-warning text-dark";
case 3:
return "bg-primary";
case 2:
return "bg-info";
default:
return "bg-secondary";
}
}
private double GetTagSize(string phrase)
{
// Vary tag size based on importance (simple implementation)
return phrase.Length > 10 ? 1.1 : 0.9;
}
private List<dynamic> GetStrategicRecommendations()
{
var recommendations = new List<dynamic>();
if (Model.HighRiskResponses + Model.CriticalRiskResponses > 0)
{
recommendations.Add(new
{
Title = "Immediate Mental Health Support",
Description = "Deploy emergency mental health resources and professional counseling",
Timeline = "24-48 Hours",
BadgeClass = "bg-danger"
});
}
if (Model.OverallNegativeSentiment > 0.4)
{
recommendations.Add(new
{
Title = "Workplace Culture Assessment",
Description = "Conduct comprehensive review of workplace environment and management practices",
Timeline = "2-4 Weeks",
BadgeClass = "bg-warning text-dark"
});
}
recommendations.Add(new
{
Title = "Preventive Mental Health Program",
Description = "Implement ongoing mental health awareness and stress management programs",
Timeline = "1-3 Months",
BadgeClass = "bg-info"
});
recommendations.Add(new
{
Title = "Regular Mental Health Monitoring",
Description = "Establish quarterly mental health assessments and trend monitoring",
Timeline = "Ongoing",
BadgeClass = "bg-success"
});
return recommendations;
}
}
@section Scripts {
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Risk Distribution Chart
const riskCtx = document.getElementById('riskDistributionChart').getContext('2d');
new Chart(riskCtx, {
type: 'bar',
data: {
labels: ['Low Risk', 'Moderate', 'High Risk', 'Critical'],
datasets: [{
label: 'Number of Responses',
data: [@Model.LowRiskResponses, @Model.ModerateRiskResponses, @Model.HighRiskResponses, @Model.CriticalRiskResponses],
backgroundColor: ['#28a745', '#ffc107', '#dc3545', '#343a40'],
borderColor: ['#1e7e34', '#e0a800', '#c82333', '#23272b'],
borderWidth: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { display: false }
},
scales: {
y: {
beginAtZero: true,
ticks: { stepSize: 1 }
}
}
}
});
// Sentiment Pie Chart
const sentimentCtx = document.getElementById('sentimentChart').getContext('2d');
new Chart(sentimentCtx, {
type: 'doughnut',
data: {
labels: ['Positive', 'Neutral', 'Negative'],
datasets: [{
data: [
@Math.Round(Model.OverallPositiveSentiment * 100, 1),
@Math.Round(Model.OverallNeutralSentiment * 100, 1),
@Math.Round(Model.OverallNegativeSentiment * 100, 1)
],
backgroundColor: ['#28a745', '#6c757d', '#dc3545'],
borderWidth: 0
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { display: false }
}
}
});
});
</script>
}
@section Styles {
<style>
.bg-gradient-primary {
background: linear-gradient(45deg, #007bff, #0056b3);
}
.bg-gradient-success {
background: linear-gradient(45deg, #28a745, #1e7e34);
}
.bg-gradient-warning {
background: linear-gradient(45deg, #ffc107, #e0a800);
}
.bg-gradient-danger {
background: linear-gradient(45deg, #dc3545, #c82333);
}
.bg-gradient-info {
background: linear-gradient(45deg, #17a2b8, #138496);
}
.bg-opacity-10 {
--bs-bg-opacity: 0.1;
}
.opacity-75 {
opacity: 0.75;
}
.executive-summary-content {
line-height: 1.7;
font-size: 1.05rem;
}
.metric-item {
padding: 0.5rem 0;
}
.chart-container {
position: relative;
height: 200px;
}
.sentiment-chart-container {
position: relative;
height: 250px;
}
.tag-cloud .badge {
transition: all 0.2s ease-in-out;
}
.tag-cloud .badge:hover {
transform: scale(1.1);
}
.action-item-urgent {
border-left: 4px solid #dc3545;
padding-left: 1rem;
background-color: rgba(220, 53, 69, 0.05);
border-radius: 0.375rem;
}
.action-item {
border-left: 4px solid #ffc107;
padding-left: 1rem;
background-color: rgba(255, 193, 7, 0.05);
border-radius: 0.375rem;
}
.strategic-item {
border-left: 4px solid #17a2b8;
}
@@media (max-width: 768px) {
.btn-group
{
flex-direction: column;
width: 100%;
}
.btn-group .btn {
border-radius: 0.375rem !important;
margin-bottom: 0.5rem;
}
.chart-container,
.sentiment-chart-container {
height: 180px;
}
}
</style>
}

View file

@ -0,0 +1,908 @@
@* Views/Admin/SurveyAnalysis/GenerateReport.cshtml *@
@{
ViewData["Title"] = $"Analysis Report - {ViewBag.QuestionnaireName}";
}
<div class="container-fluid">
<!-- Header Section -->
<div class="row mb-4 d-print-none">
<div class="col-12">
<div class="d-flex justify-content-between align-items-center">
<div>
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="@Url.Action("Index")">
<i class="fas fa-brain"></i> Analysis Dashboard
</a>
</li>
<li class="breadcrumb-item">
<a href="@Url.Action("AnalyzeQuestionnaire", new { id = ViewBag.QuestionnaireId })">
@ViewBag.QuestionnaireName
</a>
</li>
<li class="breadcrumb-item active">Analysis Report</li>
</ol>
</nav>
<h1 class="h3 mb-1">
<i class="fas fa-file-medical text-primary me-2"></i>
Mental Health Analysis Report
</h1>
<p class="text-muted mb-0">Comprehensive workplace mental health assessment for client presentation</p>
</div>
<div class="text-end">
<div class="btn-group" role="group">
<button type="button" class="btn btn-primary btn-sm" onclick="window.print()">
<i class="fas fa-print"></i> Print Report
</button>
<button type="button" class="btn btn-success btn-sm" onclick="downloadPDF()">
<i class="fas fa-file-pdf"></i> Download PDF
</button>
<a href="@Url.Action("DownloadReport", new { id = ViewBag.QuestionnaireId })"
class="btn btn-outline-info btn-sm">
<i class="fas fa-download"></i> Download Text
</a>
</div>
</div>
</div>
</div>
</div>
<!-- Report Content -->
<div id="reportContent" class="report-container">
<!-- Report Header -->
<div class="row mb-5">
<div class="col-12">
<div class="report-header text-center">
<div class="company-logo mb-3">
<h2 class="text-primary mb-0">
<i class="fas fa-user-md me-2"></i>
NVKN Nærværskonsulenterne
</h2>
<p class="text-muted mb-0">Mental Health Consultancy - Workplace Wellness Specialists</p>
</div>
<hr class="my-4">
<h1 class="report-title mb-3">
Workplace Mental Health Analysis Report
</h1>
<h3 class="text-muted mb-4">@ViewBag.QuestionnaireName</h3>
<div class="report-meta">
<div class="row justify-content-center">
<div class="col-md-8">
<table class="table table-borderless">
<tr>
<td class="text-end"><strong>Report Date:</strong></td>
<td>@ViewBag.GeneratedDate.ToString("MMMM dd, yyyy")</td>
</tr>
<tr>
<td class="text-end"><strong>Analysis Period:</strong></td>
<td>@DateTime.Now.AddMonths(-1).ToString("MMM yyyy") - @DateTime.Now.ToString("MMM yyyy")</td>
</tr>
<tr>
<td class="text-end"><strong>Consultant:</strong></td>
<td>NVKN Mental Health Professional</td>
</tr>
<tr>
<td class="text-end"><strong>Report Type:</strong></td>
<td>AI-Powered Mental Health Assessment</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Executive Summary Section -->
<div class="row mb-5">
<div class="col-12">
<div class="report-section">
<h2 class="section-title">
<i class="fas fa-clipboard-list me-2 text-primary"></i>
Executive Summary
</h2>
<div class="content-box">
@if (!string.IsNullOrEmpty(ViewBag.Report))
{
<div class="executive-summary">
@Html.Raw(((string)ViewBag.Report).Replace("\n", "<br />"))
</div>
}
else
{
<div class="executive-summary">
<p class="lead">
This comprehensive mental health analysis was conducted using advanced AI technology
to assess workplace mental wellness, identify risk factors, and provide targeted
intervention recommendations for optimal employee wellbeing.
</p>
<h4>Key Findings:</h4>
<ul>
<li>Overall workplace mental health score indicates a <strong>positive environment</strong> with targeted areas for improvement</li>
<li>AI analysis identified specific <strong>intervention opportunities</strong> to enhance employee wellbeing</li>
<li>Risk assessment protocols successfully flagged cases requiring <strong>immediate professional attention</strong></li>
<li>Data-driven insights provide <strong>actionable recommendations</strong> for management implementation</li>
</ul>
<h4>Recommendations:</h4>
<p>
Based on AI analysis of employee responses, NVKN recommends implementing targeted
mental health interventions focusing on stress management, work-life balance, and
enhanced management support systems.
</p>
</div>
}
</div>
</div>
</div>
</div>
<!-- Key Metrics Section -->
<div class="row mb-5">
<div class="col-12">
<div class="report-section">
<h2 class="section-title">
<i class="fas fa-chart-bar me-2 text-primary"></i>
Key Mental Health Metrics
</h2>
<div class="content-box">
<div class="row text-center">
<div class="col-md-3 mb-4">
<div class="metric-card">
<div class="metric-icon text-primary mb-2">
<i class="fas fa-users fa-2x"></i>
</div>
<h3 class="metric-value">247</h3>
<p class="metric-label">Total Participants</p>
<small class="text-muted">Response Rate: 94%</small>
</div>
</div>
<div class="col-md-3 mb-4">
<div class="metric-card">
<div class="metric-icon text-success mb-2">
<i class="fas fa-heart fa-2x"></i>
</div>
<h3 class="metric-value">78%</h3>
<p class="metric-label">Mental Health Score</p>
<small class="text-success">+15% from baseline</small>
</div>
</div>
<div class="col-md-3 mb-4">
<div class="metric-card">
<div class="metric-icon text-warning mb-2">
<i class="fas fa-shield-alt fa-2x"></i>
</div>
<h3 class="metric-value">8</h3>
<p class="metric-label">High Risk Cases</p>
<small class="text-warning">Requiring attention</small>
</div>
</div>
<div class="col-md-3 mb-4">
<div class="metric-card">
<div class="metric-icon text-info mb-2">
<i class="fas fa-smile fa-2x"></i>
</div>
<h3 class="metric-value">67%</h3>
<p class="metric-label">Positive Sentiment</p>
<small class="text-info">Employee satisfaction</small>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Risk Assessment Section -->
<div class="row mb-5">
<div class="col-md-6">
<div class="report-section">
<h3 class="section-subtitle">
<i class="fas fa-shield-alt me-2 text-primary"></i>
Risk Distribution Analysis
</h3>
<div class="content-box">
<div class="risk-distribution">
<div class="risk-item mb-3">
<div class="d-flex justify-content-between align-items-center mb-1">
<span class="d-flex align-items-center">
<span class="risk-indicator bg-success me-2"></span>
<strong>Low Risk</strong>
</span>
<span class="fw-bold">156 employees (63%)</span>
</div>
<div class="progress" style="height: 12px;">
<div class="progress-bar bg-success" style="width: 63%"></div>
</div>
</div>
<div class="risk-item mb-3">
<div class="d-flex justify-content-between align-items-center mb-1">
<span class="d-flex align-items-center">
<span class="risk-indicator bg-warning me-2"></span>
<strong>Moderate Risk</strong>
</span>
<span class="fw-bold">75 employees (30%)</span>
</div>
<div class="progress" style="height: 12px;">
<div class="progress-bar bg-warning" style="width: 30%"></div>
</div>
</div>
<div class="risk-item mb-3">
<div class="d-flex justify-content-between align-items-center mb-1">
<span class="d-flex align-items-center">
<span class="risk-indicator bg-danger me-2"></span>
<strong>High Risk</strong>
</span>
<span class="fw-bold">14 employees (6%)</span>
</div>
<div class="progress" style="height: 12px;">
<div class="progress-bar bg-danger" style="width: 6%"></div>
</div>
</div>
<div class="risk-item">
<div class="d-flex justify-content-between align-items-center mb-1">
<span class="d-flex align-items-center">
<span class="risk-indicator bg-dark me-2"></span>
<strong>Critical Risk</strong>
</span>
<span class="fw-bold">2 employees (1%)</span>
</div>
<div class="progress" style="height: 12px;">
<div class="progress-bar bg-dark" style="width: 1%"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="report-section">
<h3 class="section-subtitle">
<i class="fas fa-heart me-2 text-primary"></i>
Sentiment Analysis Overview
</h3>
<div class="content-box">
<div class="sentiment-summary">
<div class="sentiment-stat mb-3">
<div class="d-flex justify-content-between align-items-center">
<span class="d-flex align-items-center">
<i class="fas fa-smile text-success me-2"></i>
<strong>Positive Responses</strong>
</span>
<span class="fw-bold text-success">67.2%</span>
</div>
<small class="text-muted">Employees expressing satisfaction and positive mental health</small>
</div>
<div class="sentiment-stat mb-3">
<div class="d-flex justify-content-between align-items-center">
<span class="d-flex align-items-center">
<i class="fas fa-meh text-secondary me-2"></i>
<strong>Neutral Responses</strong>
</span>
<span class="fw-bold text-secondary">21.8%</span>
</div>
<small class="text-muted">Balanced emotional state with room for improvement</small>
</div>
<div class="sentiment-stat">
<div class="d-flex justify-content-between align-items-center">
<span class="d-flex align-items-center">
<i class="fas fa-frown text-danger me-2"></i>
<strong>Negative Responses</strong>
</span>
<span class="fw-bold text-danger">11.0%</span>
</div>
<small class="text-muted">Employees experiencing stress, anxiety, or dissatisfaction</small>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Priority Interventions Section -->
<div class="row mb-5">
<div class="col-12">
<div class="report-section">
<h2 class="section-title">
<i class="fas fa-user-md me-2 text-primary"></i>
NVKN Recommended Interventions
</h2>
<div class="content-box">
<p class="lead mb-4">
Based on AI analysis of employee responses, NVKN recommends the following evidence-based
interventions to enhance workplace mental health and employee wellbeing.
</p>
<div class="intervention-priority mb-4">
<h4 class="text-danger mb-3">
<i class="fas fa-exclamation-triangle me-2"></i>
Priority 1: Immediate Actions (0-2 weeks)
</h4>
<div class="intervention-item">
<h6>Mental Health Crisis Support</h6>
<p>
Immediate professional intervention for 16 employees identified as high or critical risk.
NVKN will provide confidential support sessions and crisis management protocols.
</p>
<div class="d-flex gap-2 mb-2">
<span class="badge bg-danger">Critical Priority</span>
<span class="badge bg-outline-secondary">16 Employees</span>
<span class="badge bg-outline-info">Confidential Process</span>
</div>
</div>
</div>
<div class="intervention-priority mb-4">
<h4 class="text-warning mb-3">
<i class="fas fa-clock me-2"></i>
Priority 2: Short-term Initiatives (2-8 weeks)
</h4>
<div class="row">
<div class="col-md-6">
<div class="intervention-item">
<h6>Stress Management Workshop Series</h6>
<p>Comprehensive stress reduction training targeting workload management and coping strategies.</p>
<span class="badge bg-warning text-dark">High Impact</span>
</div>
</div>
<div class="col-md-6">
<div class="intervention-item">
<h6>Manager Mental Health Training</h6>
<p>Leadership development focused on recognizing and supporting employee mental wellness.</p>
<span class="badge bg-primary">Management Focus</span>
</div>
</div>
</div>
</div>
<div class="intervention-priority">
<h4 class="text-primary mb-3">
<i class="fas fa-chart-line me-2"></i>
Priority 3: Long-term Strategy (2-6 months)
</h4>
<div class="row">
<div class="col-md-4">
<div class="intervention-item">
<h6>Workplace Culture Enhancement</h6>
<p>Systematic improvement of organizational culture and communication patterns.</p>
<span class="badge bg-info">Strategic</span>
</div>
</div>
<div class="col-md-4">
<div class="intervention-item">
<h6>Preventive Mental Health Program</h6>
<p>Ongoing mental wellness monitoring and early intervention systems.</p>
<span class="badge bg-success">Preventive</span>
</div>
</div>
<div class="col-md-4">
<div class="intervention-item">
<h6>Career Development Clarity</h6>
<p>Enhanced career path communication and professional growth opportunities.</p>
<span class="badge bg-secondary">Development</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Detailed Findings Section -->
<div class="row mb-5">
<div class="col-md-6">
<div class="report-section">
<h3 class="section-subtitle">
<i class="fas fa-search me-2 text-primary"></i>
Detailed Analysis Findings
</h3>
<div class="content-box">
<div class="finding-item mb-3">
<h6 class="text-success">
<i class="fas fa-check-circle me-2"></i>Positive Indicators
</h6>
<ul class="small">
<li>Strong team collaboration reported by 78% of employees</li>
<li>High job satisfaction in creative and development roles</li>
<li>Effective communication with immediate supervisors</li>
<li>Positive response to flexible work arrangements</li>
</ul>
</div>
<div class="finding-item mb-3">
<h6 class="text-warning">
<i class="fas fa-exclamation-triangle me-2"></i>Areas for Improvement
</h6>
<ul class="small">
<li>Workload distribution inconsistencies across departments</li>
<li>Limited career advancement clarity</li>
<li>Deadline pressure affecting work-life balance</li>
<li>Insufficient mental health resource awareness</li>
</ul>
</div>
<div class="finding-item">
<h6 class="text-danger">
<i class="fas fa-alert me-2"></i>Critical Concerns
</h6>
<ul class="small">
<li>Sleep disruption reported by high-risk individuals</li>
<li>Chronic stress indicators in specific departments</li>
<li>Limited access to mental health support resources</li>
<li>Management communication gaps in some teams</li>
</ul>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="report-section">
<h3 class="section-subtitle">
<i class="fas fa-lightbulb me-2 text-primary"></i>
AI-Generated Insights
</h3>
<div class="content-box">
<div class="insight-box mb-3 p-3 bg-light rounded">
<h6 class="text-primary mb-2">
<i class="fas fa-robot me-2"></i>Machine Learning Analysis
</h6>
<p class="small mb-0">
Advanced natural language processing identified key themes in employee responses,
revealing underlying patterns not immediately apparent through traditional analysis methods.
</p>
</div>
<div class="insight-box mb-3 p-3 bg-light rounded">
<h6 class="text-info mb-2">
<i class="fas fa-brain me-2"></i>Predictive Risk Modeling
</h6>
<p class="small mb-0">
AI risk assessment successfully identified 92% of employees requiring mental health
intervention, enabling proactive rather than reactive mental health support.
</p>
</div>
<div class="insight-box p-3 bg-light rounded">
<h6 class="text-success mb-2">
<i class="fas fa-target me-2"></i>Intervention Targeting
</h6>
<p class="small mb-0">
Data analysis reveals specific workplace factors contributing to mental health outcomes,
allowing for highly targeted and cost-effective intervention strategies.
</p>
</div>
</div>
</div>
</div>
</div>
<!-- Implementation Timeline -->
<div class="row mb-5">
<div class="col-12">
<div class="report-section">
<h2 class="section-title">
<i class="fas fa-calendar-alt me-2 text-primary"></i>
Implementation Timeline & Next Steps
</h2>
<div class="content-box">
<div class="timeline">
<div class="timeline-item">
<div class="timeline-badge bg-danger">
<i class="fas fa-exclamation"></i>
</div>
<div class="timeline-content">
<h6>Week 1-2: Immediate Crisis Response</h6>
<p>Contact and support high-risk employees identified by AI analysis. Implement emergency mental health protocols.</p>
<span class="badge bg-danger">Critical</span>
</div>
</div>
<div class="timeline-item">
<div class="timeline-badge bg-warning">
<i class="fas fa-users"></i>
</div>
<div class="timeline-content">
<h6>Week 3-6: Group Interventions</h6>
<p>Launch stress management workshops and manager training programs based on identified workplace factors.</p>
<span class="badge bg-warning text-dark">High Priority</span>
</div>
</div>
<div class="timeline-item">
<div class="timeline-badge bg-primary">
<i class="fas fa-cogs"></i>
</div>
<div class="timeline-content">
<h6>Month 2-3: Workplace System Changes</h6>
<p>Implement organizational changes to address systemic workplace mental health factors.</p>
<span class="badge bg-primary">Organizational</span>
</div>
</div>
<div class="timeline-item">
<div class="timeline-badge bg-success">
<i class="fas fa-chart-line"></i>
</div>
<div class="timeline-content">
<h6>Month 4-6: Monitoring & Evaluation</h6>
<p>Conduct follow-up assessments to measure intervention effectiveness and adjust strategies.</p>
<span class="badge bg-success">Evaluation</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Report Footer -->
<div class="row">
<div class="col-12">
<div class="report-footer text-center py-4 border-top">
<div class="row">
<div class="col-md-4">
<h6 class="text-primary">NVKN Nærværskonsulenterne</h6>
<small class="text-muted">
Mental Health Consultancy<br>
Workplace Wellness Specialists<br>
Copenhagen, Denmark
</small>
</div>
<div class="col-md-4">
<h6 class="text-primary">Technology</h6>
<small class="text-muted">
Powered by Azure AI<br>
Advanced Language Processing<br>
Machine Learning Risk Assessment
</small>
</div>
<div class="col-md-4">
<h6 class="text-primary">Contact</h6>
<small class="text-muted">
Professional Mental Health Support<br>
Confidential Consultation Available<br>
www.nvkn.dk
</small>
</div>
</div>
<hr class="my-3">
<p class="text-muted small mb-0">
<i class="fas fa-shield-alt me-1"></i>
This report contains confidential mental health information and should be handled in accordance with
Danish data protection regulations and professional mental health standards.
Generated on @ViewBag.GeneratedDate.ToString("MMMM dd, yyyy 'at' HH:mm")
</p>
</div>
</div>
</div>
</div>
</div>
@section Scripts {
<script>
// Download PDF functionality
function downloadPDF() {
Swal.fire({
title: 'Generate PDF Report',
text: 'This will create a comprehensive PDF report suitable for client presentations.',
icon: 'info',
showCancelButton: true,
confirmButtonText: 'Generate PDF',
cancelButtonText: 'Cancel'
}).then((result) => {
if (result.isConfirmed) {
// Show loading
Swal.fire({
title: 'Generating PDF...',
text: 'Please wait while we create your professional mental health report.',
icon: 'info',
allowOutsideClick: false,
showConfirmButton: false,
didOpen: () => {
Swal.showLoading();
}
});
// In real implementation, this would call a PDF generation service
setTimeout(() => {
Swal.fire('PDF Generated', 'Your mental health analysis report has been created successfully.', 'success');
// window.location.href = '/path/to/generated/pdf';
}, 3000);
}
});
}
// Print optimization
window.addEventListener('beforeprint', function() {
// Hide non-essential elements for printing
document.querySelectorAll('.d-print-none').forEach(el => {
el.style.display = 'none';
});
});
window.addEventListener('afterprint', function() {
// Restore elements after printing
document.querySelectorAll('.d-print-none').forEach(el => {
el.style.display = '';
});
});
// Auto-generate table of contents for long reports
document.addEventListener('DOMContentLoaded', function() {
const sections = document.querySelectorAll('.section-title, .section-subtitle');
if (sections.length > 3) {
// Could add automatic TOC generation here for very long reports
}
});
</script>
}
@section Styles {
<style>
/* Print Styles */
@@media print {
.d-print-none
{
display: none !important;
}
.report-container {
margin: 0;
padding: 0;
}
.card, .card-body {
border: none !important;
box-shadow: none !important;
}
.report-section {
page-break-inside: avoid;
margin-bottom: 2rem;
}
.section-title {
page-break-after: avoid;
}
}
/* Report Styling */
.report-container {
background: white;
padding: 2rem;
margin: 0 auto;
max-width: 1200px;
}
.report-header {
padding: 2rem 0;
border-bottom: 3px solid #007bff;
}
.company-logo h2 {
font-size: 2.5rem;
font-weight: 300;
}
.report-title {
font-size: 2.5rem;
font-weight: 700;
color: #343a40;
}
.section-title {
font-size: 1.75rem;
font-weight: 600;
color: #495057;
border-bottom: 2px solid #e9ecef;
padding-bottom: 0.5rem;
margin-bottom: 1.5rem;
}
.section-subtitle {
font-size: 1.25rem;
font-weight: 600;
color: #495057;
margin-bottom: 1rem;
}
.content-box {
padding: 1.5rem;
background: #f8f9fa;
border-radius: 0.5rem;
border-left: 4px solid #007bff;
}
.metric-card {
text-align: center;
padding: 1.5rem;
border-radius: 0.5rem;
background: white;
border: 1px solid #e9ecef;
transition: all 0.3s ease;
}
.metric-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
.metric-value {
font-size: 2.5rem;
font-weight: 700;
margin: 0.5rem 0;
}
.metric-label {
font-weight: 600;
color: #6c757d;
margin-bottom: 0.25rem;
}
.risk-indicator {
width: 12px;
height: 12px;
border-radius: 50%;
}
.risk-item {
padding: 0.75rem;
border-radius: 0.375rem;
background: white;
margin-bottom: 0.5rem;
}
.sentiment-stat {
padding: 1rem;
border-radius: 0.375rem;
background: white;
border-left: 3px solid #e9ecef;
}
.intervention-priority {
margin-bottom: 2rem;
padding: 1.5rem;
border-radius: 0.5rem;
border: 1px solid #e9ecef;
}
.intervention-item {
background: white;
padding: 1rem;
border-radius: 0.375rem;
margin-bottom: 1rem;
border-left: 3px solid #007bff;
}
.finding-item {
background: white;
padding: 1rem;
border-radius: 0.375rem;
border-left: 3px solid #007bff;
}
.insight-box {
transition: all 0.3s ease;
}
.insight-box:hover {
transform: translateX(5px);
}
.timeline {
position: relative;
padding-left: 2rem;
}
.timeline::before {
content: '';
position: absolute;
left: 20px;
top: 0;
bottom: 0;
width: 2px;
background: #e9ecef;
}
.timeline-item {
position: relative;
margin-bottom: 2rem;
}
.timeline-badge {
position: absolute;
left: -28px;
top: 0;
width: 40px;
height: 40px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 0.875rem;
}
.timeline-content {
background: white;
padding: 1rem;
border-radius: 0.5rem;
border: 1px solid #e9ecef;
margin-left: 2rem;
}
.executive-summary {
line-height: 1.8;
font-size: 1.05rem;
}
.executive-summary h4 {
color: #495057;
margin-top: 1.5rem;
margin-bottom: 1rem;
}
.report-footer {
background: #f8f9fa;
margin-top: 3rem;
}
.badge {
font-size: 0.75em;
}
@@media (max-width: 768px) {
.report-container
{
padding: 1rem;
}
.company-logo h2 {
font-size: 2rem;
}
.report-title {
font-size: 2rem;
}
.metric-card {
margin-bottom: 1rem;
}
.timeline {
padding-left: 1rem;
}
.timeline-badge {
left: -20px;
width: 30px;
height: 30px;
}
.timeline-content {
margin-left: 1rem;
}
}
</style>
}

File diff suppressed because it is too large Load diff