| import { useState } from "react"; |
| import CardForm from "../components/CardForm"; |
| import ResultsGrid from "../components/ResultsGrid"; |
|
|
| const API = ""; |
|
|
| export default function CardsPage() { |
| const [recs, setRecs] = useState([]); |
| const [error, setError] = useState(""); |
|
|
| const [lastReq, setLastReq] = useState(null); |
| const [explain, setExplain] = useState(""); |
|
|
| async function submit(payload) { |
| setError(""); |
| setRecs([]); |
| setExplain(""); |
| setLastReq(payload); |
|
|
| try { |
| const res = await fetch(`${API}/api/cards/recommend`, { |
| method: "POST", |
| headers: { "Content-Type": "application/json" }, |
| body: JSON.stringify(payload), |
| }); |
|
|
| if (!res.ok) throw new Error("Request failed"); |
| setRecs(await res.json()); |
| } catch (e) { |
| setError(e.message || "Error"); |
| } |
| } |
|
|
| async function explainOne(r) { |
| if (!lastReq) return; |
|
|
| setExplain("Thinking..."); |
|
|
| try { |
| const res = await fetch(`${API}/api/cards/explain`, { |
| method: "POST", |
| headers: { "Content-Type": "application/json" }, |
| body: JSON.stringify({ |
| user_input: lastReq, |
| product: r.product, |
| score: r.score, |
| }), |
| }); |
|
|
| const data = await res.json(); |
| setExplain(data.text || "No explanation returned."); |
| } catch { |
| setExplain("Could not generate an explanation right now."); |
| } |
| } |
|
|
| return ( |
| <section className="card"> |
| <CardForm onSubmit={submit} /> |
| {error && <div className="muted small" style={{ marginTop: 12 }}>{error}</div>} |
| |
| {explain && ( |
| <div className="card" style={{ marginTop: 12 }}> |
| <div className="muted small" style={{ whiteSpace: "pre-wrap" }}> |
| {explain} |
| </div> |
| </div> |
| )} |
| |
| <ResultsGrid |
| items={recs} |
| getKey={(r) => r.product} |
| renderTitle={(r) => r.product} |
| renderMeta={(r) => `${r.institution || "Institution"} • Score: ${r.score.toFixed(3)}`} |
| onExplain={explainOne} |
| /> |
| </section> |
| ); |
| } |
|
|