- {/* Header */}
-
-
-
- Repair Imported Assets
-
-
- Re-download missing{" "}
- .nitro bundles and
- icons for items already imported. Items with no public asset on
- habbo.com can be deleted from here.
-
-
-
-
-
-
-
- {/* Initial empty state */}
- {!summary && !auditing && (
-
-
-
- Click “Scan Assets” to audit imported furniture.
-
-
- This checks every row in items_base against files on
- disk. Scanning ~33k items takes a few seconds.
-
-
- )}
-
- {/* Stats */}
- {summary && (
-
-
-
-
-
-
-
- )}
-
- {/* Batch repair summary */}
- {lastSummary && (
-
- Last run: {lastSummary.succeeded} fixed
- {lastSummary.partial > 0 && (
- <>
- , {lastSummary.partial} partial
- >
- )}
- {lastSummary.failed > 0 && (
- <>
- , {lastSummary.failed} failed
- >
- )}
- {lastSummary.unrepairable > 0 && (
- <>
- , {lastSummary.unrepairable}{" "}
- unrepairable
- >
- )}
- · {(lastSummary.duration / 1000).toFixed(1)}s
-
- )}
-
- {/* Table area */}
- {summary && summary.items.length === 0 && (
-
-
-
- All imported items have their assets on disk.
-
-
- {summary.total} items scanned, nothing to repair.
-
-
- )}
-
- {summary && summary.items.length > 0 && (
- <>
- {/* Toolbar */}
-
-
-
- setSearch(e.target.value)}
- placeholder="Filter by classname, name, or id…"
- className="pl-8"
- />
-
-
-
-
-
-
- {summary && summary.unrepairable > 0 && (
-
- )}
-
-
- {/* Tabs */}
-
setTab(v as keyof typeof TAB_FILTERS)}
- >
-
-
- All ({summary.items.length})
-
-
- Both ({summary.missingBoth})
-
-
- .nitro ({summary.missingNitro})
-
-
- Icon ({summary.missingIcon})
-
-
- Unrepairable ({summary.unrepairable})
-
-
-
-
-
-
-
-
-
-
- ID
- Classname
- Rev
- .nitro
- Icon
- SWF
- Status
- Actions
-
-
-
- {filtered.length === 0 && (
-
-
- No items match the current filter.
-
-
- )}
- {filtered.map((it) => (
- toggleOne(it.classname)}
- progress={progress.get(it.classname)}
- onRepair={() => runRepair([it.classname])}
- disabled={repairing}
- />
- ))}
-
-
-
-
-
- >
- )}
-
-
-
- );
-}
-
-// ── Small cell helpers ────────────────────────────────────────────────
-
-function StatCard({
- label,
- value,
- tone,
- sub,
-}: {
- label: string;
- value: number;
- tone: "default" | "danger" | "warn" | "info";
- sub?: string;
-}) {
- const tones = {
- default: "border-border",
- danger: "border-destructive/40 bg-destructive/5",
- warn: "border-[var(--admin-warning-border)] bg-[var(--admin-warning-subtle)]",
- info: "border-[var(--admin-info)]/40 bg-[var(--admin-info)]/5",
- };
- return (
-