React 'Reporting Filter' Shared State Example

Shared State example of a 'Reporting Filter' React form with the agent using hooks.

// FilterPanel.tsx
import { useEffect, useRef, useState } from "react";

type FilterState = {
  location: string; // e.g., "NYC"
  account: string;  // e.g., "Acme Inc"
};

interface Props {
  agentKey: string;
  initial?: Partial<FilterState>;
}

export default function FilterPanel({ agentKey, initial }: Props) {
  const [filters, setFilters] = useState<FilterState>({
    location: initial?.location ?? "",
    account: initial?.account ?? "",
  });

  const agentRef = useRef<any | null>(null);
  const stateKey = "filters_panel";
  const stateDescription = `
    type FilterState = {
      location: string; // e.g., "NYC"
      account: string;  // e.g., "Acme Inc"
    };

    interface Props {
      agentKey: string;
      initial?: Partial<FilterState>;
    }`;

  useEffect(() => {
    agentRef.current = (window as any).eucera?.agent(agentKey);

    const handleStateChange = (key: string, nextState: unknown) => {
      if (key === stateKey) setFilters(nextState as FilterState);
    };

    // initial sync
    agentRef.current?.shareState(stateKey, filters, handleStateChange, stateDescription);

    return () => {
      agentRef.current?.clearState(stateKey);
      agentRef.current = null;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [agentKey]);

  const updateField = <K extends keyof FilterState>(k: K, v: FilterState[K]) => {
    const next = { ...filters, [k]: v };
    setFilters(next);
    agentRef.current?.shareState(stateKey, next);
  };

  const LOCATIONS = ["NYC", "London", "Tel Aviv", "Remote"];
  const ACCOUNTS  = ["Acme Inc", "Globex", "Initech", "Umbrella"];

  return (
    <div style={{ display: "grid", gap: 12, maxWidth: 360 }}>
      <label>
        Location
        <select
          value={filters.location}
          onChange={(e) => updateField("location", e.target.value)}
        >
          <option value="">Any</option>
          {LOCATIONS.map((loc) => (
            <option key={loc} value={loc}>{loc}</option>
          ))}
        </select>
      </label>

      <label>
        Account
        <select
          value={filters.account}
          onChange={(e) => updateField("account", e.target.value)}
        >
          <option value="">Any</option>
          {ACCOUNTS.map((a) => (
            <option key={a} value={a}>{a}</option>
          ))}
        </select>
      </label>

      <small>
        {/* The agent now has a fresh snapshot at state key "filters_panel". */}
        Current: {JSON.stringify(filters)}
      </small>
    </div>
  );
}