| import { useState } from "react"; |
| import { api } from "../api"; |
| import { useApiCall } from "../hooks/useApiCall"; |
| import { scoreColor } from "../utils/colors"; |
| import StatusMessage from "./StatusMessage"; |
|
|
| export default function TextCompare() { |
| const [textA, setTextA] = useState(""); |
| const [textB, setTextB] = useState(""); |
| const { data: similarity, loading, error, run } = useApiCall<number>(); |
|
|
| async function handleCompare() { |
| if (!textA.trim() || !textB.trim()) return; |
| await run(() => api.compare({ text_a: textA, text_b: textB }).then((r) => r.similarity)); |
| } |
|
|
| return ( |
| <div> |
| <div className="panel"> |
| <h2>Compare Texts</h2> |
| <p className="panel-desc"> |
| Compute cosine similarity between two sentences/passages. |
| </p> |
| <div className="grid-2"> |
| <div className="form-group"> |
| <label>Text A</label> |
| <textarea |
| value={textA} |
| onChange={(e) => setTextA(e.target.value)} |
| placeholder="I love pizza so much" |
| rows={4} |
| /> |
| </div> |
| <div className="form-group"> |
| <label>Text B</label> |
| <textarea |
| value={textB} |
| onChange={(e) => setTextB(e.target.value)} |
| placeholder="I love school so much" |
| rows={4} |
| /> |
| </div> |
| </div> |
| <div className="mt-2"> |
| <button |
| className="btn btn-primary" |
| onClick={handleCompare} |
| disabled={loading || !textA.trim() || !textB.trim()} |
| > |
| {loading ? "Computing..." : "Compare"} |
| </button> |
| </div> |
| </div> |
| |
| {error && <StatusMessage type="err" message={error} />} |
| |
| {similarity !== null && ( |
| <div className="panel"> |
| <div className="similarity-gauge"> |
| <div className="similarity-value" style={{ color: scoreColor(similarity) }}> |
| {similarity.toFixed(4)} |
| </div> |
| <div className="similarity-label">Cosine Similarity</div> |
| <div style={{ width: "100%", maxWidth: 400, marginTop: 16 }}> |
| <div className="score-bar" style={{ width: "100%", height: 12 }}> |
| <div |
| className="score-bar-fill" |
| style={{ |
| width: `${Math.max(0, similarity) * 100}%`, |
| background: scoreColor(similarity), |
| }} |
| /> |
| </div> |
| <div className="score-bar-legend"> |
| <span>0 (unrelated)</span> |
| <span>1 (identical)</span> |
| </div> |
| </div> |
| </div> |
| </div> |
| )} |
| </div> |
| ); |
| } |
|
|