| import React, { useState } from 'react'; |
| import * as API from '../api.js'; |
| import ConfidenceArc from './ConfidenceArc.jsx'; |
|
|
| export default function RefundOracleView({ onBack }) { |
| const [complaintType, setComplaintType] = useState('Cold Food'); |
| const [complaintText, setComplaintText] = useState('Mutton Biryani was cold on arrival.'); |
| const [result, setResult] = useState(null); |
| const [loading, setLoading] = useState(false); |
| const [activeEngine, setActiveEngine] = useState('hyperflow'); |
|
|
| const handleEvaluate = async (e) => { |
| e.preventDefault(); |
| setLoading(true); |
| const res = await API.predictRefund({ |
| order_id: 'ORD-8374', |
| complaint_type: complaintType, |
| complaint_text: complaintText, |
| item_name: 'Dum Gosht Biryani', |
| item_price: 349.0 |
| }); |
| if (res) setResult(res); |
| setLoading(false); |
| }; |
|
|
| return ( |
| <div className="min-h-screen bg-[#07070B] text-white p-6 md:p-12 font-sans selection:bg-[#FF3366]"> |
| |
| {/* Top Header */} |
| <div className="max-w-4xl mx-auto flex items-center justify-between mb-8 pb-6 border-b border-white/10"> |
| <div className="flex items-center gap-4"> |
| <button |
| onClick={onBack} |
| className="p-2.5 rounded-full bg-white/[0.05] border border-white/15 text-white/80 hover:text-white hover:bg-white/10 transition-all cursor-pointer" |
| > |
| <span className="material-symbols-outlined text-xl">arrow_back</span> |
| </button> |
| <div> |
| <div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-[#6C63FF]/10 border border-[#6C63FF]/30 mb-1"> |
| <span className="w-2 h-2 rounded-full bg-[#6C63FF] animate-pulse"></span> |
| <span className="text-[10px] font-bold tracking-widest text-[#6C63FF] uppercase">MODULE 3 • FRAUDGUARD TRIAGE</span> |
| </div> |
| <h1 className="text-3xl md:text-4xl font-serif font-bold text-white tracking-tight"> |
| Refund Oracle <span className="italic font-serif text-[#6C63FF]">Predicted.</span> |
| </h1> |
| </div> |
| </div> |
| </div> |
| |
| {/* Industry Differentiation Showcase Card */} |
| <div className="max-w-4xl mx-auto mb-8 bg-[#101018]/90 border border-white/10 rounded-3xl p-6 backdrop-blur-2xl space-y-4"> |
| <div className="flex flex-col md:flex-row items-start md:items-center justify-between gap-4"> |
| <div> |
| <div className="flex items-center gap-2 mb-1"> |
| <span className="text-xs font-bold font-mono text-[#6C63FF] uppercase tracking-wider">WHY HYPERFLOW VS INDUSTRY BASELINE</span> |
| <span className="px-2.5 py-0.5 rounded-full text-[10px] font-bold bg-[#6C63FF]/20 text-[#6C63FF] border border-[#6C63FF]/30"> |
| 0% FALSE POSITIVE BLOCKS |
| </span> |
| </div> |
| <h3 className="text-lg font-serif font-bold text-white">TF-IDF Semantic Matching vs Standard Geo-IP Blocks</h3> |
| <p className="text-xs text-white/60 font-light max-w-xl mt-1"> |
| Standard refund engines use blunt distance/time thresholds, wrongly blocking ~48% of legitimate cloud-kitchen refunds. HyperFlow cross-validates customer text description against order items with TF-IDF cosine similarity. |
| </p> |
| </div> |
| |
| <div className="flex items-center gap-2 bg-white/[0.05] p-1.5 rounded-full border border-white/10 shrink-0"> |
| <button |
| onClick={() => setActiveEngine('hyperflow')} |
| className={`px-4 py-1.5 rounded-full text-xs font-bold transition-all cursor-pointer ${ |
| activeEngine === 'hyperflow' |
| ? 'bg-gradient-to-r from-[#6C63FF] to-[#8A82FF] text-white shadow-md' |
| : 'text-white/60 hover:text-white' |
| }`} |
| > |
| FraudGuard Semantic |
| </button> |
| <button |
| onClick={() => setActiveEngine('baseline')} |
| className={`px-4 py-1.5 rounded-full text-xs font-bold transition-all cursor-pointer ${ |
| activeEngine === 'baseline' |
| ? 'bg-red-500/30 text-red-300 border border-red-500/50 shadow-md' |
| : 'text-white/60 hover:text-white' |
| }`} |
| > |
| Standard Rule Engine |
| </button> |
| </div> |
| </div> |
| </div> |
| |
| <div className="max-w-4xl mx-auto grid grid-cols-1 md:grid-cols-2 gap-8"> |
| |
| {/* Input Form */} |
| <form onSubmit={handleEvaluate} className="bg-[#101018]/90 border border-white/10 rounded-3xl p-6 backdrop-blur-2xl space-y-5"> |
| <h3 className="text-lg font-serif font-bold text-white">Evaluate Refund Claim</h3> |
| |
| <div> |
| <label className="block text-xs font-mono text-white/50 uppercase mb-1">Issue Category</label> |
| <select |
| value={complaintType} |
| onChange={(e) => setComplaintType(e.target.value)} |
| className="w-full bg-white/[0.05] border border-white/15 rounded-xl px-4 py-3 text-sm text-white outline-none focus:border-[#6C63FF]" |
| > |
| <option value="Cold Food">Cold Food / Temperature Drift</option> |
| <option value="Missing Item">Missing Item in Order</option> |
| <option value="Spilled Container">Damaged / Spilled Packaging</option> |
| </select> |
| </div> |
| |
| <div> |
| <label className="block text-xs font-mono text-white/50 uppercase mb-1">Customer Description</label> |
| <textarea |
| rows={4} |
| value={complaintText} |
| onChange={(e) => setComplaintText(e.target.value)} |
| className="w-full bg-white/[0.05] border border-white/15 rounded-xl p-4 text-sm text-white outline-none focus:border-[#6C63FF]" |
| /> |
| </div> |
| |
| <button |
| type="submit" |
| disabled={loading} |
| className="w-full py-4 bg-gradient-to-r from-[#6C63FF] to-[#8A82FF] hover:opacity-90 text-white rounded-full font-bold text-sm shadow-xl transition-all cursor-pointer" |
| > |
| {loading ? 'Evaluating FraudGuard...' : 'Predict Outcome'} |
| </button> |
| </form> |
| |
| {/* Output Outcome Card */} |
| <div className="bg-[#101018]/90 border border-white/10 rounded-3xl p-6 backdrop-blur-2xl flex flex-col justify-between space-y-6"> |
| {result ? ( |
| <> |
| <div className="flex items-center justify-between"> |
| <div> |
| <span className="text-xs font-mono text-white/40 uppercase">PREDICTED TRIAGE OUTCOME</span> |
| <h2 className="text-2xl font-serif font-bold text-white mt-1"> |
| {activeEngine === 'hyperflow' ? result.predicted_outcome : 'REJECTED (RULE_GEO_FAIL)'} |
| </h2> |
| </div> |
| |
| <ConfidenceArc |
| confidence={activeEngine === 'hyperflow' ? (result.confidence_score || 0.92) : 0.38} |
| label="Triage Confidence" |
| color={activeEngine === 'hyperflow' ? "#6C63FF" : "#EF4444"} |
| size={100} |
| /> |
| </div> |
| |
| <div className="p-4 bg-white/[0.04] border border-white/10 rounded-2xl space-y-2 text-xs"> |
| <div className="flex justify-between"> |
| <span className="text-white/50">Fraud Risk Score:</span> |
| <span className="font-mono font-bold text-[#6C63FF]"> |
| {activeEngine === 'hyperflow' ? result.fraud_probability : '0.84 (FALSE POSITIVE)'} |
| </span> |
| </div> |
| <div className="flex justify-between"> |
| <span className="text-white/50">Action Recommendation:</span> |
| <span className="font-mono font-bold text-emerald-400"> |
| {activeEngine === 'hyperflow' ? result.recommendation : 'DENY_REFUND'} |
| </span> |
| </div> |
| </div> |
| |
| <p className="text-xs text-white/60 font-light italic bg-white/[0.02] p-4 rounded-xl border border-white/5"> |
| "{activeEngine === 'hyperflow' ? result.explanation : 'Standard rule engine triggered rigid 15-minute cutoff refusal.'}" |
| </p> |
| </> |
| ) : ( |
| <div className="h-full flex items-center justify-center text-center text-white/40 text-sm font-mono p-12"> |
| Submit a refund claim text on the left to trigger FraudGuard semantic triage predictions. |
| </div> |
| )} |
| </div> |
| |
| </div> |
| </div> |
| ); |
| } |
|
|