Skip to content

Commit

Permalink
Productsに在庫(stock)を追加 (#36)
Browse files Browse the repository at this point in the history
  • Loading branch information
BruCandy authored Nov 16, 2024
1 parent be37a68 commit 455fcfe
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 23 deletions.
29 changes: 26 additions & 3 deletions app/components/organisms/reception/ReceptionCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,42 @@ import { TypeProduct } from "~/type/typeproduct"
import PropTypes from "prop-types"

type Props = {
quantity?: number
product: TypeProduct
addOrder: (product: TypeProduct) => void
cancelOrder: (product: TypeProduct) => void
}

export const ReceptionCard: FC<Props> = memo((props) => {
const { product, addOrder, cancelOrder } = props
const { quantity = 0, product, addOrder, cancelOrder } = props

return (
<Box w="300px" h="250px" bg="white" borderRadius="10px" shadow="md" p={4}>
<Box
w="300px"
h="250px"
bg={
product.stock - quantity === 0
? "red.200"
: product.stock - quantity <= 10
? "red.100"
: "white"
}
borderRadius="10px"
shadow="md"
p={4}
>
<h1>ID:{product.product_id}</h1>
<Stack textAlign={"center"}>
<Text>{product.product_name}</Text>
<Text>価格:{product.price}</Text>
<Button onClick={() => addOrder(product)} colorScheme="blue">
<Text>在庫:{product.stock - quantity}</Text>
<Button
isDisabled={
quantity ? product.stock - quantity <= 0 : product.stock <= 0
}
onClick={() => addOrder(product)}
colorScheme="blue"
>
+
</Button>
<Button onClick={() => cancelOrder(product)} colorScheme="red">
Expand All @@ -32,10 +53,12 @@ export const ReceptionCard: FC<Props> = memo((props) => {
ReceptionCard.displayName = "ReceptionCard"

ReceptionCard.propTypes = {
quantity: PropTypes.number,
product: PropTypes.shape({
product_id: PropTypes.number.isRequired,
product_name: PropTypes.string.isRequired,
price: PropTypes.number.isRequired,
stock: PropTypes.number.isRequired,
}).isRequired,
addOrder: PropTypes.func.isRequired,
cancelOrder: PropTypes.func.isRequired,
Expand Down
4 changes: 3 additions & 1 deletion app/components/organisms/register/ProductCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ export const ProductCard: FC<Props> = memo((props) => {
const { product, clickDelete, clickChange } = props

return (
<Box w="300px" h="250px" bg="white" borderRadius="10px" shadow="md" p={4}>
<Box w="300px" h="250px" bg={"white"} borderRadius="10px" shadow="md" p={4}>
<h1>ID:{product.product_id}</h1>
<Stack textAlign={"center"}>
<Text>{product.product_name}</Text>
<Text>価格:{product.price}</Text>
<Text>在庫:{product.stock}</Text>
<Button onClick={() => clickDelete(product)} colorScheme="red">
削除
</Button>
Expand All @@ -36,6 +37,7 @@ ProductCard.propTypes = {
product_id: PropTypes.number.isRequired,
product_name: PropTypes.string.isRequired,
price: PropTypes.number.isRequired,
stock: PropTypes.number.isRequired,
}).isRequired,
clickDelete: PropTypes.func.isRequired,
clickChange: PropTypes.func.isRequired,
Expand Down
18 changes: 18 additions & 0 deletions app/crud/crud_products.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ const prisma = new PrismaClient()
export async function createProduct(data: {
product_name: string
price: number
stock: number
}) {
return await prisma.products.create({
data: {
product_name: data.product_name,
price: data.price,
stock: data.stock,
},
})
}
Expand All @@ -26,6 +28,7 @@ export async function updateProduct(
product_id: number,
product_name: string,
price: number,
stock: number,
) {
return await prisma.products.update({
where: {
Expand All @@ -34,10 +37,25 @@ export async function updateProduct(
data: {
product_name: product_name,
price: price,
stock: stock,
},
})
}

//在庫の変更
export async function updateStock(data: {
product_id: number
stock: number | undefined
num: number
}) {
return await prisma.products.update({
where: {
product_id: data.product_id,
},
data: { stock: data.stock ? data.stock - data.num : 0 },
})
}

//同じ商品名の商品が既に存在するか確認する
export async function existProduct(name: string) {
return await prisma.products.findFirst({
Expand Down
48 changes: 33 additions & 15 deletions app/routes/reception.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { useEffect, useState } from "react"
import { ReceptionCard } from "~/components/organisms/reception/ReceptionCard"
import { createOrderDetail } from "~/crud/crud_details"
import { createOrder } from "~/crud/crud_orders"
import { readProduct } from "~/crud/crud_products"
import { readProduct, updateStock } from "~/crud/crud_products"
import { useMessage } from "~/hooks/useMessage"

// type TypeOrder = {
Expand Down Expand Up @@ -73,9 +73,9 @@ export default function Reception() {

useEffect(() => {
if (actionData?.success === true) {
setOrder([])
setTotal(0)
// setDecision(false)
setOrder([])
showMessage({ title: "注文しました", status: "success" })
onClose()
setTableNumber("")
Expand All @@ -88,6 +88,7 @@ export default function Reception() {
product_id: number
product_name: string
price: number
stock: number
}) => {
setOrder((prevOrder) => {
const existingProduct = prevOrder.find(
Expand Down Expand Up @@ -171,15 +172,21 @@ export default function Reception() {
</Box>
<div>
<Wrap p={{ base: 4, md: 10 }}>
{products.map((product) => (
<WrapItem key={product.product_id} mx="auto">
<ReceptionCard
product={product}
addOrder={addOrder}
cancelOrder={cancelOrder}
/>
</WrapItem>
))}
{products.map((product) => {
const selectedOrder = order.find(
(order) => order.product_id === product.product_id,
)
return (
<WrapItem key={product.product_id} mx="auto">
<ReceptionCard
quantity={selectedOrder?.quantity}
product={product}
addOrder={addOrder}
cancelOrder={cancelOrder}
/>
</WrapItem>
)
})}
</Wrap>
</div>

Expand Down Expand Up @@ -264,13 +271,24 @@ export const action: ActionFunction = async ({
status: "accept",
})

for (let i = 0; i < product_ids.length; i++) {
const products = await readProduct()

product_ids.map(async (product_id, index) => {
const quantity = quantities[index]
const product = products.find((p) => p.product_id === product_id)

await createOrderDetail({
order_id: order.order_id,
product_id: product_ids[i],
quantity: quantities[i],
product_id: product_id,
quantity: quantity,
})
}

await updateStock({
product_id: product_id,
stock: product?.stock,
num: quantity,
})
})

return { success: true }
}
Expand Down
44 changes: 40 additions & 4 deletions app/routes/register.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
ModalCloseButton,
ModalContent,
ModalFooter,
ModalHeader,
ModalOverlay,
Stack,
useDisclosure,
Expand Down Expand Up @@ -42,6 +41,7 @@ type ActionData = {
export default function Register() {
const [name, setName] = useState("")
const [price, setPrice] = useState("")
const [stock, setStock] = useState("")
const [isLoading, setLoading] = useState(false)
const actionData = useActionData<ActionData>()
const { showMessage } = useMessage()
Expand Down Expand Up @@ -69,6 +69,7 @@ export default function Register() {
if (actionData?.success && actionData?.method === "POST") {
setName("")
setPrice("")
setStock("")
setLoading(false)
showMessage({ title: "登録完了", status: "success" })
}
Expand Down Expand Up @@ -105,6 +106,10 @@ export default function Register() {
setPrice(e.target.value)
}

const stockChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setStock(e.target.value)
}

const productOpen = () => {
setOpen(true)
}
Expand Down Expand Up @@ -145,6 +150,15 @@ export default function Register() {
}
}

const handleStockChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (changeProduct) {
setChangeProduct({
...changeProduct,
stock: Number(e.target.value),
})
}
}

return (
<div>
<Button
Expand All @@ -161,7 +175,7 @@ export default function Register() {
<Box
bg="white"
w="400px"
h="300px"
h="380px"
borderRadius="10px"
shadow="md"
fontSize="xl"
Expand Down Expand Up @@ -191,6 +205,17 @@ export default function Register() {
required
/>
</FormControl>
<FormControl>
<FormLabel>在庫</FormLabel>
<Input
type="number"
name="stock"
value={stock}
onChange={stockChange}
bg="gray.200"
required
/>
</FormControl>
<Button
type="submit"
colorScheme="blue"
Expand Down Expand Up @@ -286,7 +311,6 @@ export default function Register() {
>
<ModalOverlay />
<ModalContent pb={2}>
<ModalHeader>ユーザー詳細</ModalHeader>
<ModalCloseButton />
<ModalBody mx={4}>
<Stack spacing={4}>
Expand All @@ -306,6 +330,14 @@ export default function Register() {
onChange={handlePriceChange}
/>
</FormControl>
<FormControl>
<FormLabel>在庫</FormLabel>
<Input
type="number"
value={changeProduct?.stock}
onChange={handleStockChange}
/>
</FormControl>
</Stack>
</ModalBody>
<ModalFooter gap={4}>
Expand All @@ -322,6 +354,7 @@ export default function Register() {
name="product_name"
/>
<Input type="hidden" value={changeProduct?.price} name="price" />
<Input type="hidden" value={changeProduct?.stock} name="stock" />
<Button type="submit" colorScheme="green">
更新
</Button>
Expand Down Expand Up @@ -352,6 +385,7 @@ export const action: ActionFunction = async ({
) {
const product_name = formData.get("product_name")
const price = Number(formData.get("price"))
const stock = Number(formData.get("stock"))

if (typeof product_name === "string") {
const isExist = await existProduct(product_name)
Expand All @@ -369,6 +403,7 @@ export const action: ActionFunction = async ({
await createProduct({
product_name,
price,
stock,
})

return json({ success: true, method: request.method })
Expand Down Expand Up @@ -405,9 +440,10 @@ export const action: ActionFunction = async ({
const product_id = Number(formData.get("product_id"))
const product_name = formData.get("product_name")
const price = Number(formData.get("price"))
const stock = Number(formData.get("stock"))

if (typeof product_name === "string") {
await updateProduct(product_id, product_name, price)
await updateProduct(product_id, product_name, price, stock)
return json({ success: true, method: method })
} else {
return json({ success: false, error: "no product_name", method: method })
Expand Down
1 change: 1 addition & 0 deletions app/type/typeproduct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export type TypeProduct = {
product_id: number
product_name: string
price: number
stock: number
}
21 changes: 21 additions & 0 deletions prisma/migrations/20241108122708_add_stock/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
Warnings:
- Added the required column `stock` to the `Products` table without a default value. This is not possible if the table is not empty.
*/
-- RedefineTables
PRAGMA defer_foreign_keys=ON;
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_Products" (
"product_id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"product_name" TEXT NOT NULL,
"price" INTEGER NOT NULL,
"stock" INTEGER NOT NULL
);
INSERT INTO "new_Products" ("price", "product_id", "product_name") SELECT "price", "product_id", "product_name" FROM "Products";
DROP TABLE "Products";
ALTER TABLE "new_Products" RENAME TO "Products";
CREATE UNIQUE INDEX "Products_product_name_key" ON "Products"("product_name");
PRAGMA foreign_keys=ON;
PRAGMA defer_foreign_keys=OFF;
1 change: 1 addition & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,6 @@ model Products{
product_id Int @id @default(autoincrement())
product_name String @unique
price Int
stock Int
orderDetails Order_details[]
}

0 comments on commit 455fcfe

Please sign in to comment.