feat(item-card): add 'market'/'catalog' mode prop with defensive price checks
Introduces optional `mode` prop ("market"/"catalog") to conditionally render components like rarity badges. Adds defensive checks for missing price data and priceHistory properties to prevent runtime errors. New icons `Badge` and `Boxes` imported from lucide-react.
This commit is contained in:
1 parent
29ba5aece0
commit
44d7f8ce81
21 files changed
+1181
-714
No files matched your search
@@ -0,0 +1,63 @@
|
||||
import path from "node:path";
|
||||
|
||||
// Mapeamento de diretórios PT (filesystem) -> categoria EN (TibiaItem.category)
|
||||
// Ajuste/cubra mais categorias conforme necessário ao longo do uso real
|
||||
export const ptToEnCategoryMap: Record<string, string> = {
|
||||
espadas: "weapon",
|
||||
armaduras: "armor",
|
||||
capacetes: "helmet",
|
||||
calcas: "legs",
|
||||
botas: "boots",
|
||||
escudos: "shield",
|
||||
amuletos: "amulet",
|
||||
aneis: "ring",
|
||||
runas: "rune",
|
||||
ferramentas: "tool",
|
||||
municao: "ammunition",
|
||||
// Outras pastas mapeiam para "other"
|
||||
};
|
||||
|
||||
// Mapeamento inverso EN -> PT para resolver caminho das imagens
|
||||
export const enToPtCategoryMap: Record<string, string> = Object.entries(
|
||||
ptToEnCategoryMap
|
||||
).reduce((acc, [pt, en]) => {
|
||||
acc[en] = pt;
|
||||
return acc;
|
||||
}, {} as Record<string, string>);
|
||||
|
||||
function normalizeFilenameSegment(value: string): string {
|
||||
// Normaliza para casar melhor com nomes de arquivo: remove acentos e espaços extras
|
||||
return value
|
||||
.normalize("NFD")
|
||||
.replace(/[\u0300-\u036f]/g, "")
|
||||
.replace(/\s+/g, "_")
|
||||
.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constrói um caminho relativo para a imagem do item dentro de data/images.
|
||||
* Retorna um caminho relativo utilizável em fs ou para um handler que sirva arquivos estáticos.
|
||||
*/
|
||||
export function buildItemImagePath(categoryEn: string, fileName: string): string {
|
||||
const ptFolder = enToPtCategoryMap[categoryEn] ?? "outros";
|
||||
// Mantém o nome original caso já esteja correto; fallback para nome normalizado
|
||||
const safeFileName = fileName || "";
|
||||
const normalized = normalizeFilenameSegment(
|
||||
safeFileName.replace(/\.(gif|png|jpg|jpeg|webp)$/i, "")
|
||||
);
|
||||
// Tenta .gif como padrão (ajuste se necessário)
|
||||
const finalFile = safeFileName || `${normalized}.gif`;
|
||||
return path.posix.join("data", "images", ptFolder, finalFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a URL pública para a imagem, caso exista um handler ou static serving configurado.
|
||||
* Por padrão, apontamos para um API proxy que servirá o arquivo do filesystem.
|
||||
*/
|
||||
export function buildPublicItemImageUrl(categoryEn: string, fileName: string): string {
|
||||
const relativePath = buildItemImagePath(categoryEn, fileName);
|
||||
// Ex.: /api/images?path=data/images/espadas/sword.gif
|
||||
return `/api/images?path=${encodeURIComponent(relativePath)}`;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user