From 631330d3b49f9d8a280702f69e061e1ee575b00b Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Wed, 19 Aug 2026 18:34:52 +0700 Subject: [PATCH] feat: refactor PurchaseEdit component to streamline material selection and quantity handling --- app/Services/Admin/Manage/PurchaseService.php | 12 +- .../js/pages/admin/manage/purchase/edit.tsx | 274 ++++++------------ 2 files changed, 101 insertions(+), 185 deletions(-) diff --git a/app/Services/Admin/Manage/PurchaseService.php b/app/Services/Admin/Manage/PurchaseService.php index a85b8ab..c5bebe2 100644 --- a/app/Services/Admin/Manage/PurchaseService.php +++ b/app/Services/Admin/Manage/PurchaseService.php @@ -152,6 +152,10 @@ public function getForEdit(Purchase $purchase): array fn ($media) => $this->s3Service->getTemporaryUrl($media->getPath()) )->toArray(); + $existingQuantities = $items->mapWithKeys(fn (PurchaseItem $item) => [ + (int) $item->raw_material_price_id => (int) $item->quantity, + ])->all(); + return [ 'id' => $purchase->id, 'name' => $rawMaterial?->name ?? '', @@ -164,12 +168,8 @@ public function getForEdit(Purchase $purchase): array 'photo_urls' => $purchasePhotoUrls, 'variants' => $variants, 'default_mode' => $singleMaterial && ! $sharedWithOther ? 'new' : 'existing', - 'existing_material_name' => $singleMaterial ? $materials->first()->name : null, - 'existing_quantities' => $singleMaterial - ? $items->mapWithKeys(fn (PurchaseItem $item) => [ - (int) $item->raw_material_price_id => (int) $item->quantity, - ])->all() - : [], + 'existing_material_name' => $materials->first()->name ?? null, + 'existing_quantities' => $existingQuantities, ]; } diff --git a/resources/js/pages/admin/manage/purchase/edit.tsx b/resources/js/pages/admin/manage/purchase/edit.tsx index 881b896..f56cb02 100644 --- a/resources/js/pages/admin/manage/purchase/edit.tsx +++ b/resources/js/pages/admin/manage/purchase/edit.tsx @@ -84,9 +84,6 @@ export default function PurchaseEdit({ }); const [uploading, setUploading] = useState(false); - const [selectedMaterialName, setSelectedMaterialName] = useState( - purchase.existing_material_name ?? '', - ); const [quantities, setQuantities] = useState>(() => Object.fromEntries( Object.entries(purchase.existing_quantities).map(([id, qty]) => [ @@ -132,10 +129,34 @@ export default function PurchaseEdit({ ); const total = subtotal - discount + shippingCost; - const selectedMaterial = useMemo( - () => rawMaterials.find((m) => m.name === selectedMaterialName) ?? null, - [rawMaterials, selectedMaterialName], - ); + const purchasedVariantsByMaterial = useMemo(() => { + const map = new Map(); + + for (const [priceId, quantity] of Object.entries(quantities)) { + const id = Number(priceId); + const price = priceMap.get(id); + const material = materialByPriceId.get(id); + + if (!price || !material) continue; + + if (!map.has(material.name)) { + map.set(material.name, { name: material.name, unit: material.unit, items: [] }); + } + + map.get(material.name)!.items.push({ + id: price.id, + variant: price.variant, + price: price.price, + stock: price.stock, + photo_url: price.photo_url, + photo_conversion_url: price.photo_conversion_url, + }); + } + + return map; + }, [quantities, priceMap, materialByPriceId]); + + const isMultiMaterial = purchasedVariantsByMaterial.size > 1; const updateQuantity = useCallback((priceId: number, value: number) => { setQuantities((prev) => ({ @@ -241,182 +262,77 @@ export default function PurchaseEdit({ -
- - m.name} - value={selectedMaterial} - onValueChange={( - value, - ) => - setSelectedMaterialName( - value?.name ?? - '', - ) - } - > - - - - Tidak ada bahan - baku ditemukan. - - - {(m) => ( - - {m.name}{' '} - ( - {m.unit} - ) - - )} - - - - -
- - {selectedMaterial && ( -
- {selectedMaterial.raw_material_prices.map( - (price) => ( -
- 0 - ? 'flex flex-wrap items-center justify-between gap-2 rounded-lg border border-primary p-3' - : 'flex flex-wrap items-center justify-between gap-2 rounded-lg border p-3' - } - > -
- {price.photo_conversion_url ?? price.photo_url ? ( - { - ) : ( -
- N/A -
- )} -
-

- { - price.variant - } -

-

- Stok:{' '} - {formatQuantity( - Number( - price.stock, - ), - )}{' '} - { - selectedMaterial.unit - }{' '} - ·{' '} - {formatCurrency( - price.price, - )} -

-
-
-
- - - updateQuantity( - price.id, - val, - ) - } + {Array.from(purchasedVariantsByMaterial.entries()).map(([materialName, group]) => ( +
+ {isMultiMaterial && ( +

+ {group.name} ({group.unit}) +

+ )} + {group.items.map((price) => ( +
+
+ {price.photo_conversion_url ?? price.photo_url ? ( + {price.variant} - + ) : ( +
+ N/A +
+ )} +
+

+ {price.variant} +

+

+ Stok:{' '} + {formatQuantity(Number(price.stock))}{' '} + {group.unit} · {formatCurrency(price.price)} +

- ), - )} +
+ + + updateQuantity(price.id, val) + } + /> + +
+
+ ))}
- )} + ))}