From 5a96b48725cd1c84245310cacc2a5ee918a88a5a Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Thu, 2 Jul 2026 12:04:30 +0700 Subject: [PATCH] feat: implement quick-create functionality for raw materials and products in Cutting module; enhance CuttingController and related components to support new features and improve user experience --- .../Manage/Cutting/CuttingController.php | 6 + .../Cutting/CuttingDraftItemController.php | 16 ++ .../CuttingQuickCreateProductRequest.php | 48 ++++ .../CuttingQuickCreateRawMaterialRequest.php | 44 ++++ .../Requests/Admin/Master/ProductRequest.php | 51 +--- .../Admin/Master/RawMaterialRequest.php | 23 +- .../Concerns/HasProductVariantRules.php | 78 ++++++ .../Concerns/HasRawMaterialPriceRules.php | 51 ++++ app/Services/Manage/CuttingService.php | 128 +++++++++ resources/js/lib/api.ts | 25 +- .../js/pages/admin/manage/cuttings/Create.vue | 6 + .../js/pages/admin/manage/cuttings/Edit.vue | 6 +- .../manage/cuttings/form/CuttingPosForm.vue | 47 +++- .../form/CuttingPosMaterialCatalogPanel.vue | 21 +- .../form/CuttingPosResultCatalogPanel.vue | 21 +- .../cuttings/form/QuickCreateProductModal.vue | 247 ++++++++++++++++++ .../form/QuickCreateRawMaterialModal.vue | 239 +++++++++++++++++ .../form/RawMaterialInfoSection.vue | 3 +- routes/web.php | 8 + 19 files changed, 986 insertions(+), 82 deletions(-) create mode 100644 app/Http/Requests/Admin/Manage/CuttingQuickCreateProductRequest.php create mode 100644 app/Http/Requests/Admin/Manage/CuttingQuickCreateRawMaterialRequest.php create mode 100644 app/Http/Requests/Concerns/HasProductVariantRules.php create mode 100644 app/Http/Requests/Concerns/HasRawMaterialPriceRules.php create mode 100644 resources/js/pages/admin/manage/cuttings/form/QuickCreateProductModal.vue create mode 100644 resources/js/pages/admin/manage/cuttings/form/QuickCreateRawMaterialModal.vue diff --git a/app/Http/Controllers/Admin/Manage/Cutting/CuttingController.php b/app/Http/Controllers/Admin/Manage/Cutting/CuttingController.php index 7009f68..9d9ad11 100644 --- a/app/Http/Controllers/Admin/Manage/Cutting/CuttingController.php +++ b/app/Http/Controllers/Admin/Manage/Cutting/CuttingController.php @@ -3,11 +3,13 @@ namespace App\Http\Controllers\Admin\Manage\Cutting; use App\Enums\CuttingStatus; +use App\Enums\RawMaterialUnit; use App\Http\Controllers\Concerns\FlashesEntityMessage; use App\Http\Controllers\Concerns\ParsesDataTableQuery; use App\Http\Controllers\Controller; use App\Http\Requests\Admin\Manage\CuttingRequest; use App\Http\Requests\Admin\Manage\CuttingStatusTransitionRequest; +use App\Models\Category; use App\Models\Cutting; use App\Services\Manage\CuttingService; use Illuminate\Http\RedirectResponse; @@ -44,6 +46,8 @@ public function create(Request $request): Response 'productCatalog' => $this->cuttingService->productCatalog(user: $user), 'draftMaterials' => $this->cuttingService->draftMaterialsForUser($user), 'draftResults' => $this->cuttingService->draftResultsForUser($user), + 'categories' => Category::query()->orderBy('name')->get(['id', 'name'])->map(fn ($c) => ['value' => $c->id, 'label' => $c->name])->all(), + 'units' => collect(RawMaterialUnit::cases())->map(fn ($u) => ['value' => $u->value, 'label' => $u->label()])->all(), ]); } @@ -70,6 +74,8 @@ public function edit(Cutting $cutting): Response|RedirectResponse 'cutting' => $this->cuttingService->findForEdit($cutting), 'rawMaterialCatalog' => $this->cuttingService->rawMaterialCatalog($cutting), 'productCatalog' => $this->cuttingService->productCatalog($cutting), + 'categories' => Category::query()->orderBy('name')->get(['id', 'name'])->map(fn ($c) => ['value' => $c->id, 'label' => $c->name])->all(), + 'units' => collect(RawMaterialUnit::cases())->map(fn ($u) => ['value' => $u->value, 'label' => $u->label()])->all(), ]); } diff --git a/app/Http/Controllers/Admin/Manage/Cutting/CuttingDraftItemController.php b/app/Http/Controllers/Admin/Manage/Cutting/CuttingDraftItemController.php index a2a1d65..f146559 100644 --- a/app/Http/Controllers/Admin/Manage/Cutting/CuttingDraftItemController.php +++ b/app/Http/Controllers/Admin/Manage/Cutting/CuttingDraftItemController.php @@ -5,6 +5,8 @@ use App\Http\Controllers\Controller; use App\Http\Requests\Admin\Manage\CuttingDraftMaterialRequest; use App\Http\Requests\Admin\Manage\CuttingDraftResultRequest; +use App\Http\Requests\Admin\Manage\CuttingQuickCreateProductRequest; +use App\Http\Requests\Admin\Manage\CuttingQuickCreateRawMaterialRequest; use App\Models\ProductVariant; use App\Models\RawMaterialPrice; use App\Services\Manage\CuttingService; @@ -44,4 +46,18 @@ public function destroyResult(Request $request, ProductVariant $productVariant): return response()->json(['ok' => true]); } + + public function quickCreateRawMaterial(CuttingQuickCreateRawMaterialRequest $request): JsonResponse + { + $rawMaterial = $this->cuttingService->quickCreateRawMaterial($request->validated()); + + return response()->json(['raw_material' => $rawMaterial]); + } + + public function quickCreateProduct(CuttingQuickCreateProductRequest $request): JsonResponse + { + $product = $this->cuttingService->quickCreateProduct($request->validated()); + + return response()->json(['product' => $product]); + } } diff --git a/app/Http/Requests/Admin/Manage/CuttingQuickCreateProductRequest.php b/app/Http/Requests/Admin/Manage/CuttingQuickCreateProductRequest.php new file mode 100644 index 0000000..71fb494 --- /dev/null +++ b/app/Http/Requests/Admin/Manage/CuttingQuickCreateProductRequest.php @@ -0,0 +1,48 @@ +user()?->can(Permission::CUTTINGS_CREATE->value) ?? false; + } + + /** + * @return array + */ + public function rules(): array + { + return [ + 'name' => ['required', 'string', 'max:200'], + 'description' => ['nullable', 'string'], + + 'category_ids' => ['nullable', 'array'], + 'category_ids.*' => ['integer', Rule::exists('categories', 'id')->whereNull('deleted_at')], + + ...$this->productVariantRules(), + ]; + } + + /** + * @return array + */ + public function attributes(): array + { + return [ + 'name' => 'Nama Produk', + 'description' => 'Deskripsi', + 'category_ids' => 'Kategori', + 'category_ids.*' => 'Kategori', + ...$this->productVariantAttributes(), + ]; + } +} diff --git a/app/Http/Requests/Admin/Manage/CuttingQuickCreateRawMaterialRequest.php b/app/Http/Requests/Admin/Manage/CuttingQuickCreateRawMaterialRequest.php new file mode 100644 index 0000000..989a039 --- /dev/null +++ b/app/Http/Requests/Admin/Manage/CuttingQuickCreateRawMaterialRequest.php @@ -0,0 +1,44 @@ +user()?->can(Permission::CUTTINGS_CREATE->value) ?? false; + } + + /** + * @return array + */ + public function rules(): array + { + return [ + 'name' => ['required', 'string', 'max:200'], + 'unit' => ['required', Rule::enum(RawMaterialUnit::class)], + + ...$this->rawMaterialPriceRules(), + ]; + } + + /** + * @return array + */ + public function attributes(): array + { + return [ + 'name' => 'Nama Bahan Baku', + 'unit' => 'Satuan', + ...$this->rawMaterialPriceAttributes(), + ]; + } +} diff --git a/app/Http/Requests/Admin/Master/ProductRequest.php b/app/Http/Requests/Admin/Master/ProductRequest.php index e4fd5fe..c463489 100644 --- a/app/Http/Requests/Admin/Master/ProductRequest.php +++ b/app/Http/Requests/Admin/Master/ProductRequest.php @@ -3,14 +3,13 @@ namespace App\Http\Requests\Admin\Master; use App\Enums\Permission; -use App\Enums\Role; -use App\Http\Requests\Concerns\ValidatesMediaUploads; +use App\Http\Requests\Concerns\HasProductVariantRules; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Validation\Rule; class ProductRequest extends FormRequest { - use ValidatesMediaUploads; + use HasProductVariantRules; public function authorize(): bool { @@ -26,42 +25,15 @@ public function authorize(): bool */ public function rules(): array { - $isAdminBahanBaku = $this->user()?->hasRole(Role::ADMIN_BAHAN_BAKU->value) ?? false; - - $rules = [ + return [ 'name' => ['required', 'string', 'max:200'], 'description' => ['nullable', 'string'], 'category_ids' => ['required', 'array', 'min:1'], 'category_ids.*' => ['integer', Rule::exists('categories', 'id')->whereNull('deleted_at')], - 'variants' => ['required', 'array', 'min:1'], - 'variants.*.id' => [ - 'nullable', - 'integer', - Rule::exists('product_variants', 'id') - ->where('product_id', $this->route('product')?->id) - ->whereNull('deleted_at'), - ], - 'variants.*.name' => ['required', 'string', 'max:200'], - 'variants.*.stock' => ['required', 'integer', 'min:0'], - 'variants.*.retail_stock' => ['required', 'integer', 'min:0'], - ...$this->variantImageRules(), + ...$this->productVariantRules(productId: $this->route('product')?->id), ]; - - if (! $isAdminBahanBaku) { - $rules['variants.*.prices'] = ['required', 'array']; - $rules['variants.*.prices.distributor'] = ['required', 'integer', 'min:0']; - $rules['variants.*.prices.agent'] = ['required', 'integer', 'min:0']; - $rules['variants.*.prices.sub_agent'] = ['required', 'integer', 'min:0']; - $rules['variants.*.prices.grosir'] = ['required', 'integer', 'min:0']; - $rules['variants.*.prices.retail'] = ['required', 'integer', 'min:0']; - $rules['variants.*.prices.tiktok'] = ['required', 'integer', 'min:0']; - $rules['variants.*.prices.shopee'] = ['required', 'integer', 'min:0']; - $rules['variants.*.prices.harga_modal'] = ['required', 'integer', 'min:0']; - } - - return $rules; } /** @@ -74,20 +46,7 @@ public function attributes(): array 'description' => 'Deskripsi', 'category_ids' => 'Kategori', 'category_ids.*' => 'Kategori', - 'variants' => 'Varian', - 'variants.*.name' => 'Nama Varian', - 'variants.*.stock' => 'Stok', - 'variants.*.retail_stock' => 'Stok Ecer', - 'variants.*.prices' => 'Harga', - 'variants.*.prices.distributor' => 'Distributor', - 'variants.*.prices.agent' => 'Agen', - 'variants.*.prices.sub_agent' => 'Sub Agen', - 'variants.*.prices.grosir' => 'Grosir', - 'variants.*.prices.retail' => 'Eceran', - 'variants.*.prices.tiktok' => 'TikTok', - 'variants.*.prices.shopee' => 'Shopee', - 'variants.*.prices.harga_modal' => 'Harga Modal', - ...$this->variantImageAttributes('variants', 'Foto Varian'), + ...$this->productVariantAttributes(), ]; } } diff --git a/app/Http/Requests/Admin/Master/RawMaterialRequest.php b/app/Http/Requests/Admin/Master/RawMaterialRequest.php index c44b98b..c044292 100644 --- a/app/Http/Requests/Admin/Master/RawMaterialRequest.php +++ b/app/Http/Requests/Admin/Master/RawMaterialRequest.php @@ -4,13 +4,13 @@ use App\Enums\Permission; use App\Enums\RawMaterialUnit; -use App\Http\Requests\Concerns\ValidatesMediaUploads; +use App\Http\Requests\Concerns\HasRawMaterialPriceRules; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Validation\Rule; class RawMaterialRequest extends FormRequest { - use ValidatesMediaUploads; + use HasRawMaterialPriceRules; public function authorize(): bool { @@ -30,18 +30,7 @@ public function rules(): array 'name' => ['required', 'string', 'max:200'], 'unit' => ['required', Rule::enum(RawMaterialUnit::class)], - 'prices' => ['required', 'array', 'min:1'], - 'prices.*.id' => [ - 'nullable', - 'integer', - Rule::exists('raw_material_prices', 'id') - ->where('raw_material_id', $this->route('rawMaterial')?->id) - ->whereNull('deleted_at'), - ], - 'prices.*.variant' => ['required', 'string', 'max:200'], - 'prices.*.price' => ['required', 'integer', 'gt:0'], - 'prices.*.stock' => ['required', 'numeric', 'decimal:0,4', 'min:0'], - ...$this->variantImageRules('prices'), + ...$this->rawMaterialPriceRules(rawMaterialId: $this->route('rawMaterial')?->id), ]; } @@ -53,11 +42,7 @@ public function attributes(): array return [ 'name' => 'Nama Bahan Baku', 'unit' => 'Satuan', - 'prices' => 'Varian', - 'prices.*.variant' => 'Nama Varian', - 'prices.*.price' => 'Harga', - 'prices.*.stock' => 'Stok', - ...$this->variantImageAttributes('prices', 'Foto Varian'), + ...$this->rawMaterialPriceAttributes(), ]; } } diff --git a/app/Http/Requests/Concerns/HasProductVariantRules.php b/app/Http/Requests/Concerns/HasProductVariantRules.php new file mode 100644 index 0000000..ce771ea --- /dev/null +++ b/app/Http/Requests/Concerns/HasProductVariantRules.php @@ -0,0 +1,78 @@ + + */ + protected function productVariantRules(string $variantsKey = 'variants', ?int $productId = null): array + { + $isAdminBahanBaku = $this->user()?->hasRole(Role::ADMIN_BAHAN_BAKU->value) ?? false; + + $rules = [ + "{$variantsKey}" => ['required', 'array', 'min:1'], + "{$variantsKey}.*.name" => ['required', 'string', 'max:200'], + "{$variantsKey}.*.stock" => ['required', 'integer', 'min:0'], + "{$variantsKey}.*.retail_stock" => ['required', 'integer', 'min:0'], + ...$this->variantImageRules($variantsKey), + ]; + + if ($productId) { + $rules["{$variantsKey}.*.id"] = [ + 'nullable', + 'integer', + Rule::exists('product_variants', 'id') + ->where('product_id', $productId) + ->whereNull('deleted_at'), + ]; + } + + if (! $isAdminBahanBaku) { + $rules["{$variantsKey}.*.prices"] = ['required', 'array']; + $rules["{$variantsKey}.*.prices.distributor"] = ['required', 'integer', 'min:0']; + $rules["{$variantsKey}.*.prices.agent"] = ['required', 'integer', 'min:0']; + $rules["{$variantsKey}.*.prices.sub_agent"] = ['required', 'integer', 'min:0']; + $rules["{$variantsKey}.*.prices.grosir"] = ['required', 'integer', 'min:0']; + $rules["{$variantsKey}.*.prices.retail"] = ['required', 'integer', 'min:0']; + $rules["{$variantsKey}.*.prices.tiktok"] = ['required', 'integer', 'min:0']; + $rules["{$variantsKey}.*.prices.shopee"] = ['required', 'integer', 'min:0']; + $rules["{$variantsKey}.*.prices.harga_modal"] = ['required', 'integer', 'min:0']; + } + + return $rules; + } + + /** + * @return array + */ + protected function productVariantAttributes(string $variantsKey = 'variants'): array + { + return [ + $variantsKey => 'Varian', + "{$variantsKey}.*.name" => 'Nama Varian', + "{$variantsKey}.*.stock" => 'Stok', + "{$variantsKey}.*.retail_stock" => 'Stok Ecer', + "{$variantsKey}.*.prices" => 'Harga', + "{$variantsKey}.*.prices.distributor" => 'Distributor', + "{$variantsKey}.*.prices.agent" => 'Agen', + "{$variantsKey}.*.prices.sub_agent" => 'Sub Agen', + "{$variantsKey}.*.prices.grosir" => 'Grosir', + "{$variantsKey}.*.prices.retail" => 'Eceran', + "{$variantsKey}.*.prices.tiktok" => 'TikTok', + "{$variantsKey}.*.prices.shopee" => 'Shopee', + "{$variantsKey}.*.prices.harga_modal" => 'Harga Modal', + ...$this->variantImageAttributes($variantsKey, 'Foto Varian'), + ]; + } +} diff --git a/app/Http/Requests/Concerns/HasRawMaterialPriceRules.php b/app/Http/Requests/Concerns/HasRawMaterialPriceRules.php new file mode 100644 index 0000000..d846727 --- /dev/null +++ b/app/Http/Requests/Concerns/HasRawMaterialPriceRules.php @@ -0,0 +1,51 @@ + + */ + protected function rawMaterialPriceRules(string $pricesKey = 'prices', ?int $rawMaterialId = null): array + { + $rules = [ + "{$pricesKey}" => ['required', 'array', 'min:1'], + "{$pricesKey}.*.variant" => ['required', 'string', 'max:200'], + "{$pricesKey}.*.price" => ['required', 'integer', 'gt:0'], + "{$pricesKey}.*.stock" => ['required', 'numeric', 'decimal:0,4', 'min:0'], + ...$this->variantImageRules($pricesKey), + ]; + + if ($rawMaterialId) { + $rules["{$pricesKey}.*.id"] = [ + 'nullable', + 'integer', + Rule::exists('raw_material_prices', 'id') + ->where('raw_material_id', $rawMaterialId) + ->whereNull('deleted_at'), + ]; + } + + return $rules; + } + + /** + * @return array + */ + protected function rawMaterialPriceAttributes(string $pricesKey = 'prices'): array + { + return [ + $pricesKey => 'Varian', + "{$pricesKey}.*.variant" => 'Nama Varian', + "{$pricesKey}.*.price" => 'Harga', + "{$pricesKey}.*.stock" => 'Stok', + ...$this->variantImageAttributes($pricesKey, 'Foto Varian'), + ]; + } +} diff --git a/app/Services/Manage/CuttingService.php b/app/Services/Manage/CuttingService.php index 1281dd8..d9f049c 100644 --- a/app/Services/Manage/CuttingService.php +++ b/app/Services/Manage/CuttingService.php @@ -3,6 +3,7 @@ namespace App\Services\Manage; use App\Enums\CuttingStatus; +use App\Enums\RawMaterialUnit; use App\Enums\Role; use App\Models\Cutting; use App\Models\CuttingMaterial; @@ -13,6 +14,7 @@ use App\Models\RawMaterial; use App\Models\RawMaterialPrice; use App\Models\User; +use App\Services\Media\MediaService; use App\Services\System\PushNotificationService; use App\Support\Media\MediaPresenter; use Illuminate\Contracts\Pagination\LengthAwarePaginator; @@ -26,6 +28,7 @@ class CuttingService { public function __construct( private readonly PushNotificationService $pushNotificationService, + private readonly MediaService $mediaService, ) {} public function paginateForIndex(array $tableQuery, User $user): LengthAwarePaginator @@ -1034,4 +1037,129 @@ private function storeResultPrices(Cutting $cutting, array $resultPrices): void } } } + + /** + * Quick-create a raw material with variants, bypassing owner verification. + */ + public function quickCreateRawMaterial(array $validated): array + { + $rawMaterial = RawMaterial::create([ + 'name' => $validated['name'], + 'unit' => $validated['unit'], + 'is_active' => true, + ]); + + $createdPrices = []; + $maxVariantImages = 5; + + foreach ($validated['prices'] as $index => $priceData) { + $price = $rawMaterial->prices()->create([ + 'variant' => $priceData['variant'], + 'price' => $priceData['price'], + 'stock' => $priceData['stock'], + ]); + + $this->mediaService->syncCollection( + $price, + 'images', + $priceData['images'] ?? null, + null, + $maxVariantImages, + required: true, + errorKey: "prices.{$index}.images", + ); + + $price->refresh(); + + $createdPrices[] = [ + 'id' => $price->id, + 'variant' => $price->variant, + 'price' => $price->price, + 'price_formatted' => 'Rp '.number_format($price->price, 0, ',', '.'), + 'stock' => $price->stock, + 'stock_formatted' => $this->formatStockForUnit((float) $price->stock, $rawMaterial->unit), + 'stock_input' => $this->formatQuantityInput((float) $price->stock), + 'images' => MediaPresenter::collection($price, 'images'), + ]; + } + + return [ + 'id' => $rawMaterial->id, + 'name' => $rawMaterial->name, + 'unit' => $rawMaterial->unit->value, + 'unit_label' => $rawMaterial->unit->label(), + 'unit_abbreviation' => $rawMaterial->unit->abbreviation(), + 'is_active' => true, + 'prices' => $createdPrices, + ]; + } + + /** + * Quick-create a product with variants and prices, bypassing owner verification. + */ + public function quickCreateProduct(array $validated): array + { + $product = Product::create([ + 'name' => $validated['name'], + 'description' => $validated['description'] ?? null, + 'is_active' => true, + ]); + + if (!empty($validated['category_ids'])) { + $product->categories()->sync($validated['category_ids']); + } + + $createdVariants = []; + $maxVariantImages = 5; + + foreach ($validated['variants'] as $index => $variantData) { + $variant = $product->variants()->create([ + 'name' => $variantData['name'], + 'stock' => $variantData['stock'] ?? 0, + 'retail_stock' => $variantData['retail_stock'] ?? 0, + ]); + + if (!empty($variantData['prices'])) { + foreach ($variantData['prices'] as $type => $priceValue) { + $variant->prices()->create([ + 'type' => $type, + 'price' => (int) $priceValue, + ]); + } + } + + $this->mediaService->syncCollection( + $variant, + 'images', + $variantData['images'] ?? null, + null, + $maxVariantImages, + required: true, + errorKey: "variants.{$index}.images", + ); + + $variant->refresh(); + + $createdVariants[] = [ + 'id' => $variant->id, + 'name' => $variant->name, + 'stock' => $variant->stock, + 'images' => MediaPresenter::collection($variant, 'images'), + ]; + } + + return [ + 'id' => $product->id, + 'name' => $product->name, + 'is_active' => true, + 'variants' => $createdVariants, + ]; + } + + private function formatStockForUnit(float $stock, RawMaterialUnit $unit): string + { + $formatted = rtrim(rtrim(number_format($stock, 2, ',', '.'), '0'), ','); + + return "{$formatted} {$unit->abbreviation()}"; + } } diff --git a/resources/js/lib/api.ts b/resources/js/lib/api.ts index bd6c81e..9c13525 100644 --- a/resources/js/lib/api.ts +++ b/resources/js/lib/api.ts @@ -7,15 +7,26 @@ function getXsrfToken(): string { } export async function apiFetch(url: string, options: RequestInit = {}): Promise { + const isFormData = options.body instanceof FormData; + + const headers: Record = { + Accept: 'application/json', + 'X-XSRF-TOKEN': getXsrfToken(), + 'X-Requested-With': 'XMLHttpRequest', + ...(!isFormData && { 'Content-Type': 'application/json' }), + ...(options.headers as Record), + }; + + // Remove any null/undefined headers + Object.keys(headers).forEach((key) => { + if (headers[key] == null) { + delete headers[key]; + } + }); + const response = await fetch(url, { ...options, - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - 'X-XSRF-TOKEN': getXsrfToken(), - 'X-Requested-With': 'XMLHttpRequest', - ...options.headers, - }, + headers, credentials: 'same-origin', }); diff --git a/resources/js/pages/admin/manage/cuttings/Create.vue b/resources/js/pages/admin/manage/cuttings/Create.vue index 8d10097..eb724e9 100644 --- a/resources/js/pages/admin/manage/cuttings/Create.vue +++ b/resources/js/pages/admin/manage/cuttings/Create.vue @@ -7,6 +7,8 @@ import type { CuttingRawMaterialCatalogItem, CuttingResultCartItem, } from '@/types/cutting'; +import type { CategoryOption } from '@/types/product'; +import type { EnumOption } from '@/types/raw-material'; import { Head } from '@inertiajs/vue3'; import CuttingPosForm from './form/CuttingPosForm.vue'; import { index, store } from '@/routes/admin/manage/cuttings'; @@ -16,6 +18,8 @@ defineProps<{ productCatalog: CuttingProductCatalogItem[]; draftMaterials: CuttingMaterialCartItem[]; draftResults: CuttingResultCartItem[]; + categories: CategoryOption[]; + units: EnumOption[]; }>(); @@ -40,6 +44,8 @@ defineProps<{ :product-catalog="productCatalog" :draft-materials="draftMaterials" :draft-results="draftResults" + :categories="categories" + :units="units" :submit-url="store.url()" method="post" submit-label="Simpan" diff --git a/resources/js/pages/admin/manage/cuttings/Edit.vue b/resources/js/pages/admin/manage/cuttings/Edit.vue index a643b63..b27aed4 100644 --- a/resources/js/pages/admin/manage/cuttings/Edit.vue +++ b/resources/js/pages/admin/manage/cuttings/Edit.vue @@ -6,6 +6,8 @@ import type { CuttingProductCatalogItem, CuttingRawMaterialCatalogItem, } from '@/types/cutting'; +import type { CategoryOption } from '@/types/product'; +import type { EnumOption } from '@/types/raw-material'; import { Head } from '@inertiajs/vue3'; import { computed } from 'vue'; import CuttingPosForm from './form/CuttingPosForm.vue'; @@ -15,6 +17,8 @@ const props = defineProps<{ cutting: CuttingEditItem; rawMaterialCatalog: CuttingRawMaterialCatalogItem[]; productCatalog: CuttingProductCatalogItem[]; + categories: CategoryOption[]; + units: EnumOption[]; }>(); const initialData = computed(() => ({ @@ -45,7 +49,6 @@ const initialData = computed(() => ({