Files
ordr/ordr-ui/app/components/OrderItemTable.tsx
2025-11-19 12:26:37 -07:00

144 lines
5.2 KiB
TypeScript

'for client'
import { useItemStore } from "../providers/ItemsProvider"
import { useState } from "react"
import useAsyncEffect from "use-async-effect"
import styled from "styled-components"
import { Mutex } from "async-mutex"
type OrderItemTableProps = {
orderId: number
}
const OrderItemTableStyle = styled.table`
width: 100%
`
const OrderItemTableHead = styled.thead`
background-color: #34067eff
`
const OrderItemTableItem = styled.td`
align: center
`
const OrderItemTH = styled.th`
align: center
`
const OrderItemTableBody = styled.tbody`
> :nth-child(even) {
background-color: #410041ff;
}
> :hover {
background-color: #707070ff;
}
`
const OrderItemTableRow = styled.tr`
`
const orderItemMutex = new Mutex()
export const OrderItemTable = ({orderId}: OrderItemTableProps) => {
const itemStore = useItemStore((state) => state)
const [orderItems, setOrderItems] = useState(itemStore.orderItems.filter((oi) => oi.OrderId === orderId))
const [itemName, setItemName] = useState("")
const [itemQuantity, setItemQuantity] = useState(0)
const [shouldPostData, setShouldPostData] = useState(false)
useAsyncEffect(async () => {
if (orderItems.length === 0) {
const release = await orderItemMutex.acquire()
setOrderItems(await itemStore.getOrderItems(orderId))
await release()
}
if (itemStore.items.length === 0) {
const release = await orderItemMutex.acquire()
await itemStore.sync()
await release()
}
}, [])
useAsyncEffect(async () => {
if(shouldPostData) {
const items = itemStore.items.filter((i) => i.ItemName.toUpperCase().includes(itemName.toUpperCase()))
if(items.length > 0) {
const release = await orderItemMutex.acquire()
setOrderItems( [...orderItems, await itemStore.addItemToOrder(items[0].ItemId, orderId, itemQuantity)])
await release()
}
setShouldPostData(false)
}
}, [shouldPostData])
return (
<>
<OrderItemTableStyle>
<OrderItemTableHead>
<tr>
<OrderItemTH>
item
</OrderItemTH>
<OrderItemTH>
needed
</OrderItemTH>
<OrderItemTH>
made
</OrderItemTH>
<OrderItemTH>
total
</OrderItemTH>
<OrderItemTH>
unit
</OrderItemTH>
</tr>
</OrderItemTableHead>
<OrderItemTableBody>
{orderItems.map((oi) => (
<OrderItemTableRow key = {oi.ItemId}>
<OrderItemTableItem>
{oi.ItemName}
</OrderItemTableItem>
<OrderItemTableItem>
<input className="w-10" defaultValue={oi.Quantity} onChange={async (e) => {
if(!Number.isNaN(parseInt(e.currentTarget.value))) {
await itemStore.setItemQuantity(oi.OrderId, oi.ItemId, parseInt(e.currentTarget.value))
}
}} />
</OrderItemTableItem>
<OrderItemTableItem>
<input className="w-10" defaultValue={oi.Made} onChange={async (e) => {
if(!Number.isNaN(parseInt(e.currentTarget.value))) {
await itemStore.setItemMade(oi.OrderId, oi.ItemId, parseInt(e.currentTarget.value))
}
}} />
</OrderItemTableItem>
<OrderItemTableItem>
${Math.trunc(oi.TotalPrice * 100) / 100}
</OrderItemTableItem>
<OrderItemTableItem>
${Math.trunc(oi.UnitPrice * 100) / 100}
</OrderItemTableItem>
</OrderItemTableRow>
))}
</OrderItemTableBody>
</OrderItemTableStyle>
<h1 className="text-xl font-bold">Add Item To Order</h1>
<div className="inline-block">
<input className="inline-block w-40" onChange={(e) => {
setItemName(e.currentTarget.value)
}} placeholder="item name"/>
<input className="inline-block w-40" onChange={(e) => {
setItemQuantity(parseInt(e.currentTarget.value))
}} placeholder="needed" />
</div>
<br />
<button className="border border-white p-1 mt-3" onClick={() => {
setShouldPostData(true)
}}>Add Item</button>
</>
)
}