mike/frontend/src/app/hooks/useSelectedModel.ts
QA Runner 0740f656e6 fix: burn down frontend eslint errors; make CI lint blocking
Takes frontend/npm run lint from 23 errors / 40 warnings to 0 errors /
40 warnings, then removes continue-on-error from the CI lint step so it
gates merges.

Errors fixed outright:
- @typescript-eslint/no-explicit-any (5, ChatView.tsx): dropped
  redundant (msg as any) casts — Message already declares files,
  workflow, and error with the exact shapes the props expect.
- react/no-unescaped-entities (1, support/page.tsx): "We'll" ->
  "We'll".

Targeted disables (17, all react-hooks/set-state-in-effect): every site
is an intentional effect-driven state pattern — SSR/hydration mount
gates (Modal, useSelectedModel), reset-on-prop/identity-change
(CaseLawPanel x3, ChatView chat switch, CitationQuotesHeader,
ChatHistoryContext logout, useFetchDocxBytes), sync fast paths of async
fetch/check effects (CaseLawPanel, MfaLoginGate x2), DOM-measured state
(ChatView scroll button, message-visibility restore), and timed UI
latches (PreResponseWrapper, TRChatPanel, AskInputPopup auto-submit).
Rewriting any of them would change runtime behavior, so each carries a
// eslint-disable-next-line with a one-line reason instead of a fix or
a repo-wide rule change.

CI: lint step is now blocking; comments updated to say the backlog is
at zero.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 11:17:24 -07:00

32 lines
1.1 KiB
TypeScript

"use client";
import { useCallback, useEffect, useState } from "react";
import { ALLOWED_MODEL_IDS, DEFAULT_MODEL_ID } from "../components/assistant/ModelToggle";
const STORAGE_KEY = "mike.selectedModel";
function readStored(): string {
if (typeof window === "undefined") return DEFAULT_MODEL_ID;
const raw = window.localStorage.getItem(STORAGE_KEY);
if (raw && ALLOWED_MODEL_IDS.has(raw)) return raw;
return DEFAULT_MODEL_ID;
}
export function useSelectedModel(): [string, (id: string) => void] {
const [model, setModelState] = useState<string>(DEFAULT_MODEL_ID);
useEffect(() => {
// eslint-disable-next-line react-hooks/set-state-in-effect -- hydration-safe localStorage read; SSR must render the default model
setModelState(readStored());
}, []);
const setModel = useCallback((id: string) => {
const next = ALLOWED_MODEL_IDS.has(id) ? id : DEFAULT_MODEL_ID;
setModelState(next);
if (typeof window !== "undefined") {
window.localStorage.setItem(STORAGE_KEY, next);
}
}, []);
return [model, setModel];
}