← back to gorewood__arcane-optimizer

Function bodies 443 total

All specs Real LLM only Function bodies
purgeDuplicates function · typescript · L152-L165 (14 LOC)
src/stores/user-data-sync.ts
export function purgeDuplicates(params: PurgeParams): PurgeResult {
  const { duplicates, userEquipment, userEnchantments, userModifiers, userGems } = params;
  const equipIds = new Set(duplicates.equipment.map((d) => d.userItemId));
  const enchIds = new Set(duplicates.enchantments.map((d) => d.userItemId));
  const modIds = new Set(duplicates.modifiers.map((d) => d.userItemId));
  const gemIds = new Set(duplicates.gems.map((d) => d.userItemId));

  return {
    userEquipment: userEquipment.filter((r) => !equipIds.has(r.id)),
    userEnchantments: userEnchantments.filter((r) => !enchIds.has(r.id)),
    userModifiers: userModifiers.filter((r) => !modIds.has(r.id)),
    userGems: userGems.filter((r) => !gemIds.has(r.id)),
  };
}
ErrorBoundary.render method · typescript · L39-L45 (7 LOC)
src/ui/error-boundary.tsx
  override render(): React.ReactNode {
    if (!this.state.hasError) {
      return this.props.children;
    }

    return <ErrorFallback error={this.state.error} />;
  }
ErrorFallback function · typescript · L52-L77 (26 LOC)
src/ui/error-boundary.tsx
function ErrorFallback({
  error,
}: {
  error: Error | null;
}): React.JSX.Element {
  const message = error?.message ?? "An unexpected error occurred.";

  return (
    <div className="flex min-h-screen items-center justify-center bg-bg-primary p-6">
      <div className="card-game max-w-md space-y-4 p-8 text-center">
        <h1 className="text-xl font-bold text-accent-gold">
          Something went wrong
        </h1>
        <p className="text-sm text-text-secondary">{message}</p>
        <Button
          variant="default"
          onClick={() => {
            window.location.reload();
          }}
        >
          Reload
        </Button>
      </div>
    </div>
  );
}
validatePreSearch function · typescript · L51-L66 (16 LOC)
src/ui/hooks/use-search-worker.ts
function validatePreSearch(
  equipmentCount: number,
  enchantmentCount: number,
  constraintCount: number,
): string | null {
  if (equipmentCount === 0 && enchantmentCount === 0) {
    return "No gear enabled. Configure the gear pool before searching.";
  }
  if (equipmentCount === 0) {
    return "No equipment enabled. Enable at least one piece in the gear pool.";
  }
  if (constraintCount === 0) {
    return "No fitness constraints defined. Add at least one constraint.";
  }
  return null;
}
buildFilteredGearPool function · typescript · L77-L104 (28 LOC)
src/ui/hooks/use-search-worker.ts
function buildFilteredGearPool(
  getters: MergedGetters,
  ids: EnabledIds,
  enabledVariants: ReadonlySet<string>,
): GearPool {
  // Build base gear pool from merged data
  const basePool = buildMergedGearPool(getters, ids);

  // Expand equipment with variants into multiple candidates
  const expandedChestplates = expandEquipment(basePool.chestplates, enabledVariants);
  const expandedLeggings = expandEquipment(basePool.leggings, enabledVariants);
  const expandedAccessories = expandEquipment(basePool.accessories, enabledVariants);

  // Filter by slot type (expansion preserves slot, so just reassign)
  const isAccessory = (e: EquipmentPiece): boolean =>
    e.slot === "accessory" ||
    e.slot === "accessory-H" ||
    e.slot === "accessory-A";

  return {
    chestplates: expandedChestplates.filter((e) => e.slot === "chestplate"),
    leggings: expandedLeggings.filter((e) => e.slot === "leggings"),
    accessories: expandedAccessories.filter(isAccessory),
    enchantments: basePoo
checkLargeSearchPrompt function · typescript · L122-L143 (22 LOC)
src/ui/hooks/use-search-worker.ts
function checkLargeSearchPrompt(
  algorithm: Algorithm,
  combinations: number,
  setAlgorithm: (a: Algorithm) => void,
): Algorithm {
  if (algorithm !== "exhaustive" || combinations <= LARGE_SEARCH_THRESHOLD) {
    return algorithm;
  }

  const formatted = combinations.toLocaleString();
  const shouldSwitch = window.confirm(
    `This search has ${formatted} combinations, which may take a while.\n\n` +
    `Switch to Genetic algorithm for faster results?\n\n` +
    `Click OK to switch to Genetic, or Cancel to continue with Exhaustive.`
  );

  if (shouldSwitch) {
    setAlgorithm("genetic");
    return "genetic";
  }
  return algorithm;
}
createSearchWorker function · typescript · L155-L176 (22 LOC)
src/ui/hooks/use-search-worker.ts
function createSearchWorker(cb: WorkerCallbacks): Worker {
  const worker = new Worker(
    new URL("../../workers/search-worker.ts", import.meta.url),
    { type: "module" },
  );

  worker.onmessage = (event: MessageEvent<WorkerResponse>) => {
    const msg = event.data;
    switch (msg.type) {
      case "progress": cb.onProgress(msg.checked, msg.total, msg.bestScore, msg.topResults); break;
      case "complete": cb.onComplete(msg.results, msg.exitMetadata); worker.terminate(); break;
      case "error": cb.onError(msg.message); worker.terminate(); break;
    }
  };

  worker.onerror = () => {
    cb.onError("Search worker encountered an unexpected error");
    worker.terminate();
  };

  return worker;
}
Repobility — the code-quality scanner for AI-generated software · https://repobility.com
launchWorker function · typescript · L192-L209 (18 LOC)
src/ui/hooks/use-search-worker.ts
function launchWorker(config: LaunchConfig, cb: WorkerCallbacks): Worker {
  const worker = createSearchWorker(cb);
  const request: WorkerRequest = {
    type: "start",
    gearPool: config.gearPool,
    constraints: DEFAULT_HARD_CONSTRAINTS,
    fitness: [...config.fitness],
    options: {
      maxResults: config.maxResults,
      populationSize: config.gaParams.populationSize,
      generations: config.gaParams.generations,
      mutationRate: config.gaParams.mutationRate,
    },
    algorithm: config.algorithm,
  };
  worker.postMessage(request);
  return worker;
}
launchCoordinator function · typescript · L227-L243 (17 LOC)
src/ui/hooks/use-search-worker.ts
function launchCoordinator(config: CoordinatorLaunchConfig, cb: CoordinatorCallbacks): ExhaustiveCoordinator {
  const coordinator = new ExhaustiveCoordinator();
  coordinator.start(
    {
      gearPool: config.gearPool,
      constraints: DEFAULT_HARD_CONSTRAINTS,
      fitness: config.fitness,
      maxResults: config.maxResults,
    },
    {
      onProgress: cb.onProgress,
      onComplete: cb.onComplete,
      onError: cb.onError,
    },
  );
  return coordinator;
}
launchIslandCoordinator function · typescript · L262-L282 (21 LOC)
src/ui/hooks/use-search-worker.ts
function launchIslandCoordinator(config: IslandLaunchConfig, cb: IslandCallbacks): IslandCoordinator {
  const coordinator = new IslandCoordinator();
  coordinator.start(
    {
      gearPool: config.gearPool,
      constraints: DEFAULT_HARD_CONSTRAINTS,
      fitness: config.fitness,
      maxResults: config.maxResults,
      populationSize: config.gaParams.populationSize,
      generations: config.gaParams.generations,
      mutationRate: config.gaParams.mutationRate,
      islandCount: config.gaParams.islandCount,
    },
    {
      onProgress: cb.onProgress,
      onComplete: cb.onComplete,
      onError: cb.onError,
    },
  );
  return coordinator;
}
executeSearch function · typescript · L307-L354 (48 LOC)
src/ui/hooks/use-search-worker.ts
function executeSearch(ctx: SearchContext): void {
  const { startSearch, setResults, setPreviewResults, setError, setExpandedCards, setProgress, workerRef, coordinatorRef, islandCoordinatorRef, algorithm, gaParams, constraints, enabledVariants, ids, getters, maxResults } = ctx;
  const basePool = buildFilteredGearPool(getters, ids, enabledVariants);

  // For exhaustive search, filter pool to items contributing to goal stats (or with sockets)
  let gearPool = basePool;
  let filterMessage: string | null = null;
  if (algorithm === "exhaustive") {
    const { pool: filteredPool, stats } = filterPoolByGoals(basePool, constraints);
    gearPool = filteredPool;
    filterMessage = formatFilterStats(stats);
  }

  startSearch();
  setProgress({ ...INITIAL_PROGRESS, startTime: Date.now(), filterMessage });

  const onProg = (c: number, t: number, b: number, r: readonly SearchResult[]): void => {
    setProgress((p) => ({ ...p, checked: c, total: t, bestScore: b, resultsCount: r.length }));
useSearchWorker function · typescript · L366-L426 (61 LOC)
src/ui/hooks/use-search-worker.ts
export function useSearchWorker(maxResults: number): WorkerHookResult {
  const startSearch = useSearchStore((s) => s.startSearch);
  const setResults = useSearchStore((s) => s.setResults);
  const setPreviewResults = useSearchStore((s) => s.setPreviewResults);
  const setError = useSearchStore((s) => s.setError);
  const reset = useSearchStore((s) => s.reset);
  const algorithm = useSearchStore((s) => s.algorithm);
  const setAlgorithm = useSearchStore((s) => s.setAlgorithm);
  const gaParams = useSearchStore((s) => s.gaParams);
  const constraints = useFitnessStore((s) => s.constraintsConfig.constraints);
  const enabledVariants = useFitnessStore((s) => s.enabledVariants);
  const eqIds = useGearPoolStore((s) => s.enabledEquipmentIds);
  const enIds = useGearPoolStore((s) => s.enabledEnchantmentIds);
  const modIds = useGearPoolStore((s) => s.enabledModifierIds);
  const gemIds = useGearPoolStore((s) => s.enabledGemIds);
  const setExpandedCards = useUIStore((s) => s.setExpandedCards
AppShell function · typescript · L29-L78 (50 LOC)
src/ui/layout/app-shell.tsx
export function AppShell(): React.JSX.Element {
  const activePanel = useUIStore((s) => s.activePanel);
  const setActivePanel = useUIStore((s) => s.setActivePanel);

  return (
    <div className="flex min-h-screen flex-col bg-bg-primary">
      {/* Header */}
      <header className="border-b border-border-default bg-bg-secondary">
        <div className="mx-auto max-w-5xl px-4 py-3">
          <h1 className="text-lg font-bold text-accent-gold">
            Arcane Odyssey Armor Optimizer
          </h1>
        </div>
      </header>

      {/* Tab bar */}
      <nav className="border-b border-border-default bg-bg-secondary">
        <div className="mx-auto max-w-5xl flex items-center gap-1 px-4">
          {TABS.map((tab) => (
            <TabButton
              key={tab.id}
              tab={tab}
              isActive={activePanel === tab.id}
              onSelect={setActivePanel}
            />
          ))}
          <div className="flex-1" />
          <DataControls />
     
PanelContent function · typescript · L120-L141 (22 LOC)
src/ui/layout/app-shell.tsx
function PanelContent({
  panel,
}: {
  panel: UIState["activePanel"];
}): React.JSX.Element {
  return (
    <>
      <div className={panel === "optimizer" ? "" : "hidden"}>
        <OptimizerPage />
      </div>
      <div className={panel === "gear" ? "" : "hidden"}>
        <GearInventoryPanel />
      </div>
      <div className={panel === "data" ? "" : "hidden"}>
        <DataManagementPanel />
      </div>
      <div className={panel === "help" ? "" : "hidden"}>
        <HelpPanel />
      </div>
    </>
  );
}
DataControls function · typescript · L62-L77 (16 LOC)
src/ui/layout/data-controls.tsx
export function DataControls(): React.JSX.Element {
  const { fileInputRef, handleExport, handleImport } = useDataImportExport();
  const [confirmClear, setConfirmClear] = useState(false);

  return (
    <>
      <div className="flex items-center gap-1.5">
        <input ref={fileInputRef} type="file" accept=".json" className="hidden" onChange={handleImport} />
        <Button variant="outline" size="xs" onClick={() => { fileInputRef.current?.click(); }}>Import</Button>
        <Button variant="outline" size="xs" onClick={handleExport}>Export</Button>
        <Button variant="outline" size="xs" className="text-stat-negative hover:text-stat-negative" onClick={() => { setConfirmClear(true); }}>Clear All</Button>
      </div>
      <ConfirmClearDialog open={confirmClear} onOpenChange={setConfirmClear} />
    </>
  );
}
Repobility · code-quality intelligence platform · https://repobility.com
getAppliedVariant function · typescript · L78-L83 (6 LOC)
src/ui/panels/build-card.tsx
function getAppliedVariant(piece: EquipmentPiece | ExpandedEquipment): string | undefined {
  if ("appliedVariant" in piece) {
    return piece.appliedVariant;
  }
  return undefined;
}
formatPieceName function · typescript · L85-L92 (8 LOC)
src/ui/panels/build-card.tsx
function formatPieceName(piece: EquipmentPiece | ExpandedEquipment): string {
  const variant = getAppliedVariant(piece);
  if (variant != null) {
    const capitalizedVariant = variant.charAt(0).toUpperCase() + variant.slice(1);
    return `${piece.name} (${capitalizedVariant})`;
  }
  return piece.name;
}
formatBuildText function · typescript · L98-L118 (21 LOC)
src/ui/panels/build-card.tsx
function formatBuildText(rank: number, result: SearchResult): string {
  const lines = [`Build #${String(rank)} (Score: ${result.score.toFixed(1)})`];

  for (const slot of result.loadout.slots) {
    const label = SLOT_LABELS[slot.piece.slot];
    const parts = [formatPieceName(slot.piece)];
    if (slot.enchantment != null) parts.push(`[${slot.enchantment.name}]`);
    if (slot.modifier != null) parts.push(`(${slot.modifier.name})`);
    if (slot.gems.length > 0) {
      parts.push(`{${slot.gems.map((g) => g.name).join(", ")}}`);
    }
    lines.push(`${label}: ${parts.join(" ")}`);
  }

  const statParts = STAT_NAMES.filter((s) => result.stats[s] !== 0).map(
    (s) => `${s}=${String(result.stats[s])}`,
  );
  lines.push(`Stats: ${statParts.join(", ")}`);

  return lines.join("\n");
}
BuildCard function · typescript · L143-L179 (37 LOC)
src/ui/panels/build-card.tsx
export function BuildCard(props: BuildCardProps): React.JSX.Element {
  const { rank, result, constraints, disabled = false, expanded: controlledExpanded, onToggleExpanded } = props;
  const [internalExpanded, setInternalExpanded] = useState(false);
  const [copied, setCopied] = useState(false);

  const isControlled = controlledExpanded !== undefined;
  const expanded = isControlled ? controlledExpanded : internalExpanded;
  const constraintMap = buildConstraintMap(constraints);

  const handleCopy = useCallback(() => {
    if (disabled) return;
    void navigator.clipboard.writeText(formatBuildText(rank, result)).then(() => {
      setCopied(true);
      setTimeout(() => { setCopied(false); }, 1500);
    });
  }, [rank, result, disabled]);

  const handleToggle = useCallback(() => {
    if (disabled) return;
    if (isControlled && onToggleExpanded != null) onToggleExpanded();
    else setInternalExpanded((prev) => !prev);
  }, [disabled, isControlled, onToggleExpanded]);

  const ca
KeyStatsDisplay function · typescript · L224-L237 (14 LOC)
src/ui/panels/build-card.tsx
function KeyStatsDisplay({ stats }: { readonly stats: SearchResult["stats"] }): React.JSX.Element {
  // Show all non-zero stats in the collapsed header
  const nonZeroStats = STAT_NAMES.filter((stat) => stats[stat] !== 0);
  return (
    <div className="hidden sm:flex items-center gap-2 ml-2 flex-wrap">
      {nonZeroStats.map((stat) => (
        <span key={stat} className="text-[10px] text-text-secondary">
          <span className="text-text-muted">{STAT_LABELS[stat]}</span>{" "}
          <span className="font-stat">{stats[stat]}</span>
        </span>
      ))}
    </div>
  );
}
CompactSlotList function · typescript · L267-L301 (35 LOC)
src/ui/panels/build-card.tsx
function CompactSlotList({
  result,
}: {
  readonly result: SearchResult;
}): React.JSX.Element {
  return (
    <div className="px-3 pb-2 space-y-0.5">
      {result.loadout.slots.map((slot, i) => {
        const variant = getAppliedVariant(slot.piece);
        return (
          <div key={i} className="flex items-center gap-1.5 text-[11px]">
            <Badge variant="outline" className="px-1.5 py-0 text-[9px] shrink-0 w-10 justify-center">
              {SLOT_LABELS[slot.piece.slot]}
            </Badge>
            <span className="text-text-primary">{slot.piece.name}</span>
            {variant != null && (
              <span className="text-accent-teal capitalize">({variant})</span>
            )}
            {slot.enchantment != null && (
              <span className="text-accent-amber">[{slot.enchantment.name}]</span>
            )}
            {slot.modifier != null && (
              <span className="text-text-muted">({slot.modifier.name})</span>
            )}
          
ExpandedContent function · typescript · L307-L355 (49 LOC)
src/ui/panels/build-card.tsx
function ExpandedContent({
  result,
  constraintMap,
}: {
  readonly result: SearchResult;
  readonly constraintMap: ReadonlyMap<StatName, SoftConstraint>;
}): React.JSX.Element {
  return (
    <div className="px-3 py-3 space-y-4">
      {/* Stat bars - grouped in 4 columns */}
      <div>
        <h4 className="text-xs font-semibold text-accent-gold mb-2">
          Total Stats
        </h4>
        <div className="grid grid-cols-4 gap-x-3 gap-y-1">
          {STAT_GROUP_ORDER.map((groupKey) => {
            const group = STAT_GROUPS[groupKey];
            return (
              <div key={groupKey} className="space-y-1">
                <span className="text-[10px] font-medium text-text-muted">{group.label}</span>
                {group.stats.map((stat) => (
                  <StatBar
                    key={stat}
                    stat={stat}
                    value={result.stats[stat]}
                    max={STAT_MAX_VALUES[stat]}
                    constraint={constraintM
ToggleIcon function · typescript · L31-L40 (10 LOC)
src/ui/panels/collapsible-section.tsx
function ToggleIcon({ disabled, open }: { disabled: boolean; open: boolean }): React.JSX.Element {
  if (disabled) {
    return <Lock className="h-4 w-4 text-text-muted" />;
  }
  return (
    <ChevronRight
      className={`h-4 w-4 text-text-muted transition-transform ${open ? "rotate-90" : ""}`}
    />
  );
}
Repobility · code-quality intelligence · https://repobility.com
TrailingContent function · typescript · L43-L59 (17 LOC)
src/ui/panels/collapsible-section.tsx
function TrailingContent({
  disabled,
  summary,
  disabledReason,
}: {
  disabled: boolean;
  summary: React.ReactNode | undefined;
  disabledReason: string | undefined;
}): React.JSX.Element | null {
  if (disabled && disabledReason != null) {
    return <span className="ml-auto text-xs text-text-muted italic">{disabledReason}</span>;
  }
  if (summary != null) {
    return <span className="ml-auto text-xs text-text-secondary truncate max-w-[60%]">{summary}</span>;
  }
  return null;
}
CollapsibleSection function · typescript · L61-L106 (46 LOC)
src/ui/panels/collapsible-section.tsx
export function CollapsibleSection({
  title,
  summary,
  children,
  defaultOpen = false,
  open: controlledOpen,
  onOpenChange,
  disabled = false,
  disabledReason,
}: CollapsibleSectionProps): React.JSX.Element {
  const [internalOpen, setInternalOpen] = useState(defaultOpen);
  const isControlled = controlledOpen !== undefined;
  const open = isControlled ? controlledOpen : internalOpen;
  const handleOpenChange = (newOpen: boolean): void => {
    if (isControlled) {
      onOpenChange?.(newOpen);
    } else {
      setInternalOpen(newOpen);
    }
  };
  const effectiveOpen = disabled ? false : open;

  const roundedClass = effectiveOpen ? "rounded-t-md" : "rounded-md";
  const buttonClass = disabled
    ? `flex w-full items-center gap-2 ${roundedClass} border border-border-default bg-bg-surface px-4 py-3 text-left transition-colors opacity-60 cursor-not-allowed`
    : `flex w-full items-center gap-2 ${roundedClass} border border-border-default bg-bg-surface px-4 py-3 text-left 
ConstraintPips function · typescript · L18-L43 (26 LOC)
src/ui/panels/constraint-pips.tsx
export function ConstraintPips({
  stats,
  constraints,
}: ConstraintPipsProps): React.JSX.Element {
  if (constraints.length === 0) {
    return <span className="text-xs text-text-muted">No constraints</span>;
  }

  return (
    <div className="flex items-center gap-1">
      {constraints.map((c, i) => {
        const value = stats[c.stat];
        const level = getSatisfaction(value, c);
        const bgClass = SATISFACTION_BG_CLASSES[level];

        return (
          <span
            key={`${c.stat}-${String(i)}`}
            className={`inline-block h-2 w-2 rounded-full ${bgClass}`}
            title={`${c.stat}: ${String(value)} (${c.type}${c.value != null ? ` ${String(c.value)}` : ""})`}
          />
        );
      })}
    </div>
  );
}
useValueHandler function · typescript · L80-L92 (13 LOC)
src/ui/panels/constraint-row.tsx
function useValueHandler(
  constraint: SoftConstraint,
  index: number,
  onUpdate: (i: number, c: SoftConstraint) => void,
  statMax: number | undefined,
): (v: number) => void {
  return useCallback((v: number) => {
    const clamped = statMax != null ? Math.min(v, statMax) : v;
    let newHardCap = constraint.hardCap;
    if (newHardCap != null && newHardCap < clamped) newHardCap = clamped;
    onUpdate(index, { ...constraint, value: clamped, hardCap: newHardCap });
  }, [constraint, index, onUpdate, statMax]);
}
useHardCapHandler function · typescript · L94-L106 (13 LOC)
src/ui/panels/constraint-row.tsx
function useHardCapHandler(
  constraint: SoftConstraint,
  index: number,
  onUpdate: (i: number, c: SoftConstraint) => void,
  statMax: number | undefined,
): (hc: number | undefined) => void {
  return useCallback((hc: number | undefined) => {
    const clamped = hc != null && statMax != null ? Math.min(hc, statMax) : hc;
    let newValue = constraint.value ?? 0;
    if (clamped != null && newValue > clamped) newValue = clamped;
    onUpdate(index, { ...constraint, value: newValue, hardCap: clamped });
  }, [constraint, index, onUpdate, statMax]);
}
ConstraintRow function · typescript · L112-L141 (30 LOC)
src/ui/panels/constraint-row.tsx
export function ConstraintRow({ constraint, index, onUpdate, onRemove }: ConstraintRowProps): React.JSX.Element {
  const scoringMode = useFitnessStore((s) => s.scoringMode);
  const showValue = VALUE_TYPES.has(constraint.type);
  const showHardCap = HARDCAP_TYPES.has(constraint.type);
  const isBetween = constraint.type === "between";
  const statMax = STAT_MAX_VALUES[constraint.stat];
  const handleValue = useValueHandler(constraint, index, onUpdate, statMax);
  const handleHardCap = useHardCapHandler(constraint, index, onUpdate, statMax);

  // In efficiency/multiplier modes, only hard filter types are available
  const availableTypes = scoringMode === "linear" ? CONSTRAINT_TYPES : HARD_FILTER_TYPES;

  return (
    <div className="flex flex-wrap items-center gap-2 rounded-md border border-border-subtle bg-bg-surface px-2 py-1.5 transition-colors hover:border-border-default">
      {/* Row 1: stat + operator (always together) */}
      <div className="flex items-center gap-2 shrink-
handleTypeChange function · typescript · L147-L159 (13 LOC)
src/ui/panels/constraint-row.tsx
function handleTypeChange(
  constraint: SoftConstraint,
  index: number,
  type: ConstraintType,
  onUpdate: (i: number, c: SoftConstraint) => void,
): void {
  onUpdate(index, {
    ...constraint,
    type,
    value: VALUE_TYPES.has(type) ? (constraint.value ?? 0) : undefined,
    hardCap: HARDCAP_TYPES.has(type) ? constraint.hardCap : undefined,
  });
}
ApplicableToCheckboxes function · typescript · L21-L62 (42 LOC)
src/ui/panels/data-management/applicable-to-checkboxes.tsx
export function ApplicableToCheckboxes({
  applicableTo,
  onChange,
}: ApplicableToCheckboxesProps): React.JSX.Element {
  const hasArmor = applicableTo.includes("armor");
  const hasAccessory = applicableTo.includes("accessory");

  const toggle = (type: "armor" | "accessory"): void => {
    const current = new Set(applicableTo);
    if (current.has(type)) {
      current.delete(type);
    } else {
      current.add(type);
    }
    onChange([...current] as ("armor" | "accessory")[]);
  };

  return (
    <div className="flex gap-4">
      <div className="flex items-center gap-1.5">
        <Checkbox
          id="armor"
          checked={hasArmor}
          onCheckedChange={() => { toggle("armor"); }}
        />
        <Label htmlFor="armor" className="text-xs text-text-secondary cursor-pointer">
          Armor
        </Label>
      </div>
      <div className="flex items-center gap-1.5">
        <Checkbox
          id="accessory"
          checked={hasAccessory}
          onChe
About: code-quality intelligence by Repobility · https://repobility.com
AtlanteanBehaviorEditor function · typescript · L22-L71 (50 LOC)
src/ui/panels/data-management/atlantean-behavior-editor.tsx
export function AtlanteanBehaviorEditor({
  modifier,
  onChange,
}: AtlanteanBehaviorEditorProps): React.JSX.Element {
  const hasAtlantean = modifier.atlanteanBehavior !== undefined;
  const [expanded, setExpanded] = useState(hasAtlantean);

  const toggleAtlantean = (): void => {
    if (hasAtlantean) {
      const { atlanteanBehavior: _, ...rest } = modifier;
      onChange(rest as Modifier);
      setExpanded(false);
    } else {
      const config: AtlanteanConfig = { insanity: 0, possibleBonusStats: [] };
      onChange({ ...modifier, atlanteanBehavior: config });
      setExpanded(true);
    }
  };

  const handleClick = (): void => {
    if (hasAtlantean) {
      setExpanded((p) => !p);
    } else {
      toggleAtlantean();
    }
  };

  return (
    <div className="border border-border-subtle rounded-md overflow-hidden">
      <button
        type="button"
        onClick={handleClick}
        className="flex w-full items-center gap-2 px-2 py-1.5 text-left text-sm text-text-m
AtlanteanFields function · typescript · L32-L60 (29 LOC)
src/ui/panels/data-management/atlantean-fields.tsx
export function AtlanteanFields({
  config,
  onChange,
  onRemove,
}: AtlanteanFieldsProps): React.JSX.Element {
  const toggleStat = (stat: StatName): void => {
    const current = new Set(config.possibleBonusStats);
    if (current.has(stat)) {
      current.delete(stat);
    } else {
      current.add(stat);
    }
    onChange({ ...config, possibleBonusStats: [...current] });
  };

  return (
    <div className="p-2 space-y-3 border-t border-border-subtle">
      <InsanityField config={config} onChange={onChange} />
      <BonusStatsField config={config} toggleStat={toggleStat} />
      <button
        type="button"
        onClick={onRemove}
        className="text-xs text-stat-negative hover:underline"
      >
        Remove Atlantean Behavior
      </button>
    </div>
  );
}
AutocompleteInput function · typescript · L23-L47 (25 LOC)
src/ui/panels/data-management/autocomplete-input.tsx
export function AutocompleteInput({
  value,
  placeholder,
  options,
  onChange,
}: AutocompleteInputProps): React.JSX.Element {
  const listId = useId();

  return (
    <>
      <Input
        value={value}
        placeholder={placeholder}
        list={listId}
        className="h-8 text-sm"
        onChange={(e) => { onChange(e.target.value); }}
      />
      <datalist id={listId}>
        {options.map((opt) => (
          <option key={opt} value={opt} />
        ))}
      </datalist>
    </>
  );
}
ConfirmClearDialog function · typescript · L29-L67 (39 LOC)
src/ui/panels/data-management/confirm-clear-dialog.tsx
export function ConfirmClearDialog({
  open,
  onOpenChange,
}: ConfirmClearDialogProps): React.JSX.Element {
  const clearAllUserData = useUserDataStore((s) => s.clearAllUserData);

  const handleConfirm = (): void => {
    clearAllUserData();
    onOpenChange(false);
  };

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="bg-bg-surface border-border-default">
        <DialogHeader>
          <DialogTitle className="text-text-primary">
            Clear All User Data?
          </DialogTitle>
          <DialogDescription className="text-text-secondary">
            This will permanently delete all custom items and modifications.
            Bundled data will be restored to defaults.
          </DialogDescription>
        </DialogHeader>
        <DialogFooter className="gap-2">
          <Button
            variant="outline"
            size="sm"
            onClick={() => { onOpenChange(false); }}
          >
            Cancel
          <
useDataCounts function · typescript · L32-L39 (8 LOC)
src/ui/panels/data-management/data-management-panel.tsx
function useDataCounts(): Record<GameDataTab, number> {
  return useUserDataStore(useShallow((s) => ({
    enchantments: s.getMergedEnchantments().length,
    modifiers: s.getMergedModifiers().length,
    gems: s.getMergedGems().length,
    variants: s.getMergedVariantTypes().length,
  })));
}
DataManagementPanel function · typescript · L45-L106 (62 LOC)
src/ui/panels/data-management/data-management-panel.tsx
export function DataManagementPanel(): React.JSX.Element {
  const [filter, setFilter] = useState("");
  const [sortBy, setSortBy] = useState<SortOption>("name-asc");
  const [activeTab, setActiveTab] = useState<GameDataTab>("enchantments");
  const [addRequest, setAddRequest] = useState(0);
  const counts = useDataCounts();

  const handleAdd = useCallback((): void => {
    setAddRequest((prev) => prev + 1);
  }, []);

  return (
    <div className="space-y-4 p-4">
      <PanelHeader onAdd={handleAdd} />
      <div className="flex items-center gap-2">
        <SearchInput value={filter} onChange={setFilter} />
        <SortSelect value={sortBy} onChange={setSortBy} />
      </div>

      <Tabs value={activeTab} onValueChange={(v) => { if (isGameDataTab(v)) setActiveTab(v); }}>
        <TabsList variant="line">
          <TabsTrigger value="enchantments">Enchantments ({counts.enchantments})</TabsTrigger>
          <TabsTrigger value="modifiers">Modifiers ({counts.modifiers})</TabsTrigg
EnchantmentEditDialog function · typescript · L27-L91 (65 LOC)
src/ui/panels/data-management/enchantment-edit-dialog.tsx
export function EnchantmentEditDialog({
  enchantment,
  isNew,
  onClose,
}: EnchantmentEditDialogProps): React.JSX.Element {
  const addEnchantment = useUserDataStore((s) => s.addEnchantment);
  const updateEnchantment = useUserDataStore((s) => s.updateEnchantment);

  const [draft, setDraft] = useState<Enchantment | null>(null);
  const [purpose, setPurpose] = useState<ItemPurpose>("contribution");

  useEffect(() => {
    setDraft(enchantment);
  }, [enchantment]);

  useEffect(() => {
    if (enchantment !== null) {
      setPurpose("contribution");
    }
  }, [enchantment]);

  const handleSave = (): void => {
    if (draft === null) return;
    if (isNew) {
      addEnchantment(draft, purpose);
    } else {
      updateEnchantment(draft.id, draft);
    }
    onClose();
  };

  const isValid =
    draft !== null &&
    draft.name.trim() !== "" &&
    draft.id.trim() !== "" &&
    draft.applicableTo.length > 0;

  return (
    <ItemEditorDialog
      open={enchantment !== null}
  
EnchantmentEditor function · typescript · L16-L79 (64 LOC)
src/ui/panels/data-management/enchantment-editor.tsx
export function EnchantmentEditor({
  filter,
  sortBy,
  addRequest,
}: {
  readonly filter: string;
  readonly sortBy: SortOption;
  readonly addRequest: number;
}): React.JSX.Element {
  // Subscribe to userEnchantments to trigger re-render on changes
  const userEnchantments = useUserDataStore((s) => s.userEnchantments);
  const getMergedEnchantments = useUserDataStore((s) => s.getMergedEnchantments);
  const getDeletedEnchantments = useUserDataStore((s) => s.getDeletedEnchantments);

  const [editingItem, setEditingItem] = useState<Enchantment | null>(null);
  const [isNew, setIsNew] = useState(false);

  // Recompute merged items when userEnchantments changes
  const items = useMemo(() => getMergedEnchantments(), [getMergedEnchantments, userEnchantments]);
  const deletedItems = useMemo(() => getDeletedEnchantments(), [getDeletedEnchantments, userEnchantments]);

  const filtered = useMemo(() => {
    let result = items;
    if (filter !== "") {
      const lower = filter.toLower
Repobility — the code-quality scanner for AI-generated software · https://repobility.com
createNewEnchantment function · typescript · L85-L93 (9 LOC)
src/ui/panels/data-management/enchantment-editor.tsx
function createNewEnchantment(): Enchantment {
  return {
    id: `custom-${String(Date.now())}`,
    name: "",
    tier: 1,
    applicableTo: ["armor", "accessory"],
    stats: {},
  };
}
EnchantmentForm function · typescript · L26-L83 (58 LOC)
src/ui/panels/data-management/enchantment-form.tsx
export function EnchantmentForm({
  enchantment,
  onChange,
  isNew,
}: EnchantmentFormProps): React.JSX.Element {
  return (
    <div className="space-y-4">
      <div className="grid grid-cols-2 gap-4">
        <div>
          <Label className="text-xs text-text-muted mb-1 block">ID</Label>
          <Input
            value={enchantment.id}
            onChange={(e) => { onChange({ ...enchantment, id: e.target.value }); }}
            disabled={!isNew}
            className="h-8 text-sm"
            placeholder="unique-enchantment-id"
          />
        </div>
        <div>
          <Label className="text-xs text-text-muted mb-1 block">Name</Label>
          <Input
            value={enchantment.name}
            onChange={(e) => { onChange({ ...enchantment, name: e.target.value }); }}
            className="h-8 text-sm"
            placeholder="Enchantment Name"
          />
        </div>
      </div>

      <div className="grid grid-cols-2 gap-4">
        <div>
          <Lab
EnchantmentList function · typescript · L25-L65 (41 LOC)
src/ui/panels/data-management/enchantment-list.tsx
export function EnchantmentList({
  items,
  deletedItems,
  onEdit,
}: EnchantmentListProps): React.JSX.Element {
  const deleteEnchantment = useUserDataStore((s) => s.deleteEnchantment);
  const restoreEnchantment = useUserDataStore((s) => s.restoreEnchantment);

  return (
    <>
      <div className="border border-border-subtle rounded-md divide-y divide-border-subtle">
        {items.length === 0 ? (
          <p className="text-text-muted text-xs p-2">No matching enchantments.</p>
        ) : (
          items.map((m) => (
            <EnchantmentRow
              key={m.item.id}
              item={m}
              onEdit={() => { onEdit(m.item); }}
              onDelete={() => { deleteEnchantment(m.item.id); }}
              onReset={m.isModified ? () => { restoreEnchantment(m.item.id); } : undefined}
            />
          ))
        )}
      </div>

      {deletedItems.length > 0 && (
        <HiddenItemsSection
          items={deletedItems}
          onRestore={(id) => {
EnchantmentRow function · typescript · L28-L65 (38 LOC)
src/ui/panels/data-management/enchantment-row.tsx
export function EnchantmentRow({
  item,
  onEdit,
  onDelete,
  onReset,
}: EnchantmentRowProps): React.JSX.Element {
  const enchantment = item.item;

  return (
    <div className="flex items-center gap-2 px-2 py-1.5 bg-bg-surface hover:bg-bg-elevated transition-colors">
      <span className="text-sm text-text-primary truncate flex-1">
        {enchantment.name}
      </span>
      <SourceBadge item={item} />
      <TierBadge tier={enchantment.tier} />
      <ApplicableToBadge applicableTo={enchantment.applicableTo} />
      <StatSummary stats={enchantment.stats} />
      <div className="flex gap-1 ml-2">
        <Button variant="ghost" size="xs" onClick={onEdit}>
          Edit
        </Button>
        {item.isModified && onReset && (
          <Button variant="ghost" size="xs" onClick={onReset}>
            Reset
          </Button>
        )}
        <Button
          variant="ghost"
          size="xs"
          className="text-stat-negative hover:text-stat-negative"
         
EquipmentBasicFields function · typescript · L48-L107 (60 LOC)
src/ui/panels/data-management/equipment-basic-fields.tsx
export function EquipmentBasicFields({
  equipment,
  onChange,
  isNew,
}: EquipmentBasicFieldsProps): React.JSX.Element {
  const update = <K extends keyof EquipmentPiece>(
    key: K,
    value: EquipmentPiece[K],
  ): void => {
    onChange({ ...equipment, [key]: value });
  };

  return (
    <>
      <FormField label="ID">
        <Input
          value={equipment.id}
          disabled={!isNew}
          className="h-8 text-sm"
          onChange={(e) => { update("id", e.target.value); }}
        />
      </FormField>

      <FormField label="Name">
        <Input
          value={equipment.name}
          className="h-8 text-sm"
          onChange={(e) => { update("name", e.target.value); }}
        />
      </FormField>

      <FormField label="Slot">
        <Select
          value={equipment.slot}
          onValueChange={(v) => { if (isSlotType(v)) update("slot", v); }}
        >
          <SelectTrigger size="sm" className="h-8">
            <SelectValue />
          </Sel
EquipmentEditDialog function · typescript · L27-L84 (58 LOC)
src/ui/panels/data-management/equipment-edit-dialog.tsx
export function EquipmentEditDialog({
  equipment,
  isNew,
  onClose,
}: EquipmentEditDialogProps): React.JSX.Element {
  const addEquipment = useUserDataStore((s) => s.addEquipment);
  const updateEquipment = useUserDataStore((s) => s.updateEquipment);

  const [draft, setDraft] = useState<EquipmentPiece | null>(null);
  const [purpose, setPurpose] = useState<ItemPurpose>("contribution");

  useEffect(() => {
    setDraft(equipment);
  }, [equipment]);

  useEffect(() => {
    if (equipment !== null) {
      setPurpose("contribution");
    }
  }, [equipment]);

  const handleSave = (): void => {
    if (draft === null) return;
    if (isNew) {
      addEquipment(draft, purpose);
    } else {
      updateEquipment(draft.id, draft);
    }
    onClose();
  };

  const isValid =
    draft !== null && draft.name.trim() !== "" && draft.id.trim() !== "";

  return (
    <ItemEditorDialog
      open={equipment !== null}
      onOpenChange={(open) => {
        if (!open) onClose();
      }}
 
EquipmentEditorHeader function · typescript · L20-L37 (18 LOC)
src/ui/panels/data-management/equipment-editor-header.tsx
export function EquipmentEditorHeader({
  count,
  onAddNew,
}: EquipmentEditorHeaderProps): React.JSX.Element {
  return (
    <div className="flex items-center justify-between">
      <h3 className="text-sm font-semibold text-accent-gold">
        Equipment
        <span className="ml-2 text-xs text-text-muted font-normal">
          ({String(count)} items)
        </span>
      </h3>
      <Button variant="outline" size="xs" onClick={onAddNew}>
        + Add New
      </Button>
    </div>
  );
}
EquipmentEditor function · typescript · L17-L74 (58 LOC)
src/ui/panels/data-management/equipment-editor.tsx
export function EquipmentEditor({
  filter,
  sortBy,
}: {
  readonly filter: string;
  readonly sortBy: SortOption;
}): React.JSX.Element {
  // Subscribe to userEquipment to trigger re-render on changes
  const userEquipment = useUserDataStore((s) => s.userEquipment);
  const getMergedEquipment = useUserDataStore((s) => s.getMergedEquipment);
  const getDeletedEquipment = useUserDataStore((s) => s.getDeletedEquipment);

  const [editingItem, setEditingItem] = useState<EquipmentPiece | null>(null);
  const [isNew, setIsNew] = useState(false);

  // Recompute merged items when userEquipment changes
  const items = useMemo(() => getMergedEquipment(), [getMergedEquipment, userEquipment]);
  const deletedItems = useMemo(() => getDeletedEquipment(), [getDeletedEquipment, userEquipment]);

  const filtered = useMemo(() => {
    let result = items;
    if (filter !== "") {
      const lower = filter.toLowerCase();
      result = result.filter(
        (m) =>
          m.item.name.toLowerCase
Repobility · code-quality intelligence platform · https://repobility.com
createNewEquipment function · typescript · L80-L90 (11 LOC)
src/ui/panels/data-management/equipment-editor.tsx
function createNewEquipment(): EquipmentPiece {
  return {
    id: `custom-${String(Date.now())}`,
    name: "",
    slot: "accessory",
    baseStats: {},
    socketCount: 0,
    maxLevel: 1,
    tags: [],
  };
}
EquipmentExtraFields function · typescript · L25-L83 (59 LOC)
src/ui/panels/data-management/equipment-extra-fields.tsx
export function EquipmentExtraFields({
  equipment,
  onChange,
}: EquipmentExtraFieldsProps): React.JSX.Element {
  const getMergedEquipment = useUserDataStore((s) => s.getMergedEquipment);

  // Extract known values from existing equipment for autocomplete
  const { knownTags, knownSources } = useMemo(() => {
    const tags = new Set<string>();
    const sources = new Set<string>();
    for (const { item } of getMergedEquipment()) {
      for (const tag of item.tags) tags.add(tag);
      if (item.source !== undefined) sources.add(item.source);
    }
    return { knownTags: [...tags].sort(), knownSources: [...sources].sort() };
  }, [getMergedEquipment]);

  return (
    <>
      <EquipmentNumericFields equipment={equipment} onChange={onChange} />

      <FormField label="Tags (comma-separated, optional)">
        <AutocompleteInput
          value={equipment.tags.join(", ")}
          placeholder="e.g., sunken, boss-drop"
          options={knownTags}
          onChange={(value) => {
EquipmentForm function · typescript · L26-L55 (30 LOC)
src/ui/panels/data-management/equipment-form.tsx
export function EquipmentForm({
  equipment,
  onChange,
  isNew,
}: EquipmentFormProps): React.JSX.Element {
  return (
    <div className="space-y-4">
      <EquipmentBasicFields
        equipment={equipment}
        onChange={onChange}
        isNew={isNew}
      />

      <EquipmentExtraFields equipment={equipment} onChange={onChange} />

      <div>
        <Label className="text-xs text-text-muted mb-2 block">Base Stats</Label>
        <StatsEditor
          stats={equipment.baseStats}
          onChange={(s) => { onChange({ ...equipment, baseStats: s }); }}
        />
      </div>

      <VariantsEditor
        variants={equipment.variants}
        onChange={(v) => { onChange({ ...equipment, variants: v }); }}
      />
    </div>
  );
}
‹ prevpage 6 / 9next ›