88 lines
3.0 KiB
TypeScript
88 lines
3.0 KiB
TypeScript
/** Shared UI helpers for inventory pages (parity with CI views). */
|
||
|
||
export function gradeLabel(cat: Record<string, unknown> | null | undefined): string {
|
||
if (!cat) return '—'
|
||
const gmin = cat.grade_min
|
||
const gmax = cat.grade_max
|
||
if (gmin == null && gmax == null) return '—'
|
||
const nmin = typeof gmin === 'number' ? gmin : gmin !== '' ? Number(gmin) : null
|
||
const nmax = typeof gmax === 'number' ? gmax : gmax !== '' ? Number(gmax) : null
|
||
if (nmin != null && Number.isFinite(nmin) && nmax != null && Number.isFinite(nmax))
|
||
return `G${Math.floor(nmin)}–G${Math.floor(nmax)}`
|
||
if (nmin != null && Number.isFinite(nmin)) return `G${Math.floor(nmin)}+`
|
||
if (nmax != null && Number.isFinite(nmax)) return `≤G${Math.floor(nmax)}`
|
||
return '—'
|
||
}
|
||
|
||
export function catLabelBook(c: Record<string, unknown>): string {
|
||
let name = String(c.name ?? '')
|
||
const gl = gradeLabel(c)
|
||
if (gl !== '—') name += ` (${gl})`
|
||
return name
|
||
}
|
||
|
||
export function conditionBadgeClass(condition: unknown): string {
|
||
const map: Record<string, string> = {
|
||
good: 'success',
|
||
needs_repair: 'warning',
|
||
need_replace: 'danger',
|
||
cannot_find: 'secondary',
|
||
}
|
||
const k = typeof condition === 'string' ? condition : ''
|
||
return map[k] ?? 'light'
|
||
}
|
||
|
||
export function formatConditionLabel(condition: unknown): string {
|
||
if (condition == null || condition === '') return ''
|
||
return String(condition)
|
||
.split('_')
|
||
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
||
.join(' ')
|
||
}
|
||
|
||
export function parseInventoryList(data: unknown): {
|
||
items: Record<string, unknown>[]
|
||
categories: Record<string, unknown>[]
|
||
userNames: Record<string, string>
|
||
} {
|
||
if (!data || typeof data !== 'object')
|
||
return { items: [], categories: [], userNames: {} }
|
||
const o = data as Record<string, unknown>
|
||
const items = Array.isArray(o.items) ? (o.items as Record<string, unknown>[]) : []
|
||
const categories = Array.isArray(o.categories) ? (o.categories as Record<string, unknown>[]) : []
|
||
const userNames =
|
||
o.userNames && typeof o.userNames === 'object'
|
||
? (o.userNames as Record<string, string>)
|
||
: {}
|
||
return { items, categories, userNames }
|
||
}
|
||
|
||
export function userDisplay(
|
||
userNames: Record<string, string>,
|
||
updatedBy: unknown,
|
||
): string {
|
||
const id = typeof updatedBy === 'number' ? updatedBy : Number(updatedBy ?? 0)
|
||
if (!id) return '—'
|
||
return userNames[String(id)] ?? userNames[id] ?? '—'
|
||
}
|
||
|
||
export function parseClassesSelection(item: Record<string, unknown>): number[] {
|
||
const raw = item.classes ?? item.class_list ?? item.class_ids
|
||
if (Array.isArray(raw)) {
|
||
return raw.map((x) => Number(x)).filter((n) => n >= 1 && n <= 13)
|
||
}
|
||
if (typeof raw === 'string' && raw !== '') {
|
||
try {
|
||
const decoded = JSON.parse(raw) as unknown
|
||
if (Array.isArray(decoded)) {
|
||
return decoded.map((x) => Number(x)).filter((n) => n >= 1 && n <= 13)
|
||
}
|
||
} catch {
|
||
/* fall through */
|
||
}
|
||
const parts = raw.split(/[,\s]+/)
|
||
return parts.map((p) => Number(p)).filter((n) => n >= 1 && n <= 13 && Number.isFinite(n))
|
||
}
|
||
return []
|
||
}
|