← back to Omega Watches 2

src/app/(dashboard)/quarantine/page.tsx

112 lines

"use client";

import { useEffect, useState } from "react";
import { api } from "@/lib/api-client";
import { formatDateTime } from "@/lib/utils";

export default function QuarantineQueuePage() {
  const [data, setData] = useState<any>({ records: [], severity_counts: [] });
  const [error, setError] = useState("");
  const [resolving, setResolving] = useState<string | null>(null);
  const [notes, setNotes] = useState("");

  useEffect(() => {
    api.getQuarantine({ resolved: false }).then(setData).catch((e) => setError(e.message));
  }, []);

  async function handleResolve(id: string, action: "release" | "reject") {
    if (!notes.trim()) return;
    setResolving(id);
    try {
      await api.resolveQuarantine(id, notes, action);
      setData((prev: any) => ({
        ...prev,
        records: prev.records.filter((r: any) => r.id !== id),
      }));
      setNotes("");
    } catch (e: any) {
      setError(e.message);
    }
    setResolving(null);
  }

  const severityColor: Record<string, string> = {
    critical: "text-red-400 bg-red-900/20",
    high: "text-orange-400 bg-orange-900/20",
    medium: "text-yellow-400 bg-yellow-900/20",
    low: "text-blue-400 bg-blue-900/20",
  };

  return (
    <div className="space-y-6">
      <div className="flex items-center justify-between">
        <h1 className="text-xl font-bold text-gray-100">Quarantine Review Queue</h1>
        <div className="flex gap-2">
          {data.severity_counts.map((sc: any) => (
            <span key={sc.severity} className={`badge ${severityColor[sc.severity] || ""}`}>
              {sc.severity}: {sc.count}
            </span>
          ))}
        </div>
      </div>

      {error && <div className="rounded bg-red-900/30 p-3 text-red-300">{error}</div>}

      {data.records.length === 0 ? (
        <div className="card border-navy-700 p-8 text-center">
          <div className="text-4xl">&#10003;</div>
          <div className="mt-2 text-lg font-medium text-green-400">Queue Clear</div>
          <div className="text-sm text-gray-500">No quarantined records requiring review.</div>
        </div>
      ) : (
        <div className="space-y-3">
          {data.records.map((r: any) => (
            <div key={r.id} className="card border-navy-700">
              <div className="flex items-start justify-between">
                <div className="flex items-center gap-3">
                  <span className={`badge ${severityColor[r.severity] || "badge-info"}`}>{r.severity}</span>
                  <span className="text-sm font-medium text-gray-200">{r.reason}</span>
                </div>
                <span className="text-xs text-gray-500">{formatDateTime(r.created_at)}</span>
              </div>
              {r.source_name && (
                <div className="mt-2 text-xs text-gray-400">
                  Source: {r.source_name} | Ref: {r.reference_number_raw || "N/A"} | Price: ${r.price_usd || "N/A"} | Type: {r.event_type}
                </div>
              )}
              {r.details && (
                <pre className="mt-2 rounded bg-navy-950 p-2 text-xs text-gray-500">
                  {JSON.stringify(r.details, null, 2)}
                </pre>
              )}
              <div className="mt-3 flex items-center gap-2">
                <input
                  type="text"
                  placeholder="Resolution notes..."
                  className="input flex-1 text-xs"
                  value={resolving === r.id ? notes : ""}
                  onChange={(e) => { setResolving(r.id); setNotes(e.target.value); }}
                />
                <button
                  onClick={() => handleResolve(r.id, "release")}
                  disabled={resolving === r.id && !notes.trim()}
                  className="btn-primary text-xs"
                >
                  Release
                </button>
                <button
                  onClick={() => handleResolve(r.id, "reject")}
                  disabled={resolving === r.id && !notes.trim()}
                  className="btn-secondary text-xs"
                >
                  Reject
                </button>
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}