Files
Mohamed Mathar Irfan ed6610d5d8 Initial project upload
2026-07-28 17:57:02 +05:30

121 lines
5.8 KiB
TypeScript

"use client";
import { useEffect, useState } from "react";
import { Search, Plus, Lock } from "lucide-react";
import { api } from "@/lib/api";
export default function Support() {
const [orgs, setOrgs] = useState<any[]>([]);
const [q, setQ] = useState("");
const [selected, setSelected] = useState<string>("");
const [view, setView] = useState<any>(null);
const [notes, setNotes] = useState<any[]>([]);
const [note, setNote] = useState("");
useEffect(() => { api("/admin/organizations").then(setOrgs).catch(() => {}); }, []);
async function open(orgId: string) {
setSelected(orgId);
api(`/admin/organizations/${orgId}/support-view`).then(setView).catch(() => {});
api(`/admin/organizations/${orgId}/notes`).then(setNotes).catch(() => setNotes([]));
}
async function addNote() {
if (!note.trim()) return;
await api(`/admin/organizations/${selected}/notes`, { method: "POST", body: JSON.stringify({ note }) });
setNote("");
api(`/admin/organizations/${selected}/notes`).then(setNotes);
}
const filtered = orgs.filter((o) => o.name.toLowerCase().includes(q.toLowerCase()));
return (
<div className="space-y-5">
<div className="flex items-center gap-2">
<h2 className="text-xl font-bold">Support View</h2>
<span className="text-xs font-semibold bg-slate-100 text-slate-500 px-2 py-1 rounded-full flex items-center gap-1">
<Lock className="h-3 w-3" /> Read-only
</span>
</div>
<div className="grid md:grid-cols-[260px_1fr] gap-5">
{/* Org list */}
<div className="card p-4 h-fit">
<div className="relative mb-3">
<Search className="absolute left-3 top-2.5 h-4 w-4 text-slate-400" />
<input value={q} onChange={(e) => setQ(e.target.value)} placeholder="Search org…"
className="pl-9 pr-3 py-2 w-full rounded-lg border border-slate-200 text-sm" />
</div>
<div className="space-y-1 max-h-[60vh] overflow-y-auto">
{filtered.map((o) => (
<button key={o.org_id} onClick={() => open(o.org_id)}
className={`w-full text-left px-3 py-2 rounded-lg text-sm ${selected === o.org_id ? "bg-brand-50 text-brand-700" : "hover:bg-slate-50"}`}>
{o.name}
</button>
))}
</div>
</div>
{/* Detail */}
<div className="space-y-4">
{!view ? (
<div className="card p-12 text-center text-slate-400">Select an organization to debug.</div>
) : (
<>
<div className="card p-5">
<h3 className="font-bold">{view.org.name}</h3>
<p className="text-sm text-slate-500 capitalize">{view.org.status} · {view.org.contact_email}</p>
</div>
<div className="card overflow-x-auto">
<h3 className="font-bold p-4 pb-2">Products ({view.products.length})</h3>
<table className="w-full text-sm">
<thead className="bg-slate-50 text-slate-500 text-left">
<tr><th className="px-4 py-2">Name</th><th className="px-4 py-2">SKU</th><th className="px-4 py-2">Status</th><th className="px-4 py-2">QRs</th></tr>
</thead>
<tbody className="divide-y divide-slate-100">
{view.products.map((p: any, i: number) => (
<tr key={i}><td className="px-4 py-2">{p.name}</td><td className="px-4 py-2">{p.sku}</td><td className="px-4 py-2 capitalize">{p.status}</td><td className="px-4 py-2">{p.qr_count}</td></tr>
))}
</tbody>
</table>
</div>
<div className="card overflow-x-auto">
<h3 className="font-bold p-4 pb-2">Recent Scans</h3>
<table className="w-full text-sm">
<thead className="bg-slate-50 text-slate-500 text-left">
<tr><th className="px-4 py-2">Time</th><th className="px-4 py-2">Code</th><th className="px-4 py-2">City</th><th className="px-4 py-2">Device</th></tr>
</thead>
<tbody className="divide-y divide-slate-100">
{view.recent_scans.map((s: any, i: number) => (
<tr key={i}><td className="px-4 py-2 text-slate-500">{new Date(s.at).toLocaleString()}</td><td className="px-4 py-2 font-mono">{s.code}</td><td className="px-4 py-2">{s.city ?? "—"}</td><td className="px-4 py-2">{s.device ?? "—"}</td></tr>
))}
{view.recent_scans.length === 0 && <tr><td colSpan={4} className="px-4 py-6 text-center text-slate-400">No scans.</td></tr>}
</tbody>
</table>
</div>
<div className="card p-5">
<h3 className="font-bold mb-3">Internal Notes</h3>
<div className="flex gap-2 mb-3">
<input value={note} onChange={(e) => setNote(e.target.value)} placeholder="Add a debugging note…"
className="flex-1 px-3 py-2 rounded-lg border border-slate-200 text-sm" />
<button onClick={addNote} className="flex items-center gap-1 bg-brand-600 text-white px-3 py-2 rounded-lg text-sm font-semibold"><Plus className="h-4 w-4" /> Add</button>
</div>
<div className="space-y-2">
{notes.map((n) => (
<div key={n.id} className="text-sm border-b border-slate-100 py-2">
<div>{n.note}</div>
<div className="text-xs text-slate-400">{n.author} · {new Date(n.at).toLocaleString()}</div>
</div>
))}
{notes.length === 0 && <p className="text-sm text-slate-400">No notes.</p>}
</div>
</div>
</>
)}
</div>
</div>
</div>
);
}