550 lines
39 KiB
Text
550 lines
39 KiB
Text
@* Views/Admin/SurveyAnalysis/AnalyzeQuestionnaire.cshtml *@
|
|
@model Services.AIViewModel.QuestionnaireAnalysisOverview
|
|
|
|
@{
|
|
ViewData["Title"] = $"AI Analysis — {Model.QuestionnaireTitle}";
|
|
}
|
|
|
|
@section Styles {
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
|
|
<style>
|
|
@@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&family=Space+Grotesk:wght@300;400;500;600;700&display=swap');
|
|
|
|
:root {
|
|
--neon-blue:#60a5fa;--neon-purple:#c084fc;--neon-green:#34d399;--neon-pink:#f472b6;
|
|
--neon-yellow:#fbbf24;--neon-red:#f87171;--neon-cyan:#22d3ee;--neon-indigo:#818cf8;
|
|
--neon-teal:#33b3ae;--neon-amber:#f59e0b;
|
|
--dark-900:#0f172a;--dark-800:#1e293b;--dark-700:#334155;--dark-600:#475569;
|
|
--dark-500:#64748b;--dark-400:#94a3b8;--dark-300:#cbd5e1;--dark-200:#e2e8f0;
|
|
--glass-bg:rgba(255,255,255,0.04);--glass-border:rgba(255,255,255,0.08);
|
|
--font-main:'Space Grotesk',sans-serif;--font-mono:'JetBrains Mono',monospace;
|
|
}
|
|
|
|
*{margin:0;padding:0;box-sizing:border-box}
|
|
body{font-family:var(--font-main);background:var(--dark-900);color:#e2e8f0;overflow-x:hidden}
|
|
|
|
/* ===== ANIMATED BG ===== */
|
|
.nex-bg{position:fixed;inset:0;z-index:-1;overflow:hidden}
|
|
.nex-bg .grid{position:absolute;inset:0;background-image:linear-gradient(rgba(96,165,250,0.04) 1px,transparent 1px),linear-gradient(90deg,rgba(96,165,250,0.04) 1px,transparent 1px);background-size:60px 60px;animation:gridDrift 25s linear infinite}
|
|
.nex-bg .mesh{position:absolute;inset:0;background:radial-gradient(ellipse at 25% 20%,rgba(96,165,250,0.06) 0%,transparent 55%),radial-gradient(ellipse at 75% 60%,rgba(192,132,252,0.05) 0%,transparent 55%),radial-gradient(ellipse at 50% 90%,rgba(52,211,153,0.04) 0%,transparent 55%);animation:meshFloat 18s ease-in-out infinite}
|
|
|
|
@@keyframes gridDrift{0%{transform:translate(0,0)}100%{transform:translate(60px,60px)}}
|
|
@@keyframes meshFloat{0%,100%{filter:hue-rotate(0deg);transform:scale(1)}50%{filter:hue-rotate(15deg);transform:scale(1.02)}}
|
|
@@keyframes pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.6;transform:scale(1.12)}}
|
|
@@keyframes fadeInUp{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}
|
|
@@keyframes shimmer{0%{transform:translateX(-100%)}100%{transform:translateX(100%)}}
|
|
@@keyframes barGrow{from{width:0}to{width:var(--w)}}
|
|
|
|
.container{max-width:1400px;margin:0 auto;padding:0 2rem}
|
|
|
|
/* ===== HEADER ===== */
|
|
.page-header{position:relative;z-index:10;padding:2rem 0 1.5rem;border-bottom:1px solid rgba(129,140,248,0.1)}
|
|
.breadcrumb-nex{display:flex;align-items:center;gap:.8rem;margin-bottom:1.8rem;font-family:var(--font-mono);font-size:.7rem;letter-spacing:.08em}
|
|
.breadcrumb-nex a{color:var(--dark-400);text-decoration:none;display:flex;align-items:center;gap:.5rem;transition:color .2s}
|
|
.breadcrumb-nex a:hover{color:var(--neon-indigo)}
|
|
.breadcrumb-nex .sep{color:var(--dark-600);font-size:.55rem}
|
|
.breadcrumb-nex .current{color:var(--neon-indigo);font-weight:600}
|
|
|
|
.header-row{display:flex;justify-content:space-between;align-items:flex-start;gap:2rem}
|
|
.header-left{flex:1}
|
|
.header-badge{display:inline-flex;align-items:center;gap:.5rem;padding:.4rem 1rem;background:rgba(129,140,248,0.08);border:1px solid rgba(129,140,248,0.2);border-radius:50px;margin-bottom:1.5rem;font-family:var(--font-mono);font-size:.6rem;font-weight:600;letter-spacing:.1em;color:var(--neon-indigo)}
|
|
.header-badge .dot{width:6px;height:6px;background:var(--neon-green);border-radius:50%;animation:pulse 2s infinite}
|
|
.header-title{font-size:2.8rem;font-weight:700;line-height:1.1;margin-bottom:.8rem;color:#fff}
|
|
.header-title .grad{background:linear-gradient(135deg,var(--neon-blue),var(--neon-purple),var(--neon-pink));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}
|
|
.header-sub{font-size:1rem;color:var(--dark-300);line-height:1.6;max-width:550px}
|
|
.header-sub .q-name{color:var(--neon-indigo);font-weight:600}
|
|
|
|
.header-actions{display:flex;flex-wrap:wrap;gap:.7rem;align-items:flex-start;padding-top:.5rem}
|
|
.h-btn{display:flex;align-items:center;gap:.6rem;padding:.65rem 1.2rem;border-radius:10px;text-decoration:none;font-family:var(--font-mono);font-size:.68rem;font-weight:600;letter-spacing:.04em;transition:all .25s;border:1px solid}
|
|
.h-btn:hover{transform:translateY(-2px);text-decoration:none}
|
|
.h-btn.pri{background:linear-gradient(135deg,var(--neon-indigo),var(--neon-purple));border-color:transparent;color:#fff}
|
|
.h-btn.pri:hover{box-shadow:0 12px 28px rgba(129,140,248,0.25);color:#fff}
|
|
.h-btn.sec{background:rgba(255,255,255,0.04);border-color:rgba(255,255,255,0.1);color:var(--dark-300)}
|
|
.h-btn.sec:hover{background:rgba(129,140,248,0.08);border-color:rgba(129,140,248,0.25);color:var(--neon-indigo)}
|
|
.h-btn.danger{background:rgba(248,113,113,0.08);border-color:rgba(248,113,113,0.25);color:var(--neon-red)}
|
|
.h-btn.danger:hover{background:rgba(248,113,113,0.15);color:var(--neon-red)}
|
|
.h-btn i{font-size:.8rem}
|
|
|
|
/* ===== METRICS ===== */
|
|
.metrics-section{position:relative;z-index:10;padding:2.5rem 0}
|
|
.metrics-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:1.2rem}
|
|
.m-card{background:rgba(30,41,59,0.45);backdrop-filter:blur(20px);border:1px solid rgba(255,255,255,0.07);border-radius:16px;padding:1.8rem;position:relative;overflow:hidden;transition:all .3s;animation:fadeInUp .5s ease both}
|
|
.m-card:nth-child(2){animation-delay:.1s}.m-card:nth-child(3){animation-delay:.2s}.m-card:nth-child(4){animation-delay:.3s}
|
|
.m-card:hover{transform:translateY(-4px);border-color:rgba(129,140,248,0.3)}
|
|
.m-card .glow{position:absolute;top:0;left:0;right:0;height:2px;opacity:0;transition:opacity .3s}
|
|
.m-card:hover .glow{opacity:1}
|
|
.m-card.c1 .glow{background:linear-gradient(90deg,var(--neon-indigo),var(--neon-cyan))}
|
|
.m-card.c2 .glow{background:linear-gradient(90deg,var(--neon-purple),var(--neon-pink))}
|
|
.m-card.c3 .glow{background:linear-gradient(90deg,var(--neon-green),var(--neon-teal))}
|
|
.m-card.c4 .glow{background:linear-gradient(90deg,var(--neon-red),var(--neon-amber))}
|
|
|
|
.m-icon{width:48px;height:48px;border-radius:12px;display:flex;align-items:center;justify-content:center;color:#fff;font-size:1.2rem;margin-bottom:1.2rem}
|
|
.m-card.c1 .m-icon{background:linear-gradient(135deg,var(--neon-indigo),var(--neon-blue))}
|
|
.m-card.c2 .m-icon{background:linear-gradient(135deg,var(--neon-purple),var(--neon-pink))}
|
|
.m-card.c3 .m-icon{background:linear-gradient(135deg,var(--neon-green),var(--neon-teal))}
|
|
.m-card.c4 .m-icon{background:linear-gradient(135deg,var(--neon-red),var(--neon-amber))}
|
|
|
|
.m-val{font-size:2.2rem;font-weight:700;color:#fff;line-height:1;margin-bottom:.4rem}
|
|
.m-lbl{font-family:var(--font-mono);font-size:.6rem;font-weight:600;letter-spacing:.1em;color:var(--dark-400);text-transform:uppercase}
|
|
.m-card .pulse-dot{position:absolute;top:1.2rem;right:1.2rem;width:10px;height:10px;background:var(--neon-red);border-radius:50%;animation:pulse 1.5s infinite}
|
|
.m-card .orb{position:absolute;bottom:-15px;right:-15px;width:60px;height:60px;border-radius:50%;opacity:.08}
|
|
.m-card.c1 .orb{background:var(--neon-indigo)}.m-card.c2 .orb{background:var(--neon-purple)}
|
|
.m-card.c3 .orb{background:var(--neon-green)}.m-card.c4 .orb{background:var(--neon-red)}
|
|
|
|
/* ===== CARDS ===== */
|
|
.dash-section{position:relative;z-index:10;padding:1.5rem 0}
|
|
.dash-grid{display:grid;grid-template-columns:1fr 1fr;gap:1.5rem}
|
|
.nex-card{background:rgba(30,41,59,0.45);backdrop-filter:blur(20px);border:1px solid rgba(255,255,255,0.07);border-radius:18px;overflow:hidden;position:relative;transition:all .3s}
|
|
.nex-card:hover{border-color:rgba(129,140,248,0.25)}
|
|
.nex-card .top-glow{position:absolute;top:0;left:0;right:0;height:2px;background:linear-gradient(90deg,var(--neon-indigo),var(--neon-purple));opacity:0;transition:opacity .3s}
|
|
.nex-card:hover .top-glow{opacity:1}
|
|
|
|
.c-head{padding:1.8rem 1.8rem 1rem;display:flex;align-items:center;gap:1.2rem}
|
|
.c-icon{width:44px;height:44px;border-radius:12px;display:flex;align-items:center;justify-content:center;color:#fff;font-size:1.1rem;flex-shrink:0}
|
|
.c-icon.risk{background:linear-gradient(135deg,var(--neon-red),var(--neon-amber))}
|
|
.c-icon.sent{background:linear-gradient(135deg,var(--neon-green),var(--neon-teal))}
|
|
.c-icon.issue{background:linear-gradient(135deg,var(--neon-indigo),var(--neon-purple))}
|
|
.c-icon.theme{background:linear-gradient(135deg,var(--neon-amber),var(--neon-yellow))}
|
|
.c-head h3{font-size:1.1rem;font-weight:700;color:#fff;margin-bottom:.2rem}
|
|
.c-head p{color:var(--dark-400);font-size:.78rem}
|
|
.c-body{padding:0 1.8rem 1.8rem}
|
|
|
|
/* ===== RISK BARS ===== */
|
|
.risk-row{background:rgba(255,255,255,0.025);border:1px solid rgba(255,255,255,0.06);border-radius:12px;padding:1.1rem 1.2rem;margin-bottom:.8rem;transition:all .2s}
|
|
.risk-row:last-child{margin-bottom:0}
|
|
.risk-row:hover{background:rgba(255,255,255,0.04);transform:translateX(4px)}
|
|
.risk-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:.7rem}
|
|
.risk-left{display:flex;align-items:center;gap:.8rem}
|
|
.risk-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0}
|
|
.risk-dot.low{background:var(--neon-green);box-shadow:0 0 8px rgba(52,211,153,0.4)}
|
|
.risk-dot.mod{background:var(--neon-yellow);box-shadow:0 0 8px rgba(251,191,36,0.4)}
|
|
.risk-dot.high{background:var(--neon-red);box-shadow:0 0 8px rgba(248,113,113,0.4)}
|
|
.risk-dot.crit{background:#dc2626;box-shadow:0 0 8px rgba(220,38,38,0.5)}
|
|
.risk-name{font-weight:600;color:#fff;font-size:.9rem}
|
|
.risk-cnt{font-family:var(--font-mono);font-weight:700;color:var(--dark-300);background:rgba(255,255,255,0.05);padding:.2rem .7rem;border-radius:6px;font-size:.75rem;min-width:32px;text-align:center}
|
|
.risk-bar{height:8px;background:rgba(255,255,255,0.06);border-radius:4px;overflow:hidden;margin-bottom:.4rem}
|
|
.risk-fill{height:100%;border-radius:4px;position:relative;overflow:hidden;animation:barGrow .8s ease both}
|
|
.risk-fill::after{content:'';position:absolute;inset:0;background:linear-gradient(90deg,transparent,rgba(255,255,255,0.15),transparent);animation:shimmer 2.5s infinite}
|
|
.risk-fill.low{background:linear-gradient(90deg,var(--neon-green),var(--neon-cyan))}
|
|
.risk-fill.mod{background:linear-gradient(90deg,var(--neon-yellow),#fb923c)}
|
|
.risk-fill.high{background:linear-gradient(90deg,var(--neon-red),var(--neon-amber))}
|
|
.risk-fill.crit{background:linear-gradient(90deg,#dc2626,#991b1b)}
|
|
.risk-pct{font-family:var(--font-mono);font-size:.65rem;font-weight:600;color:var(--dark-400);text-align:right}
|
|
|
|
.risk-alert{display:flex;align-items:center;gap:1rem;padding:.9rem 1.2rem;background:rgba(248,113,113,0.06);border:1px solid rgba(248,113,113,0.2);border-radius:10px;margin-top:1rem;position:relative;overflow:hidden}
|
|
.risk-alert::before{content:'';position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--neon-red)}
|
|
.risk-alert-icon{color:var(--neon-red);font-size:1rem;margin-left:.5rem}
|
|
.risk-alert-lbl{font-family:var(--font-mono);font-size:.55rem;font-weight:700;letter-spacing:.1em;color:var(--neon-red);margin-bottom:.15rem}
|
|
.risk-alert-txt{font-size:.78rem;color:var(--dark-300)}
|
|
.risk-alert-txt a{color:var(--neon-indigo);text-decoration:none;font-weight:600}
|
|
.risk-alert-txt a:hover{text-decoration:underline}
|
|
|
|
/* ===== SENTIMENT ===== */
|
|
.sent-row{background:rgba(255,255,255,0.025);border:1px solid rgba(255,255,255,0.06);border-radius:12px;padding:1.1rem 1.2rem;margin-bottom:.8rem;transition:all .2s}
|
|
.sent-row:last-child{margin-bottom:0}
|
|
.sent-row:hover{background:rgba(255,255,255,0.04)}
|
|
.sent-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:.7rem}
|
|
.sent-left{display:flex;align-items:center;gap:.8rem}
|
|
.sent-icon{font-size:1rem}
|
|
.sent-icon.pos{color:var(--neon-green)}.sent-icon.neu{color:var(--dark-400)}.sent-icon.neg{color:var(--neon-red)}
|
|
.sent-name{font-weight:600;color:#fff;font-size:.9rem}
|
|
.sent-pct{font-family:var(--font-mono);font-weight:700;color:var(--dark-300);font-size:.85rem}
|
|
.sent-bar{height:8px;background:rgba(255,255,255,0.06);border-radius:4px;overflow:hidden}
|
|
.sent-fill{height:100%;border-radius:4px;animation:barGrow .8s ease both}
|
|
.sent-fill.pos{background:linear-gradient(90deg,var(--neon-green),var(--neon-cyan))}
|
|
.sent-fill.neu{background:linear-gradient(90deg,var(--dark-500),var(--dark-400))}
|
|
.sent-fill.neg{background:linear-gradient(90deg,var(--neon-red),var(--neon-amber))}
|
|
|
|
.sent-verdict{display:flex;align-items:center;gap:1rem;padding:1rem 1.2rem;border-radius:10px;border:1px solid;margin-top:1rem}
|
|
.sent-verdict.good{background:rgba(52,211,153,0.06);border-color:rgba(52,211,153,0.2)}
|
|
.sent-verdict.ok{background:rgba(251,191,36,0.06);border-color:rgba(251,191,36,0.2)}
|
|
.sent-verdict.bad{background:rgba(248,113,113,0.06);border-color:rgba(248,113,113,0.2)}
|
|
.verdict-icon{font-size:1.1rem}
|
|
.sent-verdict.good .verdict-icon{color:var(--neon-green)}
|
|
.sent-verdict.ok .verdict-icon{color:var(--neon-yellow)}
|
|
.sent-verdict.bad .verdict-icon{color:var(--neon-red)}
|
|
.verdict-txt{font-weight:600;color:#fff;font-size:.85rem}
|
|
|
|
/* ===== EXECUTIVE SUMMARY ===== */
|
|
.summary-section{position:relative;z-index:10;padding:1.5rem 0}
|
|
.summary-card{background:rgba(30,41,59,0.45);backdrop-filter:blur(20px);border:1px solid rgba(255,255,255,0.07);border-radius:18px;overflow:hidden}
|
|
.summary-head{background:linear-gradient(135deg,rgba(30,41,59,0.95),rgba(51,65,85,0.95));padding:1.5rem 2rem;display:flex;align-items:center;gap:1.2rem;border-bottom:1px solid rgba(129,140,248,0.15);position:relative}
|
|
.summary-head::before{content:'';position:absolute;inset:0;background:linear-gradient(135deg,rgba(129,140,248,0.08) 0%,transparent 60%)}
|
|
.summary-head-icon{width:44px;height:44px;background:linear-gradient(135deg,var(--neon-indigo),var(--neon-purple));border-radius:10px;display:flex;align-items:center;justify-content:center;color:#fff;font-size:1.1rem;position:relative;z-index:2;flex-shrink:0}
|
|
.summary-head h3{font-family:var(--font-mono);font-size:.95rem;font-weight:700;letter-spacing:.05em;color:#e2e8f0;position:relative;z-index:2}
|
|
.summary-head p{font-size:.75rem;color:var(--dark-400);position:relative;z-index:2}
|
|
.summary-body{padding:2rem}
|
|
|
|
/* Rendered markdown styles */
|
|
.md-content{font-size:.92rem;line-height:1.8;color:var(--dark-200)}
|
|
.md-content h1,.md-content h2{font-family:var(--font-mono);font-weight:700;letter-spacing:.05em;color:var(--neon-indigo);margin:2rem 0 1rem;padding-bottom:.6rem;border-bottom:1px solid rgba(129,140,248,0.15);font-size:1rem}
|
|
.md-content h1:first-child,.md-content h2:first-child{margin-top:0}
|
|
.md-content h3{font-family:var(--font-mono);font-weight:700;letter-spacing:.04em;color:#fff;margin:1.5rem 0 .8rem;font-size:.9rem}
|
|
.md-content p{margin-bottom:1rem;color:var(--dark-200)}
|
|
.md-content strong{color:#fff;font-weight:700}
|
|
.md-content ul,.md-content ol{margin:0 0 1rem 0;padding-left:0;list-style:none}
|
|
.md-content li{position:relative;padding:.5rem 0 .5rem 1.8rem;color:var(--dark-200);border-bottom:1px solid rgba(255,255,255,0.03)}
|
|
.md-content li:last-child{border-bottom:none}
|
|
.md-content li::before{content:'';position:absolute;left:0;top:.85rem;width:8px;height:8px;background:linear-gradient(135deg,var(--neon-indigo),var(--neon-purple));border-radius:2px;transform:rotate(45deg)}
|
|
.md-content hr{border:none;height:1px;background:linear-gradient(90deg,transparent,rgba(129,140,248,0.2),transparent);margin:1.5rem 0}
|
|
.md-content code{background:rgba(129,140,248,0.1);border:1px solid rgba(129,140,248,0.2);padding:.15rem .5rem;border-radius:4px;font-family:var(--font-mono);font-size:.8rem;color:var(--neon-indigo)}
|
|
|
|
/* ===== ISSUES ===== */
|
|
.insights-section{position:relative;z-index:10;padding:1.5rem 0}
|
|
.insights-grid{display:grid;grid-template-columns:2fr 1fr;gap:1.5rem}
|
|
|
|
.issue-item{background:rgba(255,255,255,0.025);border:1px solid rgba(255,255,255,0.06);border-radius:14px;padding:1.5rem;margin-bottom:1rem;border-left:3px solid;transition:all .2s}
|
|
.issue-item:last-child{margin-bottom:0}
|
|
.issue-item:hover{background:rgba(255,255,255,0.04);transform:translateX(4px)}
|
|
.issue-item.p1{border-left-color:var(--neon-red)}.issue-item.p2{border-left-color:var(--neon-amber)}
|
|
.issue-item.p3{border-left-color:var(--neon-indigo)}.issue-item.p4{border-left-color:var(--neon-cyan)}
|
|
.issue-item.p5{border-left-color:var(--dark-500)}
|
|
|
|
.issue-top{display:flex;align-items:center;gap:1rem;margin-bottom:1rem}
|
|
.pri-badge{width:36px;height:36px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-family:var(--font-mono);font-size:.65rem;font-weight:700;color:#fff;flex-shrink:0}
|
|
.issue-item.p1 .pri-badge{background:var(--neon-red)}.issue-item.p2 .pri-badge{background:var(--neon-amber);color:var(--dark-900)}
|
|
.issue-item.p3 .pri-badge{background:var(--neon-indigo)}.issue-item.p4 .pri-badge{background:var(--neon-cyan);color:var(--dark-900)}
|
|
.issue-item.p5 .pri-badge{background:var(--dark-500)}
|
|
.issue-cat{font-weight:700;color:#fff;font-size:1rem;flex:1}
|
|
.pri-chip{font-family:var(--font-mono);font-size:.55rem;font-weight:600;letter-spacing:.08em;padding:.25rem .7rem;border-radius:20px;border:1px solid}
|
|
.issue-item.p1 .pri-chip{background:rgba(248,113,113,0.15);border-color:rgba(248,113,113,0.3);color:var(--neon-red)}
|
|
.issue-item.p2 .pri-chip{background:rgba(245,158,11,0.15);border-color:rgba(245,158,11,0.3);color:var(--neon-amber)}
|
|
.issue-item.p3 .pri-chip{background:rgba(129,140,248,0.15);border-color:rgba(129,140,248,0.3);color:var(--neon-indigo)}
|
|
.issue-item.p4 .pri-chip{background:rgba(34,211,238,0.15);border-color:rgba(34,211,238,0.3);color:var(--neon-cyan)}
|
|
.issue-item.p5 .pri-chip{background:rgba(100,116,139,0.15);border-color:rgba(100,116,139,0.3);color:var(--dark-400)}
|
|
|
|
.issue-desc{color:var(--dark-300);font-size:.85rem;line-height:1.6;margin-bottom:1rem}
|
|
.intervention{background:rgba(129,140,248,0.04);border:1px solid rgba(129,140,248,0.1);border-radius:8px;padding:1rem;margin-bottom:.8rem}
|
|
.intervention-head{display:flex;align-items:center;gap:.5rem;font-family:var(--font-mono);font-size:.6rem;font-weight:600;letter-spacing:.1em;color:var(--neon-indigo);margin-bottom:.6rem}
|
|
.intervention-txt{color:var(--dark-200);font-size:.82rem;line-height:1.6}
|
|
.area-tags{display:flex;flex-wrap:wrap;gap:.4rem}
|
|
.area-tag{padding:.2rem .6rem;background:rgba(255,255,255,0.04);border:1px solid rgba(255,255,255,0.08);border-radius:5px;font-size:.65rem;color:var(--dark-300)}
|
|
|
|
/* ===== THEMES ===== */
|
|
.theme-group{background:rgba(255,255,255,0.025);border:1px solid rgba(255,255,255,0.06);border-radius:12px;padding:1.3rem;margin-bottom:1rem}
|
|
.theme-group:last-child{margin-bottom:0}
|
|
.theme-head{display:flex;align-items:center;gap:.7rem;font-family:var(--font-mono);font-size:.6rem;font-weight:600;letter-spacing:.1em;color:var(--dark-300);margin-bottom:1rem}
|
|
.theme-head i{font-size:.7rem;color:var(--neon-indigo)}
|
|
.tag-list{display:flex;flex-wrap:wrap;gap:.5rem}
|
|
.tag-phrase{padding:.35rem .8rem;background:rgba(96,165,250,0.12);border:1px solid rgba(96,165,250,0.25);border-radius:6px;font-size:.72rem;color:var(--neon-blue);font-weight:500}
|
|
.tag-cat{padding:.35rem .8rem;background:rgba(251,191,36,0.12);border:1px solid rgba(251,191,36,0.25);border-radius:6px;font-size:.72rem;color:var(--neon-yellow);font-weight:500}
|
|
|
|
/* ===== FOOTER META ===== */
|
|
.meta-section{position:relative;z-index:10;padding:1.5rem 0 4rem}
|
|
.meta-bar{background:rgba(30,41,59,0.45);backdrop-filter:blur(20px);border:1px solid rgba(255,255,255,0.07);border-radius:14px;padding:1.2rem 1.8rem;display:flex;align-items:center;justify-content:space-between;gap:1.5rem;flex-wrap:wrap}
|
|
.meta-info{display:flex;align-items:center;gap:.8rem;flex:1}
|
|
.meta-info i{color:var(--neon-indigo);font-size:.9rem}
|
|
.meta-txt{font-family:var(--font-mono);font-size:.68rem;color:var(--dark-400);display:flex;align-items:center;gap:.6rem;flex-wrap:wrap}
|
|
.meta-txt .sep{color:var(--dark-600)}
|
|
.meta-actions{display:flex;gap:.7rem}
|
|
.meta-btn{display:flex;align-items:center;gap:.5rem;padding:.55rem 1rem;background:rgba(255,255,255,0.04);border:1px solid rgba(255,255,255,0.08);border-radius:8px;color:var(--dark-300);text-decoration:none;font-family:var(--font-mono);font-size:.62rem;font-weight:600;letter-spacing:.04em;transition:all .2s}
|
|
.meta-btn:hover{background:rgba(129,140,248,0.08);border-color:rgba(129,140,248,0.25);color:var(--neon-indigo);text-decoration:none}
|
|
|
|
/* ===== EMPTY STATE ===== */
|
|
.empty{text-align:center;padding:2.5rem;color:var(--dark-500)}
|
|
.empty i{font-size:1.5rem;margin-bottom:.8rem;opacity:.5;display:block}
|
|
|
|
/* ===== RESPONSIVE ===== */
|
|
@@media(max-width:1200px){.metrics-grid{grid-template-columns:repeat(2,1fr)}.dash-grid,.insights-grid{grid-template-columns:1fr}}
|
|
@@media(max-width:768px){
|
|
.header-row{flex-direction:column}.header-actions{width:100%}
|
|
.metrics-grid{grid-template-columns:1fr}
|
|
.header-title{font-size:2rem}
|
|
.meta-bar{flex-direction:column;text-align:center}
|
|
.meta-actions{justify-content:center}
|
|
}
|
|
@@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}
|
|
</style>
|
|
}
|
|
|
|
<div class="nex-bg"><div class="grid"></div><div class="mesh"></div></div>
|
|
|
|
<!-- Header -->
|
|
<section class="page-header">
|
|
<div class="container">
|
|
<div class="breadcrumb-nex">
|
|
<a href="@Url.Action("Index")"><i class="fa-solid fa-brain"></i> Analysis Dashboard</a>
|
|
<i class="fa-solid fa-chevron-right sep"></i>
|
|
<span class="current">@Model.QuestionnaireTitle</span>
|
|
</div>
|
|
|
|
<div class="header-row">
|
|
<div class="header-left">
|
|
<div class="header-badge"><span class="dot"></span> CLAUDE AI ANALYSIS</div>
|
|
<h1 class="header-title">Mental Health <span class="grad">Analysis</span></h1>
|
|
<p class="header-sub">Comprehensive AI-powered analysis for <span class="q-name">@Model.QuestionnaireTitle</span> — sentiment, risk assessment, and workplace insights.</p>
|
|
</div>
|
|
<div class="header-actions">
|
|
<a href="@Url.Action("Dashboard", new { id = Model.QuestionnaireId })" class="h-btn pri"><i class="fa-solid fa-gauge-high"></i> Executive Dashboard</a>
|
|
<a href="@Url.Action("GenerateReport", new { id = Model.QuestionnaireId })" class="h-btn sec"><i class="fa-solid fa-file-lines"></i> Report</a>
|
|
<a href="@Url.Action("ExportAnalysis", new { id = Model.QuestionnaireId })" class="h-btn sec"><i class="fa-solid fa-download"></i> Export</a>
|
|
<a href="@Url.Action("HighRiskResponses", new { id = Model.QuestionnaireId })" class="h-btn danger"><i class="fa-solid fa-triangle-exclamation"></i> High Risk</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Metrics -->
|
|
<section class="metrics-section">
|
|
<div class="container">
|
|
<div class="metrics-grid">
|
|
<div class="m-card c1">
|
|
<div class="glow"></div>
|
|
<div class="m-icon"><i class="fa-solid fa-users"></i></div>
|
|
<div class="m-val">@Model.TotalResponses</div>
|
|
<div class="m-lbl">Total Responses</div>
|
|
<div class="orb"></div>
|
|
</div>
|
|
<div class="m-card c2">
|
|
<div class="glow"></div>
|
|
<div class="m-icon"><i class="fa-solid fa-sparkles"></i></div>
|
|
<div class="m-val">@Model.AnalyzedResponses</div>
|
|
<div class="m-lbl">AI Analyzed</div>
|
|
<div class="orb"></div>
|
|
</div>
|
|
<div class="m-card c3">
|
|
<div class="glow"></div>
|
|
<div class="m-icon"><i class="fa-solid fa-face-smile"></i></div>
|
|
<div class="m-val">@Math.Round(Model.OverallPositiveSentiment * 100, 1)%</div>
|
|
<div class="m-lbl">Positive Sentiment</div>
|
|
<div class="orb"></div>
|
|
</div>
|
|
<div class="m-card c4">
|
|
<div class="glow"></div>
|
|
<div class="m-icon"><i class="fa-solid fa-shield-halved"></i></div>
|
|
<div class="m-val">@(Model.HighRiskResponses + Model.CriticalRiskResponses)</div>
|
|
<div class="m-lbl">High / Critical Risk</div>
|
|
@if (Model.HighRiskResponses + Model.CriticalRiskResponses > 0) { <div class="pulse-dot"></div> }
|
|
<div class="orb"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Risk + Sentiment -->
|
|
<section class="dash-section">
|
|
<div class="container">
|
|
<div class="dash-grid">
|
|
|
|
<!-- Risk Distribution -->
|
|
<div class="nex-card">
|
|
<div class="top-glow"></div>
|
|
<div class="c-head">
|
|
<div class="c-icon risk"><i class="fa-solid fa-shield-halved"></i></div>
|
|
<div><h3>Risk Distribution</h3><p>Mental health risk assessment across all responses</p></div>
|
|
</div>
|
|
<div class="c-body">
|
|
@if (Model.AnalyzedResponses > 0)
|
|
{
|
|
var total = (double)Model.AnalyzedResponses;
|
|
|
|
<div class="risk-row">
|
|
<div class="risk-top"><div class="risk-left"><div class="risk-dot low"></div><span class="risk-name">Low Risk</span></div><div class="risk-cnt">@Model.LowRiskResponses</div></div>
|
|
<div class="risk-bar"><div class="risk-fill low" style="--w:@(Math.Round(Model.LowRiskResponses / total * 100, 1))%;width:var(--w)"></div></div>
|
|
<div class="risk-pct">@Math.Round(Model.LowRiskResponses / total * 100, 1)%</div>
|
|
</div>
|
|
<div class="risk-row">
|
|
<div class="risk-top"><div class="risk-left"><div class="risk-dot mod"></div><span class="risk-name">Moderate Risk</span></div><div class="risk-cnt">@Model.ModerateRiskResponses</div></div>
|
|
<div class="risk-bar"><div class="risk-fill mod" style="--w:@(Math.Round(Model.ModerateRiskResponses / total * 100, 1))%;width:var(--w)"></div></div>
|
|
<div class="risk-pct">@Math.Round(Model.ModerateRiskResponses / total * 100, 1)%</div>
|
|
</div>
|
|
<div class="risk-row">
|
|
<div class="risk-top"><div class="risk-left"><div class="risk-dot high"></div><span class="risk-name">High Risk</span></div><div class="risk-cnt">@Model.HighRiskResponses</div></div>
|
|
<div class="risk-bar"><div class="risk-fill high" style="--w:@(Math.Round(Model.HighRiskResponses / total * 100, 1))%;width:var(--w)"></div></div>
|
|
<div class="risk-pct">@Math.Round(Model.HighRiskResponses / total * 100, 1)%</div>
|
|
</div>
|
|
<div class="risk-row">
|
|
<div class="risk-top"><div class="risk-left"><div class="risk-dot crit"></div><span class="risk-name">Critical Risk</span></div><div class="risk-cnt">@Model.CriticalRiskResponses</div></div>
|
|
<div class="risk-bar"><div class="risk-fill crit" style="--w:@(Math.Round(Model.CriticalRiskResponses / total * 100, 1))%;width:var(--w)"></div></div>
|
|
<div class="risk-pct">@Math.Round(Model.CriticalRiskResponses / total * 100, 1)%</div>
|
|
</div>
|
|
|
|
@if (Model.HighRiskResponses > 0 || Model.CriticalRiskResponses > 0)
|
|
{
|
|
<div class="risk-alert">
|
|
<div class="risk-alert-icon"><i class="fa-solid fa-triangle-exclamation"></i></div>
|
|
<div>
|
|
<div class="risk-alert-lbl">ATTENTION REQUIRED</div>
|
|
<div class="risk-alert-txt"><strong>@(Model.HighRiskResponses + Model.CriticalRiskResponses) responses</strong> flagged for immediate review. <a href="@Url.Action("HighRiskResponses", new { id = Model.QuestionnaireId })">View details →</a></div>
|
|
</div>
|
|
</div>
|
|
}
|
|
}
|
|
else { <div class="empty"><i class="fa-solid fa-circle-info"></i><p>No risk data available</p></div> }
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Sentiment -->
|
|
<div class="nex-card">
|
|
<div class="top-glow"></div>
|
|
<div class="c-head">
|
|
<div class="c-icon sent"><i class="fa-solid fa-heart-pulse"></i></div>
|
|
<div><h3>Sentiment Analysis</h3><p>Emotional tone assessment across responses</p></div>
|
|
</div>
|
|
<div class="c-body">
|
|
@if (Model.AnalyzedResponses > 0)
|
|
{
|
|
<div class="sent-row">
|
|
<div class="sent-top"><div class="sent-left"><i class="fa-solid fa-face-smile sent-icon pos"></i><span class="sent-name">Positive</span></div><span class="sent-pct">@Math.Round(Model.OverallPositiveSentiment * 100, 1)%</span></div>
|
|
<div class="sent-bar"><div class="sent-fill pos" style="--w:@(Model.OverallPositiveSentiment * 100)%;width:var(--w)"></div></div>
|
|
</div>
|
|
<div class="sent-row">
|
|
<div class="sent-top"><div class="sent-left"><i class="fa-solid fa-face-meh sent-icon neu"></i><span class="sent-name">Neutral</span></div><span class="sent-pct">@Math.Round(Model.OverallNeutralSentiment * 100, 1)%</span></div>
|
|
<div class="sent-bar"><div class="sent-fill neu" style="--w:@(Model.OverallNeutralSentiment * 100)%;width:var(--w)"></div></div>
|
|
</div>
|
|
<div class="sent-row">
|
|
<div class="sent-top"><div class="sent-left"><i class="fa-solid fa-face-frown sent-icon neg"></i><span class="sent-name">Negative</span></div><span class="sent-pct">@Math.Round(Model.OverallNegativeSentiment * 100, 1)%</span></div>
|
|
<div class="sent-bar"><div class="sent-fill neg" style="--w:@(Model.OverallNegativeSentiment * 100)%;width:var(--w)"></div></div>
|
|
</div>
|
|
|
|
var vClass = ""; var vIcon = ""; var vText = "";
|
|
if (Model.OverallPositiveSentiment >= 0.6) { vClass = "good"; vIcon = "fa-thumbs-up"; vText = "Excellent mental health climate"; }
|
|
else if (Model.OverallPositiveSentiment >= 0.4) { vClass = "ok"; vIcon = "fa-scale-balanced"; vText = "Moderate mental health climate"; }
|
|
else { vClass = "bad"; vIcon = "fa-triangle-exclamation"; vText = "Concerning mental health climate"; }
|
|
<div class="sent-verdict @vClass">
|
|
<i class="fa-solid @vIcon verdict-icon"></i>
|
|
<span class="verdict-txt">@vText</span>
|
|
</div>
|
|
}
|
|
else { <div class="empty"><i class="fa-solid fa-circle-info"></i><p>No sentiment data available</p></div> }
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Executive Summary -->
|
|
@if (!string.IsNullOrEmpty(Model.ExecutiveSummary))
|
|
{
|
|
<section class="summary-section">
|
|
<div class="container">
|
|
<div class="summary-card">
|
|
<div class="summary-head">
|
|
<div class="summary-head-icon"><i class="fa-solid fa-clipboard-list"></i></div>
|
|
<div><h3>EXECUTIVE SUMMARY</h3><p>Comprehensive analysis overview powered by Claude AI</p></div>
|
|
</div>
|
|
<div class="summary-body">
|
|
<div class="md-content" id="executiveSummary"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
}
|
|
|
|
<!-- Insights: Issues + Themes -->
|
|
<section class="insights-section">
|
|
<div class="container">
|
|
<div class="insights-grid">
|
|
<!-- Workplace Issues -->
|
|
<div class="nex-card">
|
|
<div class="top-glow"></div>
|
|
<div class="c-head">
|
|
<div class="c-icon issue"><i class="fa-solid fa-magnifying-glass-chart"></i></div>
|
|
<div><h3>Workplace Issues & Interventions</h3><p>Priority-ranked issues with recommended actions</p></div>
|
|
</div>
|
|
<div class="c-body">
|
|
@if (Model.TopWorkplaceIssues != null && Model.TopWorkplaceIssues.Any())
|
|
{
|
|
@foreach (var issue in Model.TopWorkplaceIssues.Take(5))
|
|
{
|
|
<div class="issue-item p@issue.Priority">
|
|
<div class="issue-top">
|
|
<div class="pri-badge">P@issue.Priority</div>
|
|
<span class="issue-cat">@issue.Category</span>
|
|
<span class="pri-chip">PRIORITY @issue.Priority</span>
|
|
</div>
|
|
<div class="issue-desc">@issue.Issue</div>
|
|
<div class="intervention">
|
|
<div class="intervention-head"><i class="fa-solid fa-lightbulb"></i> RECOMMENDED INTERVENTION</div>
|
|
<div class="intervention-txt">@issue.RecommendedIntervention</div>
|
|
</div>
|
|
@if (issue.AffectedAreas.Any())
|
|
{
|
|
<div class="area-tags">
|
|
@foreach (var area in issue.AffectedAreas) { <span class="area-tag">@area</span> }
|
|
</div>
|
|
}
|
|
</div>
|
|
}
|
|
}
|
|
else { <div class="empty"><i class="fa-solid fa-circle-info"></i><p>No workplace issues identified</p></div> }
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Themes -->
|
|
<div class="nex-card">
|
|
<div class="top-glow"></div>
|
|
<div class="c-head">
|
|
<div class="c-icon theme"><i class="fa-solid fa-tags"></i></div>
|
|
<div><h3>Common Themes</h3><p>Key patterns and categories</p></div>
|
|
</div>
|
|
<div class="c-body">
|
|
@if (Model.MostCommonKeyPhrases != null && Model.MostCommonKeyPhrases.Any())
|
|
{
|
|
<div class="theme-group">
|
|
<div class="theme-head"><i class="fa-solid fa-quote-left"></i> MOST MENTIONED PHRASES</div>
|
|
<div class="tag-list">
|
|
@foreach (var phrase in Model.MostCommonKeyPhrases.Take(10)) { <span class="tag-phrase">@phrase</span> }
|
|
</div>
|
|
</div>
|
|
|
|
@if (Model.TopWorkplaceIssues.Any())
|
|
{
|
|
<div class="theme-group">
|
|
<div class="theme-head"><i class="fa-solid fa-layer-group"></i> ISSUE CATEGORIES</div>
|
|
<div class="tag-list">
|
|
@foreach (var cat in Model.TopWorkplaceIssues.Select(i => i.Category).Distinct().Take(6)) { <span class="tag-cat">@cat</span> }
|
|
</div>
|
|
</div>
|
|
}
|
|
}
|
|
else { <div class="empty"><i class="fa-solid fa-circle-info"></i><p>No themes identified</p></div> }
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Footer Meta -->
|
|
<section class="meta-section">
|
|
<div class="container">
|
|
<div class="meta-bar">
|
|
<div class="meta-info">
|
|
<i class="fa-solid fa-circle-info"></i>
|
|
<div class="meta-txt">
|
|
<span>Analyzed @Model.LastAnalyzedAt.ToString("MMMM dd, yyyy 'at' HH:mm")</span>
|
|
<span class="sep">|</span>
|
|
<span>@Model.AnalyzedResponses responses processed</span>
|
|
<span class="sep">|</span>
|
|
<span>Powered by Claude AI (Anthropic)</span>
|
|
</div>
|
|
</div>
|
|
<div class="meta-actions">
|
|
<a href="@Url.Action("BatchAnalyze", new { id = Model.QuestionnaireId })" class="meta-btn"><i class="fa-solid fa-rotate"></i> Refresh</a>
|
|
<a href="@Url.Action("AnalyzeTrends", new { id = Model.QuestionnaireId })" class="meta-btn"><i class="fa-solid fa-chart-line"></i> Trends</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
@section Scripts {
|
|
<!-- Markdown parser (lightweight) -->
|
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
// Parse and render executive summary as proper HTML from markdown
|
|
var raw = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(Model.ExecutiveSummary ?? ""));
|
|
var container = document.getElementById('executiveSummary');
|
|
if (container && raw) {
|
|
// Configure marked for clean output
|
|
marked.setOptions({
|
|
breaks: true,
|
|
gfm: true,
|
|
headerIds: false,
|
|
mangle: false
|
|
});
|
|
container.innerHTML = marked.parse(raw);
|
|
}
|
|
});
|
|
</script>
|
|
}
|