All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m29s
New /methodology page with 3 tabs for viewing and editing decision
writing methodology. Uses DB override pattern: hardcoded Python
constants serve as defaults, edits saved to appeal_type_rules table,
delete restores default.
Backend: 3 generic endpoints (GET/PUT/DELETE /api/methodology/{category}/{key})
with validation per category type.
Frontend: methodology.ts hooks, GoldenRatiosPanel (number inputs per
outcome/section), DiscussionRulesPanel (accordion with textarea per
rule), ContentChecklistsPanel (markdown editor with preview toggle).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
72 lines
2.4 KiB
TypeScript
72 lines
2.4 KiB
TypeScript
/**
|
|
* Methodology settings hooks — view and edit golden ratios,
|
|
* discussion rules, and content checklists.
|
|
*/
|
|
|
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
import { apiRequest } from "./client";
|
|
|
|
// ── Types ────────────────────────────────────────────────────────
|
|
|
|
export type MethodologyItem<T = unknown> = {
|
|
value: T;
|
|
is_override: boolean;
|
|
updated_at: string | null;
|
|
};
|
|
|
|
export type MethodologyResponse<T = unknown> = {
|
|
items: Record<string, MethodologyItem<T>>;
|
|
};
|
|
|
|
/** Golden ratio per section: [min%, max%] */
|
|
export type GoldenRatios = Record<string, [number, number]>;
|
|
|
|
// ── Query Keys ───────────────────────────────────────────────────
|
|
|
|
export const methodologyKeys = {
|
|
all: ["methodology"] as const,
|
|
category: (cat: string) => [...methodologyKeys.all, cat] as const,
|
|
};
|
|
|
|
// ── Hooks ────────────────────────────────────────────────────────
|
|
|
|
export function useMethodology<T = unknown>(category: string) {
|
|
return useQuery({
|
|
queryKey: methodologyKeys.category(category),
|
|
queryFn: ({ signal }) =>
|
|
apiRequest<MethodologyResponse<T>>(
|
|
`/api/methodology/${category}`,
|
|
{ signal },
|
|
),
|
|
staleTime: 30_000,
|
|
});
|
|
}
|
|
|
|
export function useUpdateMethodology(category: string) {
|
|
const qc = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: ({ key, value }: { key: string; value: unknown }) =>
|
|
apiRequest<{ key: string; value: unknown; is_override: boolean }>(
|
|
`/api/methodology/${category}/${key}`,
|
|
{ method: "PUT", body: { value } },
|
|
),
|
|
onSuccess: () => {
|
|
qc.invalidateQueries({ queryKey: methodologyKeys.category(category) });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useResetMethodology(category: string) {
|
|
const qc = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: (key: string) =>
|
|
apiRequest<{ key: string; value: unknown; is_override: boolean }>(
|
|
`/api/methodology/${category}/${key}`,
|
|
{ method: "DELETE" },
|
|
),
|
|
onSuccess: () => {
|
|
qc.invalidateQueries({ queryKey: methodologyKeys.category(category) });
|
|
},
|
|
});
|
|
}
|