mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-17 04:32:31 +03:00
refactor(usage): extract useQuotaVisibility hook (file-size budget)
ProviderLimits/index.tsx grew past its frozen 1127-line budget with the quota-visibility wiring; extract the state + persistence + hide/show handlers into a dedicated hook (same pattern as useCodexResetCreditRedemption). No behavior change — the live validation evidence on the PR covers this flow end-to-end. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
This commit is contained in:
committed by
Diego Rodrigues de Sa e Souza
parent
5cc604c05a
commit
39b4fc38a4
@@ -12,7 +12,6 @@ import {
|
||||
calculatePercentage,
|
||||
matchesProviderFilter,
|
||||
buildProviderOptions,
|
||||
getQuotaVisibilityKey,
|
||||
} from "./utils";
|
||||
import Card from "@/shared/components/Card";
|
||||
import { CardSkeleton } from "@/shared/components/Loading";
|
||||
@@ -20,6 +19,8 @@ import { USAGE_SUPPORTED_PROVIDERS } from "@/shared/constants/providers";
|
||||
import { pickDisplayValue } from "@/shared/utils/maskEmail";
|
||||
import useEmailPrivacyStore from "@/store/emailPrivacyStore";
|
||||
import { useNotificationStore } from "@/store/notificationStore";
|
||||
|
||||
import { useQuotaVisibility } from "./useQuotaVisibility";
|
||||
import QuotaCutoffModal from "./QuotaCutoffModal";
|
||||
import QuotaCardGrid from "./QuotaCardGrid";
|
||||
import { useVisibleQuotaData } from "./useVisibleQuotaData";
|
||||
@@ -200,12 +201,7 @@ export default function ProviderLimits({
|
||||
const [refreshingAll, setRefreshingAll] = useState(false);
|
||||
const [initialLoading, setInitialLoading] = useState(true);
|
||||
const [tierFilter, setTierFilter] = useState("all");
|
||||
// Per-operator quota row visibility (upstream 9router#2371 port). Keyed by
|
||||
// provider id → { hidden: [<quota visibility key>] }, persisted server-side
|
||||
// via PATCH /api/settings so it survives refresh/reload.
|
||||
const [quotaVisibility, setQuotaVisibility] = useState<Record<string, { hidden?: string[] }>>(
|
||||
{}
|
||||
);
|
||||
const { quotaVisibility, handleHideQuota, handleShowQuota } = useQuotaVisibility(tr, notify);
|
||||
const resetCreditRedemption = useCodexResetCreditRedemption(
|
||||
tr,
|
||||
setErrors,
|
||||
@@ -328,76 +324,6 @@ export default function ProviderLimits({
|
||||
[notify, tr]
|
||||
);
|
||||
|
||||
// Load persisted per-operator quota row visibility once on mount. Best
|
||||
// effort — a fetch failure just leaves every row visible (safe default).
|
||||
useEffect(() => {
|
||||
let alive = true;
|
||||
fetch("/api/settings", { cache: "no-store" })
|
||||
.then((r) => (r.ok ? r.json() : {}))
|
||||
.then((s) => {
|
||||
if (alive) setQuotaVisibility(s?.quotaVisibility || {});
|
||||
})
|
||||
.catch(() => {});
|
||||
return () => {
|
||||
alive = false;
|
||||
};
|
||||
}, []);
|
||||
|
||||
const persistQuotaVisibility = useCallback(
|
||||
async (
|
||||
next: Record<string, { hidden?: string[] }>,
|
||||
previous: Record<string, { hidden?: string[] }>
|
||||
) => {
|
||||
setQuotaVisibility(next);
|
||||
try {
|
||||
const response = await fetch("/api/settings", {
|
||||
method: "PATCH",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ quotaVisibility: next }),
|
||||
});
|
||||
if (!response.ok) throw new Error("Failed to update quota visibility");
|
||||
} catch {
|
||||
setQuotaVisibility(previous);
|
||||
notify.error(tr("quotaVisibilityUpdateFailed", "Failed to update quota visibility"));
|
||||
}
|
||||
},
|
||||
[notify, tr]
|
||||
);
|
||||
|
||||
const handleHideQuota = useCallback(
|
||||
(provider: string, quotaRow: any) => {
|
||||
const key = getQuotaVisibilityKey(quotaRow);
|
||||
if (!provider || !key) return;
|
||||
const previous = quotaVisibility;
|
||||
const providerVisibility = previous[provider] || {};
|
||||
const hidden = new Set(providerVisibility.hidden || []);
|
||||
hidden.add(key);
|
||||
const next = {
|
||||
...previous,
|
||||
[provider]: { ...providerVisibility, hidden: [...hidden] },
|
||||
};
|
||||
persistQuotaVisibility(next, previous);
|
||||
},
|
||||
[quotaVisibility, persistQuotaVisibility]
|
||||
);
|
||||
|
||||
const handleShowQuota = useCallback(
|
||||
(provider: string, quotaRow: any) => {
|
||||
const key = getQuotaVisibilityKey(quotaRow);
|
||||
if (!provider || !key) return;
|
||||
const previous = quotaVisibility;
|
||||
const providerVisibility = previous[provider] || {};
|
||||
const hidden = new Set(providerVisibility.hidden || []);
|
||||
hidden.delete(key);
|
||||
const next = {
|
||||
...previous,
|
||||
[provider]: { ...providerVisibility, hidden: [...hidden] },
|
||||
};
|
||||
persistQuotaVisibility(next, previous);
|
||||
},
|
||||
[quotaVisibility, persistQuotaVisibility]
|
||||
);
|
||||
|
||||
const applyCachedQuotaState = useCallback(
|
||||
(connectionList: any[], caches: Record<string, any>) => {
|
||||
const nextQuotaData: Record<string, any> = {};
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
"use client";
|
||||
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
|
||||
import { getQuotaVisibilityKey } from "./utils";
|
||||
|
||||
type QuotaVisibilityMap = Record<string, { hidden?: string[] }>;
|
||||
|
||||
type Translate = (key: string, fallback: string) => string;
|
||||
|
||||
interface NotifyLike {
|
||||
error: (message: string) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Per-operator quota row visibility (upstream 9router#2371 port). Keyed by
|
||||
* provider id → { hidden: [<quota visibility key>] }, persisted server-side
|
||||
* via PATCH /api/settings so it survives refresh/reload.
|
||||
*
|
||||
* Extracted from ProviderLimits/index.tsx to keep the container under the
|
||||
* frozen file-size budget — same pattern as useCodexResetCreditRedemption.
|
||||
*/
|
||||
export function useQuotaVisibility(tr: Translate, notify: NotifyLike) {
|
||||
const [quotaVisibility, setQuotaVisibility] = useState<QuotaVisibilityMap>({});
|
||||
|
||||
// Load persisted per-operator quota row visibility once on mount. Best
|
||||
// effort — a fetch failure just leaves every row visible (safe default).
|
||||
useEffect(() => {
|
||||
let alive = true;
|
||||
fetch("/api/settings", { cache: "no-store" })
|
||||
.then((r) => (r.ok ? r.json() : {}))
|
||||
.then((s) => {
|
||||
if (alive) setQuotaVisibility(s?.quotaVisibility || {});
|
||||
})
|
||||
.catch(() => {});
|
||||
return () => {
|
||||
alive = false;
|
||||
};
|
||||
}, []);
|
||||
|
||||
const persistQuotaVisibility = useCallback(
|
||||
async (next: QuotaVisibilityMap, previous: QuotaVisibilityMap) => {
|
||||
setQuotaVisibility(next);
|
||||
try {
|
||||
const response = await fetch("/api/settings", {
|
||||
method: "PATCH",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ quotaVisibility: next }),
|
||||
});
|
||||
if (!response.ok) throw new Error("Failed to update quota visibility");
|
||||
} catch {
|
||||
setQuotaVisibility(previous);
|
||||
notify.error(tr("quotaVisibilityUpdateFailed", "Failed to update quota visibility"));
|
||||
}
|
||||
},
|
||||
[notify, tr]
|
||||
);
|
||||
|
||||
const toggleQuotaKey = useCallback(
|
||||
(provider: string, quotaRow: any, hide: boolean) => {
|
||||
const key = getQuotaVisibilityKey(quotaRow);
|
||||
if (!provider || !key) return;
|
||||
const previous = quotaVisibility;
|
||||
const providerVisibility = previous[provider] || {};
|
||||
const hidden = new Set(providerVisibility.hidden || []);
|
||||
if (hide) hidden.add(key);
|
||||
else hidden.delete(key);
|
||||
const next = {
|
||||
...previous,
|
||||
[provider]: { ...providerVisibility, hidden: [...hidden] },
|
||||
};
|
||||
persistQuotaVisibility(next, previous);
|
||||
},
|
||||
[quotaVisibility, persistQuotaVisibility]
|
||||
);
|
||||
|
||||
const handleHideQuota = useCallback(
|
||||
(provider: string, quotaRow: any) => toggleQuotaKey(provider, quotaRow, true),
|
||||
[toggleQuotaKey]
|
||||
);
|
||||
|
||||
const handleShowQuota = useCallback(
|
||||
(provider: string, quotaRow: any) => toggleQuotaKey(provider, quotaRow, false),
|
||||
[toggleQuotaKey]
|
||||
);
|
||||
|
||||
return { quotaVisibility, handleHideQuota, handleShowQuota };
|
||||
}
|
||||
Reference in New Issue
Block a user