| | |
| | import React, { useState } from "react"; |
| | import api from "../../api/client"; |
| |
|
| | export default function AdminAIAssistant({ open, onClose, memberships }) { |
| | const [message, setMessage] = useState(""); |
| | const [answer, setAnswer] = useState(""); |
| | const [loading, setLoading] = useState(false); |
| |
|
| | if (!open) return null; |
| |
|
| | async function handleAsk(e) { |
| | e.preventDefault(); |
| | if (!message.trim()) return; |
| |
|
| | setLoading(true); |
| | setAnswer(""); |
| |
|
| | try { |
| | const res = await api.post("/ai/admin", { |
| | question: message, |
| | membership_count: memberships.length, |
| | }); |
| | setAnswer(res.data?.answer || "AI assistant responded."); |
| | } catch (err) { |
| | setAnswer("Sorry, the AI assistant is not available right now."); |
| | } finally { |
| | setLoading(false); |
| | } |
| | } |
| |
|
| | return ( |
| | <div className="fixed inset-0 z-40 flex items-end sm:items-center justify-center bg-black/30"> |
| | <div className="w-full max-w-lg bg-white rounded-t-2xl sm:rounded-2xl shadow-xl border border-stone-200 p-4 sm:p-5"> |
| | <div className="flex items-center justify-between mb-3"> |
| | <div> |
| | <h2 className="text-sm font-semibold text-stone-900"> |
| | Admin AI assistant |
| | </h2> |
| | <p className="text-xs text-stone-500"> |
| | Ask about renewals, churn risk, and membership health. |
| | </p> |
| | </div> |
| | <button |
| | type="button" |
| | onClick={onClose} |
| | className="text-xs text-stone-500 hover:text-stone-800" |
| | > |
| | Close |
| | </button> |
| | </div> |
| | |
| | <form onSubmit={handleAsk} className="space-y-3"> |
| | <textarea |
| | className="w-full rounded-lg border border-stone-200 px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 min-h-[70px]" |
| | placeholder="e.g., Which members are most at risk of churning this month?" |
| | value={message} |
| | onChange={(e) => setMessage(e.target.value)} |
| | /> |
| | |
| | <div className="flex items-center justify-between gap-3"> |
| | <div className="text-[11px] text-stone-400"> |
| | This calls the <code>/api/ai/admin</code> endpoint. |
| | </div> |
| | <button |
| | type="submit" |
| | disabled={loading} |
| | className="px-3 py-1.5 rounded-lg bg-purple-600 text-white text-xs font-medium hover:bg-purple-700 disabled:opacity-60" |
| | > |
| | {loading ? "Thinking…" : "Ask AI"} |
| | </button> |
| | </div> |
| | </form> |
| | |
| | {answer && ( |
| | <div className="mt-3 rounded-lg bg-stone-50 border border-stone-200 px-3 py-2 text-sm text-stone-800 whitespace-pre-wrap"> |
| | {answer} |
| | </div> |
| | )} |
| | </div> |
| | </div> |
| | ); |
| | } |
| |
|