2025-06-20 05:41:10 +00:00
|
|
|
import { createColumnHelper } from '@tanstack/react-table'
|
|
|
|
|
import { useAtomValue, useSetAtom } from 'jotai'
|
|
|
|
|
import { useMemo } from 'react'
|
|
|
|
|
import { currentItemSelectionAtom, itemSelectionSetActionAtom } from '@/state/atoms'
|
|
|
|
|
import { StatsColumns } from '../columns'
|
|
|
|
|
import { ItemWithSelection } from './defs'
|
2025-05-25 05:17:41 +00:00
|
|
|
|
2025-06-20 05:41:10 +00:00
|
|
|
const ch = createColumnHelper<ItemWithSelection>()
|
2025-05-25 05:17:41 +00:00
|
|
|
|
|
|
|
|
const columns = {
|
|
|
|
|
icon: ch.display({
|
|
|
|
|
id: 'icon',
|
2025-06-20 05:41:10 +00:00
|
|
|
header: function Component(_col) {
|
2025-05-25 05:17:41 +00:00
|
|
|
return <div className="flex flex-row justify-center"></div>
|
|
|
|
|
},
|
2025-06-20 05:41:10 +00:00
|
|
|
cell: function Component({ row }) {
|
|
|
|
|
const setItemSelection = useSetAtom(itemSelectionSetActionAtom)
|
|
|
|
|
const c = useAtomValue(currentItemSelectionAtom)
|
|
|
|
|
const selected = useMemo(() => {
|
|
|
|
|
return c[0].has(row.original.item.id)
|
2025-05-25 05:17:41 +00:00
|
|
|
}, [c])
|
2025-06-20 05:41:10 +00:00
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
className={`no-select flex flex-row ${row.original.status?.selected ? 'animate-pulse' : ''}`}
|
|
|
|
|
onClick={_e => {
|
|
|
|
|
setItemSelection({
|
|
|
|
|
[row.original.item.id]: selected ? undefined : row.original.item.item_count,
|
|
|
|
|
})
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<div className="flex flex-row w-6 h-6 justify-center">
|
|
|
|
|
<img
|
|
|
|
|
src={row.original.item.item_image || ''}
|
|
|
|
|
alt="icon"
|
|
|
|
|
className="select-none object-contain select-none"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
2025-05-25 05:17:41 +00:00
|
|
|
</div>
|
2025-06-20 05:41:10 +00:00
|
|
|
)
|
2025-05-25 05:17:41 +00:00
|
|
|
},
|
|
|
|
|
}),
|
|
|
|
|
count: ch.display({
|
|
|
|
|
id: 'count',
|
2025-06-20 05:41:10 +00:00
|
|
|
header: function Component(_col) {
|
2025-05-25 05:17:41 +00:00
|
|
|
return <div className="flex flex-row justify-center">#</div>
|
|
|
|
|
},
|
2025-06-20 05:41:10 +00:00
|
|
|
cell: function Component({ row }) {
|
|
|
|
|
const c = useAtomValue(currentItemSelectionAtom)
|
|
|
|
|
const setItemSelection = useSetAtom(itemSelectionSetActionAtom)
|
|
|
|
|
const currentValue = useMemo(() => {
|
|
|
|
|
const got = c[0].get(row.original.item.id)
|
|
|
|
|
if (got !== undefined) {
|
|
|
|
|
return got.toString()
|
2025-05-25 05:17:41 +00:00
|
|
|
}
|
2025-06-20 05:41:10 +00:00
|
|
|
return ''
|
2025-05-25 05:17:41 +00:00
|
|
|
}, [c])
|
|
|
|
|
const itemCount = row.original.item.item_count
|
2025-06-20 05:41:10 +00:00
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
className={`flex flex-row select-none ${row.original.status?.selected ? 'bg-gray-200' : ''}`}
|
|
|
|
|
>
|
|
|
|
|
<input
|
|
|
|
|
className="w-10 text-center "
|
|
|
|
|
value={currentValue}
|
|
|
|
|
onChange={e => {
|
|
|
|
|
if (e.target.value === '') {
|
|
|
|
|
setItemSelection({ [row.original.item.id]: undefined })
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (e.target.value === '-') {
|
|
|
|
|
setItemSelection({
|
|
|
|
|
[row.original.item.id]: itemCount,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
let parsedInt = parseInt(e.target.value)
|
|
|
|
|
if (Number.isNaN(parsedInt)) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (parsedInt > itemCount) {
|
|
|
|
|
parsedInt = itemCount
|
|
|
|
|
}
|
2025-05-25 05:17:41 +00:00
|
|
|
setItemSelection({
|
2025-06-20 05:41:10 +00:00
|
|
|
[row.original.item.id]: parsedInt,
|
2025-05-25 05:17:41 +00:00
|
|
|
})
|
2025-06-20 05:41:10 +00:00
|
|
|
}}
|
|
|
|
|
placeholder={itemCount.toString()}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
2025-05-25 05:17:41 +00:00
|
|
|
},
|
|
|
|
|
}),
|
|
|
|
|
name: ch.display({
|
|
|
|
|
id: 'name',
|
2025-06-20 05:41:10 +00:00
|
|
|
header: _col => {
|
|
|
|
|
return <div className="flex flex-row text-sm">name</div>
|
2025-05-25 05:17:41 +00:00
|
|
|
},
|
2025-06-20 05:41:10 +00:00
|
|
|
cell: function Component({ row }) {
|
|
|
|
|
return (
|
|
|
|
|
<div className="flex flex-row whitespace-pre">
|
|
|
|
|
<span>{row.original.item.item_name}</span>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
2025-05-25 05:17:41 +00:00
|
|
|
},
|
|
|
|
|
}),
|
|
|
|
|
slots: ch.display({
|
|
|
|
|
id: 'slots',
|
2025-06-20 05:41:10 +00:00
|
|
|
header: _col => {
|
|
|
|
|
return <div className="flex flex-row text-sm">slots</div>
|
2025-05-25 05:17:41 +00:00
|
|
|
},
|
2025-06-20 05:41:10 +00:00
|
|
|
cell: function Component({ row }) {
|
|
|
|
|
return (
|
|
|
|
|
<div className="flex flex-row justify-center">
|
|
|
|
|
<span>{row.original.item.item_slots}</span>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
2025-05-25 05:17:41 +00:00
|
|
|
},
|
|
|
|
|
}),
|
|
|
|
|
stats: ch.group({
|
|
|
|
|
id: 'stats',
|
2025-06-20 05:41:10 +00:00
|
|
|
header: _col => {
|
|
|
|
|
return <div className="flex flex-row text-sm">stats</div>
|
2025-05-25 05:17:41 +00:00
|
|
|
},
|
|
|
|
|
columns: [
|
2025-06-20 05:41:10 +00:00
|
|
|
...StatsColumns.map(c => {
|
2025-05-25 05:17:41 +00:00
|
|
|
return ch.display({
|
2025-06-20 05:41:10 +00:00
|
|
|
id: `stats.${c}`,
|
|
|
|
|
header: _col => {
|
|
|
|
|
return <div className="flex flex-row text-sm justify-center">{c}</div>
|
2025-05-25 05:17:41 +00:00
|
|
|
},
|
2025-06-20 05:41:10 +00:00
|
|
|
cell: function Component({ row }) {
|
2025-05-25 05:17:41 +00:00
|
|
|
const stats = row.original.item.stats
|
2025-06-20 05:41:10 +00:00
|
|
|
const stat = stats ? stats[c] : ''
|
|
|
|
|
return (
|
|
|
|
|
<div className={`flex flex-row justify-start ${stat ? 'border' : ''}`}>
|
|
|
|
|
<span>{stat}</span>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
2025-05-25 05:17:41 +00:00
|
|
|
},
|
|
|
|
|
})
|
2025-06-20 05:41:10 +00:00
|
|
|
}),
|
|
|
|
|
],
|
2025-05-25 05:17:41 +00:00
|
|
|
}),
|
2025-06-20 05:41:10 +00:00
|
|
|
} as const
|
2025-05-25 05:17:41 +00:00
|
|
|
|
2025-06-20 05:41:10 +00:00
|
|
|
export const InventoryColumns = columns
|