fix: fix runtime error when clearing backlinks filter (#105)
This commit is contained in:
parent
4137b386ab
commit
53505c0a5b
@ -324,6 +324,7 @@ export function BacklinksFilterPanel({
|
|||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
|
type="button"
|
||||||
className="btn btn-xs btn-ghost gap-1"
|
className="btn btn-xs btn-ghost gap-1"
|
||||||
onClick={current.reset}
|
onClick={current.reset}
|
||||||
disabled={current.activeFilterCount === 0}
|
disabled={current.activeFilterCount === 0}
|
||||||
|
|||||||
@ -7,9 +7,9 @@ export type BacklinksTabFilterValues = {
|
|||||||
maxLinkAuthority: string;
|
maxLinkAuthority: string;
|
||||||
minSpamScore: string;
|
minSpamScore: string;
|
||||||
maxSpamScore: string;
|
maxSpamScore: string;
|
||||||
linkType: "" | "dofollow" | "nofollow";
|
linkType: string;
|
||||||
hideLost: "" | "true";
|
hideLost: string;
|
||||||
hideBroken: "" | "true";
|
hideBroken: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ReferringDomainsFilterValues = {
|
export type ReferringDomainsFilterValues = {
|
||||||
|
|||||||
@ -12,72 +12,79 @@ import { countActiveFilters } from "./backlinksFiltering";
|
|||||||
|
|
||||||
const STORAGE_KEY_PREFIX = "backlinks-filters:";
|
const STORAGE_KEY_PREFIX = "backlinks-filters:";
|
||||||
|
|
||||||
|
type FilterValues = Record<string, string>;
|
||||||
|
|
||||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||||
return typeof value === "object" && value !== null;
|
return typeof value === "object" && value !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadFromStorage<T extends Record<string, string>>(
|
function loadFromStorage<T extends FilterValues>(tab: string, fallback: T): T {
|
||||||
tab: string,
|
const fallbackClone = { ...fallback };
|
||||||
fallback: T,
|
|
||||||
): T {
|
|
||||||
try {
|
try {
|
||||||
const raw = localStorage.getItem(`${STORAGE_KEY_PREFIX}${tab}`);
|
const raw = localStorage.getItem(`${STORAGE_KEY_PREFIX}${tab}`);
|
||||||
if (!raw) return fallback;
|
if (!raw) return fallbackClone;
|
||||||
|
|
||||||
const parsed: unknown = JSON.parse(raw);
|
const parsed: unknown = JSON.parse(raw);
|
||||||
if (!isRecord(parsed)) return fallback;
|
if (!isRecord(parsed)) return fallbackClone;
|
||||||
const result = { ...fallback };
|
|
||||||
for (const key of Object.keys(fallback)) {
|
const result = { ...fallbackClone };
|
||||||
const val = parsed[key];
|
for (const key in fallback) {
|
||||||
if (typeof val === "string") {
|
const value = parsed[key];
|
||||||
(result as Record<string, string>)[key] = val;
|
if (typeof value === "string") {
|
||||||
|
Object.assign(result, { [key]: value });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
} catch {
|
} catch {
|
||||||
return fallback;
|
return fallbackClone;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveToStorage(tab: string, values: Record<string, string>) {
|
function saveToStorage(tab: string, values: FilterValues) {
|
||||||
try {
|
try {
|
||||||
localStorage.setItem(`${STORAGE_KEY_PREFIX}${tab}`, JSON.stringify(values));
|
localStorage.setItem(`${STORAGE_KEY_PREFIX}${tab}`, JSON.stringify(values));
|
||||||
} catch {
|
} catch {
|
||||||
// storage full — silently ignore
|
// storage full - silently ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function useTabFilterForm<T extends Record<string, string>>(
|
function useTabFilters<T extends FilterValues>(tab: string, emptyValues: T) {
|
||||||
tab: string,
|
const [defaultValues] = useState<T>(() =>
|
||||||
emptyValues: T,
|
loadFromStorage(tab, { ...emptyValues }),
|
||||||
) {
|
);
|
||||||
const form = useForm({ defaultValues: loadFromStorage(tab, emptyValues) });
|
const form = useForm({ defaultValues });
|
||||||
const values = useStore(form.store, (s) => s.values);
|
const values = useStore(form.store, (state) => state.values);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
saveToStorage(tab, values);
|
saveToStorage(tab, values);
|
||||||
}, [tab, values]);
|
}, [tab, values]);
|
||||||
|
|
||||||
const reset = useCallback(() => {
|
const reset = useCallback(() => {
|
||||||
form.reset(emptyValues);
|
form.reset({ ...emptyValues }, { keepDefaultValues: true });
|
||||||
}, [form, emptyValues]);
|
}, [emptyValues, form]);
|
||||||
|
|
||||||
const activeFilterCount = countActiveFilters(values);
|
return {
|
||||||
|
form,
|
||||||
return { form, values, reset, activeFilterCount };
|
values,
|
||||||
|
reset,
|
||||||
|
activeFilterCount: countActiveFilters(values),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useBacklinksFilters() {
|
export function useBacklinksFilters() {
|
||||||
const [showFilters, setShowFilters] = useState(false);
|
const [showFilters, setShowFilters] = useState(false);
|
||||||
|
|
||||||
const backlinks = useTabFilterForm<BacklinksTabFilterValues>(
|
const backlinks = useTabFilters<BacklinksTabFilterValues>(
|
||||||
"backlinks",
|
"backlinks",
|
||||||
EMPTY_BACKLINKS_FILTERS,
|
EMPTY_BACKLINKS_FILTERS,
|
||||||
);
|
);
|
||||||
const domains = useTabFilterForm<ReferringDomainsFilterValues>(
|
const domains = useTabFilters<ReferringDomainsFilterValues>(
|
||||||
"domains",
|
"domains",
|
||||||
EMPTY_REFERRING_DOMAINS_FILTERS,
|
EMPTY_REFERRING_DOMAINS_FILTERS,
|
||||||
);
|
);
|
||||||
const pages = useTabFilterForm<TopPagesFilterValues>(
|
const pages = useTabFilters<TopPagesFilterValues>(
|
||||||
"pages",
|
"pages",
|
||||||
EMPTY_TOP_PAGES_FILTERS,
|
EMPTY_TOP_PAGES_FILTERS,
|
||||||
);
|
);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user