From 5335e5ad588355eb85718e027a4707b69efcad3a Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Wed, 12 Aug 2026 21:35:46 +0700 Subject: [PATCH] feat: add receipt conversion URLs for media handling across various services and components --- .../Finance/Cash/CashTransactionService.php | 2 ++ app/Services/Admin/Finance/ExpenseService.php | 7 +++++++ app/Services/Admin/Manage/CuttingService.php | 6 ++++++ app/Services/Admin/Manage/PurchaseService.php | 12 +++++++++--- app/Services/Admin/Manage/RestockService.php | 3 +++ app/Services/Admin/Manage/TransactionService.php | 6 ++++++ .../Admin/Master/Product/ProductService.php | 1 + .../Master/RawMaterial/RawMaterialService.php | 12 ++++++++---- .../components/dialogs/image-preview-button.tsx | 10 ++++++++-- .../finance/cash-account/transaction-columns.tsx | 7 +++++-- .../js/pages/admin/finance/expense/columns.tsx | 7 +++++-- .../js/pages/admin/manage/cutting/columns.tsx | 2 ++ .../pages/admin/manage/cutting/cutting-card.tsx | 3 ++- .../admin/manage/cutting/cutting-sub-row.tsx | 16 ++++++++++++++++ .../js/pages/admin/manage/purchase/columns.tsx | 2 ++ .../admin/manage/purchase/purchase-card.tsx | 3 ++- .../admin/manage/purchase/purchase-sub-row.tsx | 4 ++-- .../js/pages/admin/manage/restock/columns.tsx | 1 + .../admin/manage/restock/restock-sub-row.tsx | 8 ++++++++ .../pages/admin/manage/transaction/columns.tsx | 2 ++ .../manage/transaction/transaction-card.tsx | 3 ++- .../manage/transaction/transaction-sub-row.tsx | 3 ++- .../js/pages/admin/master/product/columns.tsx | 1 + .../admin/master/product/variant/sub-row.tsx | 3 ++- .../pages/admin/master/raw-material/columns.tsx | 1 + .../master/raw-material/variant/sub-row.tsx | 3 ++- 26 files changed, 107 insertions(+), 21 deletions(-) diff --git a/app/Services/Admin/Finance/Cash/CashTransactionService.php b/app/Services/Admin/Finance/Cash/CashTransactionService.php index 34425f9..a757761 100644 --- a/app/Services/Admin/Finance/Cash/CashTransactionService.php +++ b/app/Services/Admin/Finance/Cash/CashTransactionService.php @@ -193,6 +193,7 @@ private function formatTransaction(CashTransaction $transaction): array return $transaction->toArray() + [ 'receipt_key' => null, 'receipt_url' => null, + 'receipt_conversion_url' => null, ]; } @@ -201,6 +202,7 @@ private function formatTransaction(CashTransaction $transaction): array return $transaction->toArray() + [ 'receipt_key' => $s3Key, 'receipt_url' => $this->s3Service->getTemporaryUrl($s3Key), + 'receipt_conversion_url' => $this->s3Service->getTemporaryUrl($media->getPath('thumb')), ]; } } diff --git a/app/Services/Admin/Finance/ExpenseService.php b/app/Services/Admin/Finance/ExpenseService.php index cf81d02..e35db0b 100644 --- a/app/Services/Admin/Finance/ExpenseService.php +++ b/app/Services/Admin/Finance/ExpenseService.php @@ -155,6 +155,7 @@ private function formatExpense(Expense $expense): array return $expense->toArray() + [ 'receipt_key' => null, 'receipt_url' => null, + 'receipt_conversion_url' => null, ]; } @@ -165,9 +166,15 @@ private function formatExpense(Expense $expense): array return $this->s3Service->getTemporaryUrl($s3Key); }); + $conversionCacheKey = "expense_receipt_conversion_{$media->id}"; + $receiptConversionUrl = Cache::remember($conversionCacheKey, now()->addMinutes(55), function () use ($media) { + return $this->s3Service->getTemporaryUrl($media->getPath('thumb')); + }); + return $expense->toArray() + [ 'receipt_key' => $s3Key, 'receipt_url' => $receiptUrl, + 'receipt_conversion_url' => $receiptConversionUrl, ]; } } diff --git a/app/Services/Admin/Manage/CuttingService.php b/app/Services/Admin/Manage/CuttingService.php index 41ba3ab..a9869b5 100644 --- a/app/Services/Admin/Manage/CuttingService.php +++ b/app/Services/Admin/Manage/CuttingService.php @@ -46,6 +46,9 @@ public function paginated(int $perPage = 25, string $search = '', string $sort = $cutting->photo_url = $cuttingMedia ? $this->s3Service->getTemporaryUrl($cuttingMedia->getPath()) : null; + $cutting->photo_conversion_url = $cuttingMedia + ? $this->s3Service->getTemporaryUrl($cuttingMedia->getPath('thumb')) + : null; $cutting->cuttingMaterials->each(function (CuttingMaterial $material) { $media = $material->rawMaterialPrice?->getFirstMedia('images'); @@ -53,6 +56,9 @@ public function paginated(int $perPage = 25, string $search = '', string $sort = $material->rawMaterialPrice->photo_url = $media ? $this->s3Service->getTemporaryUrl($media->getPath()) : null; + $material->rawMaterialPrice->photo_conversion_url = $media + ? $this->s3Service->getTemporaryUrl($media->getPath('thumb')) + : null; } }); }); diff --git a/app/Services/Admin/Manage/PurchaseService.php b/app/Services/Admin/Manage/PurchaseService.php index 0705100..ed3cdfc 100644 --- a/app/Services/Admin/Manage/PurchaseService.php +++ b/app/Services/Admin/Manage/PurchaseService.php @@ -49,15 +49,21 @@ public function paginated(int $perPage = 25, string $search = '', string $sort = $purchase->photo_url = $purchaseMedia ? $this->s3Service->getTemporaryUrl($purchaseMedia->getPath()) : null; + $purchase->photo_conversion_url = $purchaseMedia + ? $this->s3Service->getTemporaryUrl($purchaseMedia->getPath('thumb')) + : null; $purchase->purchaseItems->each(function (PurchaseItem $item) { if (! $item->rawMaterialPrice) { return; } - $media = $item->rawMaterialPrice->getMedia('images'); - $item->rawMaterialPrice->photo_url = $media->first() - ? $this->s3Service->getTemporaryUrl($media->first()->getPath()) + $media = $item->rawMaterialPrice->getFirstMedia('images'); + $item->rawMaterialPrice->photo_url = $media + ? $this->s3Service->getTemporaryUrl($media->getPath()) + : null; + $item->rawMaterialPrice->photo_conversion_url = $media + ? $this->s3Service->getTemporaryUrl($media->getPath('thumb')) : null; }); }); diff --git a/app/Services/Admin/Manage/RestockService.php b/app/Services/Admin/Manage/RestockService.php index 8d090c5..18e9fb2 100644 --- a/app/Services/Admin/Manage/RestockService.php +++ b/app/Services/Admin/Manage/RestockService.php @@ -53,6 +53,9 @@ public function paginated(int $perPage = 25, string $search = '', string $sort = $item->productVariant->photo_url = $media ? $this->s3Service->getTemporaryUrl($media->getPath()) : null; + $item->productVariant->photo_conversion_url = $media + ? $this->s3Service->getTemporaryUrl($media->getPath('thumb')) + : null; }); }); diff --git a/app/Services/Admin/Manage/TransactionService.php b/app/Services/Admin/Manage/TransactionService.php index afef58b..6e76841 100644 --- a/app/Services/Admin/Manage/TransactionService.php +++ b/app/Services/Admin/Manage/TransactionService.php @@ -79,6 +79,9 @@ public function paginated(int $perPage = 25, string $search = '', string $sort = $order->photo_url = $orderMedia ? $this->s3Service->getTemporaryUrl($orderMedia->getPath()) : null; + $order->photo_conversion_url = $orderMedia + ? $this->s3Service->getTemporaryUrl($orderMedia->getPath('thumb')) + : null; $order->orderItems->each(function (OrderItem $item) { if (! $item->productVariant) { @@ -89,6 +92,9 @@ public function paginated(int $perPage = 25, string $search = '', string $sort = $item->productVariant->photo_url = $media ? $this->s3Service->getTemporaryUrl($media->getPath()) : null; + $item->productVariant->photo_conversion_url = $media + ? $this->s3Service->getTemporaryUrl($media->getPath('thumb')) + : null; }); $order->profit = $order->total_amount - $order->cogs; diff --git a/app/Services/Admin/Master/Product/ProductService.php b/app/Services/Admin/Master/Product/ProductService.php index 9a9c665..112b75f 100644 --- a/app/Services/Admin/Master/Product/ProductService.php +++ b/app/Services/Admin/Master/Product/ProductService.php @@ -60,6 +60,7 @@ public function paginated(int $perPage = 25, string $search = '', string $sort = $product->productVariants->each(function ($variant) { $media = $variant->getMedia('images'); $variant->photo_urls = $media->map(fn ($m) => $this->s3Service->getTemporaryUrl($m->getPath()))->toArray(); + $variant->photo_conversion_urls = $media->map(fn ($m) => $this->s3Service->getTemporaryUrl($m->getPath('thumb')))->toArray(); }); }); diff --git a/app/Services/Admin/Master/RawMaterial/RawMaterialService.php b/app/Services/Admin/Master/RawMaterial/RawMaterialService.php index af8b89e..308b775 100644 --- a/app/Services/Admin/Master/RawMaterial/RawMaterialService.php +++ b/app/Services/Admin/Master/RawMaterial/RawMaterialService.php @@ -48,10 +48,14 @@ public function paginated(int $perPage = 25, string $search = '', string $sort = $paginator->getCollection()->each(function ($rawMaterial) { $rawMaterial->rawMaterialPrices->each(function ($price) { - $media = $price->getMedia('images'); - $price->photo_url = $media->first() - ? $this->s3Service->getTemporaryUrl($media->first()->getPath()) - : null; + $media = $price->getFirstMedia('images'); + if ($media) { + $price->photo_url = $this->s3Service->getTemporaryUrl($media->getPath()); + $price->photo_conversion_url = $this->s3Service->getTemporaryUrl($media->getPath('thumb')); + } else { + $price->photo_url = null; + $price->photo_conversion_url = null; + } }); }); diff --git a/resources/js/components/dialogs/image-preview-button.tsx b/resources/js/components/dialogs/image-preview-button.tsx index 35ba38c..73ccd57 100644 --- a/resources/js/components/dialogs/image-preview-button.tsx +++ b/resources/js/components/dialogs/image-preview-button.tsx @@ -3,6 +3,8 @@ import { ImagePreviewModal } from '@/components/dialogs'; type ImagePreviewButtonProps = { srcs: string[]; + modalSrc?: string; + modalSrcs?: string[]; title?: string; alt?: string; className?: string; @@ -10,12 +12,16 @@ type ImagePreviewButtonProps = { export function ImagePreviewButton({ srcs, + modalSrc, + modalSrcs, title, alt, className = 'h-10 w-10', }: ImagePreviewButtonProps) { const [open, setOpen] = useState(false); + const modalSources = modalSrcs ?? (modalSrc ? [modalSrc] : null); + return ( <>