Fixing image url

This commit is contained in:
Corey Blais
2026-03-26 17:19:01 -04:00
parent e078e3312b
commit 900bf4eb06
+54 -2
View File
@@ -189,6 +189,33 @@ const getCategorySilhouette = (category: string) => {
return silhouettes[normalized] ?? silhouettes.other; return silhouettes[normalized] ?? silhouettes.other;
}; };
const resolveFirearmImageUrl = (imageUrl: string | null | undefined) => {
const trimmed = imageUrl?.trim();
if (!trimmed) {
return null;
}
const normalized = trimmed.startsWith('//') ? `https:${trimmed}` : trimmed;
try {
const parsed = new URL(normalized);
if (!['http:', 'https:'].includes(parsed.protocol)) {
return null;
}
if (parsed.hostname === 'commons.wikimedia.org' && parsed.pathname.startsWith('/wiki/File:')) {
const fileName = parsed.pathname.replace('/wiki/File:', '');
return `https://commons.wikimedia.org/wiki/Special:FilePath/${fileName}`;
}
return parsed.toString();
} catch {
return null;
}
};
export default function Home() { export default function Home() {
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false); const [saving, setSaving] = useState(false);
@@ -206,6 +233,7 @@ export default function Home() {
const [newFirearm, setNewFirearm] = useState<FirearmForm>(emptyFirearmForm); const [newFirearm, setNewFirearm] = useState<FirearmForm>(emptyFirearmForm);
const [showNewFirearmForm, setShowNewFirearmForm] = useState(false); const [showNewFirearmForm, setShowNewFirearmForm] = useState(false);
const [selectedFirearmCategory, setSelectedFirearmCategory] = useState(allFirearmCategoriesLabel); const [selectedFirearmCategory, setSelectedFirearmCategory] = useState(allFirearmCategoriesLabel);
const [failedFirearmImages, setFailedFirearmImages] = useState<Record<string, boolean>>({});
const [ammoAdjustments, setAmmoAdjustments] = useState<AmmoAdjustments>({}); const [ammoAdjustments, setAmmoAdjustments] = useState<AmmoAdjustments>({});
const [ammoPageCaliberIds, setAmmoPageCaliberIds] = useState<string[]>(() => loadStoredAmmoPageSelection()); const [ammoPageCaliberIds, setAmmoPageCaliberIds] = useState<string[]>(() => loadStoredAmmoPageSelection());
const [selectedAmmoCaliberId, setSelectedAmmoCaliberId] = useState(''); const [selectedAmmoCaliberId, setSelectedAmmoCaliberId] = useState('');
@@ -331,6 +359,7 @@ export default function Home() {
setFirearmDrafts( setFirearmDrafts(
Object.fromEntries(payload.firearms.map((firearm) => [firearm.id, buildFirearmForm(firearm)])), Object.fromEntries(payload.firearms.map((firearm) => [firearm.id, buildFirearmForm(firearm)])),
); );
setFailedFirearmImages({});
setAmmoAdjustments(buildAmmoAdjustments(payload.ammoInventory)); setAmmoAdjustments(buildAmmoAdjustments(payload.ammoInventory));
}; };
@@ -616,6 +645,18 @@ export default function Home() {
}; };
const handleFirearmChange = (id: string, field: keyof FirearmForm, value: string) => { const handleFirearmChange = (id: string, field: keyof FirearmForm, value: string) => {
if (field === 'imageUrl') {
setFailedFirearmImages((current) => {
if (!current[id]) {
return current;
}
const next = { ...current };
delete next[id];
return next;
});
}
setFirearmDrafts((current) => ({ setFirearmDrafts((current) => ({
...current, ...current,
[id]: { [id]: {
@@ -1043,14 +1084,25 @@ export default function Home() {
) : ( ) : (
filteredFirearms.map((firearm) => { filteredFirearms.map((firearm) => {
const draft = firearmDrafts[firearm.id] ?? buildFirearmForm(firearm); const draft = firearmDrafts[firearm.id] ?? buildFirearmForm(firearm);
const resolvedImageUrl = resolveFirearmImageUrl(draft.imageUrl);
const firearmImageSrc = !failedFirearmImages[firearm.id] && resolvedImageUrl
? resolvedImageUrl
: getCategorySilhouette(draft.category);
return ( return (
<article className="firearm-card" key={firearm.id}> <article className="firearm-card" key={firearm.id}>
<div className="firearm-visual"> <div className="firearm-visual">
<img <img
className={draft.imageUrl ? 'firearm-photo' : 'firearm-silhouette'} className={!failedFirearmImages[firearm.id] && resolvedImageUrl ? 'firearm-photo' : 'firearm-silhouette'}
alt={`${firearm.manufacturer} ${firearm.model}`} alt={`${firearm.manufacturer} ${firearm.model}`}
src={draft.imageUrl || getCategorySilhouette(draft.category)} loading="lazy"
referrerPolicy="no-referrer"
onError={() =>
setFailedFirearmImages((current) =>
current[firearm.id] ? current : { ...current, [firearm.id]: true },
)
}
src={firearmImageSrc}
/> />
</div> </div>
<div className="form-grid"> <div className="form-grid">