human handoffs
This commit is contained in:
parent
79188e0f59
commit
36a55930f9
35 changed files with 4039 additions and 139 deletions
74
frontend/src/components/HandoffConversation.jsx
Normal file
74
frontend/src/components/HandoffConversation.jsx
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
import { ArrowLeft } from "lucide-react";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { getHandoffConversation } from "../api";
|
||||
|
||||
function formatTime(dateValue) {
|
||||
if (!dateValue) return "";
|
||||
return new Date(dateValue).toLocaleString(undefined, {
|
||||
hour: "numeric",
|
||||
minute: "2-digit",
|
||||
});
|
||||
}
|
||||
|
||||
export default function HandoffConversation({ handoffId, onBack }) {
|
||||
const token = sessionStorage.getItem("agmail_access_token");
|
||||
const [conversation, setConversation] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState("");
|
||||
|
||||
const load = useCallback(async () => {
|
||||
setLoading(true);
|
||||
setError("");
|
||||
try {
|
||||
const data = await getHandoffConversation(handoffId, token);
|
||||
setConversation(data);
|
||||
} catch (err) {
|
||||
setError(err.message);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [handoffId, token]);
|
||||
|
||||
useEffect(() => {
|
||||
load();
|
||||
}, [load]);
|
||||
|
||||
if (loading) {
|
||||
return <p className="people-table-empty">Loading conversation…</p>;
|
||||
}
|
||||
if (error) {
|
||||
return <p className="form-error" role="alert">{error}</p>;
|
||||
}
|
||||
if (!conversation) return null;
|
||||
|
||||
return (
|
||||
<div className="handoff-conversation">
|
||||
<button type="button" className="handoff-back-btn" onClick={onBack}>
|
||||
<ArrowLeft size={16} strokeWidth={1.75} /> Back to Handoffs
|
||||
</button>
|
||||
|
||||
<header className="handoff-conversation-head">
|
||||
<h2>{conversation.external_subject || "(No subject)"}</h2>
|
||||
<div className="handoff-linked-external">
|
||||
<span>Linked conversation:</span>
|
||||
<strong>{conversation.linked_external.sender}</strong>
|
||||
<em>“{conversation.linked_external.subject}”</em>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div className="handoff-message-list">
|
||||
{conversation.messages.map((message) => (
|
||||
<article key={message.id} className={`handoff-message handoff-message-${message.role}`}>
|
||||
<header>
|
||||
<strong>{message.role === "human" ? "HUMAN OWNER" : "AGENT"}</strong>
|
||||
<time>{formatTime(message.event_at)}</time>
|
||||
</header>
|
||||
<div className="handoff-message-body">
|
||||
{message.body_text || message.snippet}
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue