File size: 5,398 Bytes
f500247
 
82d9c42
f500247
 
 
 
 
 
 
 
 
82d9c42
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f500247
 
 
 
82d9c42
 
 
f500247
 
 
 
 
 
 
82d9c42
f500247
 
82d9c42
f500247
 
 
 
82d9c42
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import { marked } from "marked";
import DOMPurify from "dompurify";
import { useEffect, useState } from "react";

import BotIcon from "./icons/BotIcon";
import UserIcon from "./icons/UserIcon";
import "./Chat.css";

function render(text) {
  return DOMPurify.sanitize(marked.parse(text));
}

// مكون فرعي لكل رسالة للتحكم في التقييم والاقتراحات
function MessageItem({ msg }) {
  const [feedback, setFeedback] = useState(null); // 'up' or 'down'
  const [showOptions, setShowOptions] = useState(false);

  const medicalOptions = [
    "Not medically accurate",
    "Does not follow ABCDE protocol",
    "Too long for emergency context",
    "Incorrect dosage suggestion",
    "Other medical reason"
  ];

  const handleOptionClick = (option) => {
    alert(`Thank you for your feedback: "${option}". This helps improve the ER Assistant.`);
    setShowOptions(false);
    setFeedback('down');
  };

  return (
    <div className="flex items-start space-x-4 mb-4 relative">
      {msg.role === "assistant" ? (
        <>
          <BotIcon className="h-6 w-6 min-h-6 min-w-6 my-3 text-gray-500 dark:text-gray-300" />
          <div className="flex flex-col items-start w-full">
            <div className="bg-gray-200 dark:bg-gray-700 rounded-lg p-4 w-full">
              <p className="min-h-6 text-gray-800 dark:text-gray-200 overflow-wrap-anywhere">
                {msg.content.length > 0 ? (
                  <span
                    className="markdown"
                    dangerouslySetInnerHTML={{ __html: render(msg.content) }}
                  />
                ) : (
                  <span className="h-6 flex items-center gap-1">
                    <span className="w-2.5 h-2.5 bg-gray-600 dark:bg-gray-300 rounded-full animate-pulse"></span>
                    <span className="w-2.5 h-2.5 bg-gray-600 dark:bg-gray-300 rounded-full animate-pulse animation-delay-200"></span>
                    <span className="w-2.5 h-2.5 bg-gray-600 dark:bg-gray-300 rounded-full animate-pulse animation-delay-400"></span>
                  </span>
                )}
              </p>
            </div>
            
            {/* أزرار التقييم - تظهر فقط بعد انتهاء الكتابة */}
            {msg.content.length > 0 && (
              <div className="flex items-center mt-2 space-x-3 text-gray-400 ml-1">
                <button 
                  onClick={() => {setFeedback('up'); setShowOptions(false);}}
                  className={`hover:text-green-500 transition-colors ${feedback === 'up' ? 'text-green-500' : ''}`}
                  title="Correct"
                >
                  👍
                </button>
                <button 
                  onClick={() => setShowOptions(!showOptions)}
                  className={`hover:text-red-500 transition-colors ${feedback === 'down' ? 'text-red-500' : ''}`}
                  title="Incorrect"
                >
                  👎
                </button>

                {/* نافذة الأسباب (Popup) */}
                {showOptions && (
                  <div className="absolute z-50 mt-10 left-10 p-4 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-xl shadow-2xl w-64 animate-in fade-in zoom-in duration-200">
                    <div className="flex justify-between items-center mb-3">
                      <h4 className="text-xs font-bold uppercase tracking-wider text-gray-500">What went wrong?</h4>
                      <button onClick={() => setShowOptions(false)} className="text-gray-400 hover:text-gray-600">✕</button>
                    </div>
                    <div className="flex flex-col gap-1.5">
                      {medicalOptions.map((option) => (
                        <button
                          key={option}
                          onClick={() => handleOptionClick(option)}
                          className="text-left text-xs p-2.5 hover:bg-red-50 dark:hover:bg-red-900/30 rounded-lg border border-transparent hover:border-red-200 transition-all text-gray-700 dark:text-gray-300"
                        >
                          {option}
                        </button>
                      ))}
                    </div>
                  </div>
                )}
                {feedback === 'up' && <span className="text-[10px] text-green-600 font-medium">Feedback sent!</span>}
              </div>
            )}
          </div>
        </>
      ) : (
        <>
          <UserIcon className="h-6 w-6 min-h-6 min-w-6 my-3 text-gray-500 dark:text-gray-300" />
          <div className="bg-blue-500 text-white rounded-lg p-4">
            <p className="min-h-6 overflow-wrap-anywhere">{msg.content}</p>
          </div>
        </>
      )}
    </div>
  );
}

export default function Chat({ messages }) {
  const empty = messages.length === 0;

  useEffect(() => {
    if (window.MathJax) {
      window.MathJax.typeset();
    }
  }, [messages]);

  return (
    <div
      className={`flex-1 p-6 max-w-[960px] w-full ${empty ? "flex flex-col items-center justify-end" : "space-y-4"}`}
    >
      {empty ? (
        <div className="text-xl font-medium text-gray-400">ER Assistant is Ready...</div>
      ) : (
        messages.map((msg, i) => (
          <MessageItem key={`message-${i}`} msg={msg} />
        ))
      )}
    </div>
  );
}