Added: Product & Upload Module

This commit is contained in:
Fahim Anzam Dip 2021-07-16 21:13:21 +06:00
parent 017ea56668
commit cb5a3f00ae
22 changed files with 536 additions and 58 deletions

View File

@ -16,6 +16,7 @@ class CreateProductsTable extends Migration
Schema::create('products', function (Blueprint $table) { Schema::create('products', function (Blueprint $table) {
$table->id(); $table->id();
$table->unsignedBigInteger('category_id'); $table->unsignedBigInteger('category_id');
$table->string('product_image')->nullable();
$table->string('product_name'); $table->string('product_name');
$table->string('product_code')->unique()->nullable(); $table->string('product_code')->unique()->nullable();
$table->string('product_barcode_symbology')->nullable(); $table->string('product_barcode_symbology')->nullable();
@ -24,7 +25,7 @@ class CreateProductsTable extends Migration
$table->integer('product_price'); $table->integer('product_price');
$table->integer('product_stock_alert'); $table->integer('product_stock_alert');
$table->integer('product_order_tax')->nullable(); $table->integer('product_order_tax')->nullable();
$table->boolean('product_tax_type')->nullable(); $table->tinyInteger('product_tax_type')->nullable();
$table->text('product_note')->nullable(); $table->text('product_note')->nullable();
$table->foreign('category_id')->references('id')->on('categories')->restrictOnDelete(); $table->foreign('category_id')->references('id')->on('categories')->restrictOnDelete();
$table->timestamps(); $table->timestamps();

View File

@ -12,6 +12,6 @@ class Category extends Model
protected $guarded = []; protected $guarded = [];
public function products() { public function products() {
return $this->hasMany(Product::class, 'id', 'category_id'); return $this->hasMany(Product::class, 'category_id', 'id');
} }
} }

View File

@ -13,6 +13,8 @@ class Product extends Model implements HasMedia
protected $guarded = []; protected $guarded = [];
protected $with = ['media'];
public function category() { public function category() {
return $this->belongsTo(Category::class, 'category_id', 'id'); return $this->belongsTo(Category::class, 'category_id', 'id');
} }

View File

@ -6,6 +6,11 @@ use App\DataTables\ProductDataTable;
use Illuminate\Contracts\Support\Renderable; use Illuminate\Contracts\Support\Renderable;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Routing\Controller; use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Storage;
use Modules\Product\Entities\Product;
use Modules\Product\Http\Requests\ProductCreateRequest;
use Modules\Product\Http\Requests\ProductUpdateRequest;
use Modules\Upload\Entities\Upload;
class ProductController extends Controller class ProductController extends Controller
{ {
@ -31,8 +36,32 @@ class ProductController extends Controller
* @param Request $request * @param Request $request
* @return Renderable * @return Renderable
*/ */
public function store(Request $request) { public function store(ProductCreateRequest $request) {
// $product = Product::create($request->except('image'));
if ($request->has('image')) {
$tempFile = Upload::where('folder', $request->image)->first();
if ($tempFile) {
$product->addMedia(Storage::path('public/temp/' . $request->image . '/' . $tempFile->filename))->toMediaCollection();
Storage::deleteDirectory('public/temp/' . $request->image);
$tempFile->delete();
}
}
toast('Product Created!', 'success');
return redirect()->route('products.index');
}
/**
* Show the details for the specified resource.
* @param int $id
* @return Renderable
*/
public function show(Product $product) {
return view('product::products.show', compact('product'));
} }
/** /**
@ -40,8 +69,8 @@ class ProductController extends Controller
* @param int $id * @param int $id
* @return Renderable * @return Renderable
*/ */
public function edit($id) { public function edit(Product $product) {
return view('product::products.edit'); return view('product::products.edit', compact('product'));
} }
/** /**
@ -50,8 +79,26 @@ class ProductController extends Controller
* @param int $id * @param int $id
* @return Renderable * @return Renderable
*/ */
public function update(Request $request, $id) { public function update(ProductUpdateRequest $request, Product $product) {
// $product->update($request->except('image'));
if ($request->has('image')) {
$tempFile = Upload::where('folder', $request->image)->first();
$media = $product->getMedia();
$media[0]->delete();
if ($tempFile) {
$product->addMedia(Storage::path('public/temp/' . $request->image . '/' . $tempFile->filename))->toMediaCollection();
Storage::deleteDirectory('public/temp/' . $request->image);
$tempFile->delete();
}
}
toast('Product Updated!', 'info');
return redirect()->route('products.index');
} }
/** /**
@ -59,7 +106,11 @@ class ProductController extends Controller
* @param int $id * @param int $id
* @return Renderable * @return Renderable
*/ */
public function destroy($id) { public function destroy(Product $product) {
// $product->delete();
toast('Product Deleted!', 'warning');
return redirect()->route('products.index');
} }
} }

View File

@ -0,0 +1,40 @@
<?php
namespace Modules\Product\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ProductCreateRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'product_name' => ['required', 'string', 'max:255'],
'product_code' => ['required', 'string', 'max:255', 'unique:products,product_code'],
'product_barcode_symbology' => ['required', 'string', 'max:255'],
'product_quantity' => ['required', 'integer', 'min:1'],
'product_cost' => ['required', 'integer'],
'product_price' => ['required', 'integer'],
'product_stock_alert' => ['required', 'integer', 'min:0'],
'product_order_tax' => ['nullable', 'integer', 'min:1'],
'product_tax_type' => ['nullable', 'integer'],
'product_note' => ['nullable', 'string', 'max:1000'],
'category_id' => ['required', 'integer']
];
}
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
}

View File

@ -0,0 +1,41 @@
<?php
namespace Modules\Product\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class ProductUpdateRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'product_name' => ['required', 'string', 'max:255'],
'product_code' => ['required', 'string', 'max:255', 'unique:products,product_code,' . $this->product->id],
'product_barcode_symbology' => ['required', 'string', 'max:255'],
'product_quantity' => ['required', 'integer', 'min:1'],
'product_cost' => ['required', 'integer'],
'product_price' => ['required', 'integer'],
'product_stock_alert' => ['required', 'integer', 'min:0'],
'product_order_tax' => ['nullable', 'integer', 'min:1'],
'product_tax_type' => ['nullable', 'integer'],
'product_note' => ['nullable', 'string', 'max:1000'],
'category_id' => ['required', 'integer']
];
}
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
}

View File

@ -1,7 +1,12 @@
<a href="{{ route('product-categories.edit', $data->id) }}" class="btn btn-info btn-sm"> <a href="{{ route('product-categories.edit', $data->id) }}" class="btn btn-info btn-sm">
<i class="bi bi-pencil"></i> <i class="bi bi-pencil"></i>
</a> </a>
<button id="delete" class="btn btn-danger btn-sm" onclick="e.preventDefault();document.getElementById('destroy{{ $data->id }}').submit();"> <button id="delete" class="btn btn-danger btn-sm" onclick="
e.preventDefault();
if (confirm('Are you sure? It will delete the data permanently!')) {
document.getElementById('destroy{{ $data->id }}').submit();
}
">
<i class="bi bi-trash"></i> <i class="bi bi-trash"></i>
<form id="destroy{{ $data->id }}" class="d-none" action="{{ route('product-categories.destroy', $data->id) }}"> <form id="destroy{{ $data->id }}" class="d-none" action="{{ route('product-categories.destroy', $data->id) }}">
@csrf @csrf

View File

@ -7,14 +7,6 @@
<link href="https://unpkg.com/filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css" rel="stylesheet"> <link href="https://unpkg.com/filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css" rel="stylesheet">
@endsection @endsection
@push('page_css')
<style>
.filepond--credits {
display: none;
}
</style>
@endpush
@section('breadcrumb') @section('breadcrumb')
<ol class="breadcrumb border-0 m-0"> <ol class="breadcrumb border-0 m-0">
<li class="breadcrumb-item"><a href="{{ route('home') }}">Home</a></li> <li class="breadcrumb-item"><a href="{{ route('home') }}">Home</a></li>
@ -29,6 +21,7 @@
@csrf @csrf
<div class="row"> <div class="row">
<div class="col-lg-12"> <div class="col-lg-12">
@include('utils.alerts')
<div class="form-group"> <div class="form-group">
<button class="btn btn-primary">Create Product <i class="bi bi-check"></i></button> <button class="btn btn-primary">Create Product <i class="bi bi-check"></i></button>
</div> </div>
@ -66,7 +59,7 @@
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="barcode_symbology">Barcode Symbology <span class="text-danger">*</span></label> <label for="barcode_symbology">Barcode Symbology <span class="text-danger">*</span></label>
<select class="form-control" name="barcode_symbology" id="barcode_symbology" required> <select class="form-control" name="product_barcode_symbology" id="barcode_symbology" required>
<option value="" selected disabled>Select Symbology</option> <option value="" selected disabled>Select Symbology</option>
<option value="C128">Code 128</option> <option value="C128">Code 128</option>
<option value="C39">Code 39</option> <option value="C39">Code 39</option>
@ -102,8 +95,8 @@
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="stock_alert">Alert Quantity <span class="text-danger">*</span></label> <label for="product_stock_alert">Alert Quantity <span class="text-danger">*</span></label>
<input type="number" class="form-control" name="stock_alert" required value="{{ old('stock_alert') }}" min="0"> <input type="number" class="form-control" name="product_stock_alert" required value="{{ old('stock_alert') }}" min="0">
</div> </div>
</div> </div>
</div> </div>
@ -112,16 +105,16 @@
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="product_order_tax">Tax (%)</label> <label for="product_order_tax">Tax (%)</label>
<input type="number" class="form-control" name="product_order_tax" required value="{{ old('product_order_tax') }}" min="1"> <input type="number" class="form-control" name="product_order_tax" value="{{ old('product_order_tax') }}" min="1">
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="product_tax_type">Tax type</label> <label for="product_tax_type">Tax type</label>
<select class="form-control" name="product_tax_type" id="product_tax_type" required> <select class="form-control" name="product_tax_type" id="product_tax_type">
<option value="" selected disabled>Select Tax Type</option> <option value="" selected disabled>Select Tax Type</option>
<option value="0">Exclusive</option> <option value="1">Exclusive</option>
<option value="1">Inclusive</option> <option value="2">Inclusive</option>
</select> </select>
</div> </div>
</div> </div>
@ -135,7 +128,7 @@
<div class="card-body"> <div class="card-body">
<div class="form-group"> <div class="form-group">
<label for="image">Product Image <span class="text-danger">*</span></label> <label for="image">Product Image <span class="text-danger">*</span></label>
<input id="image" type="file" name="product_image" required data-max-file-size="500KB"> <input id="image" type="file" name="image" required data-max-file-size="500KB">
</div> </div>
</div> </div>
</div> </div>

View File

@ -0,0 +1,170 @@
@extends('layouts.app')
@section('title', 'Edit Product')
@section('third_party_stylesheets')
<link href="https://unpkg.com/filepond/dist/filepond.css" rel="stylesheet" />
<link href="https://unpkg.com/filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css" rel="stylesheet">
@endsection
@section('breadcrumb')
<ol class="breadcrumb border-0 m-0">
<li class="breadcrumb-item"><a href="{{ route('home') }}">Home</a></li>
<li class="breadcrumb-item"><a href="{{ route('products.index') }}">Products</a></li>
<li class="breadcrumb-item active">Edit</li>
</ol>
@endsection
@section('content')
<div class="container-fluid mb-4">
<form action="{{ route('products.update', $product->id) }}" method="POST" enctype="multipart/form-data">
@csrf
@method('patch')
<div class="row">
<div class="col-lg-12">
@include('utils.alerts')
<div class="form-group">
<button class="btn btn-primary">Update Product <i class="bi bi-check"></i></button>
</div>
</div>
<div class="col-lg-8">
<div class="card h-100">
<div class="card-body">
<div class="form-row">
<div class="col-md-7">
<div class="form-group">
<label for="product_name">Product Name <span class="text-danger">*</span></label>
<input type="text" class="form-control" name="product_name" required value="{{ $product->product_name }}">
</div>
</div>
<div class="col-md-5">
<div class="form-group">
<label for="product_code">Code <span class="text-danger">*</span></label>
<input type="text" class="form-control" name="product_code" required value="{{ $product->product_code }}">
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-6">
<div class="form-group">
<label for="category_id">Category <span class="text-danger">*</span></label>
<select class="form-control" name="category_id" id="category_id" required>
@foreach(\Modules\Product\Entities\Category::all() as $category)
<option {{ $category->id == $product->category->id ? 'selected' : '' }} value="{{ $category->id }}">{{ $category->category_name }}</option>
@endforeach
</select>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="barcode_symbology">Barcode Symbology <span class="text-danger">*</span></label>
<select class="form-control" name="product_barcode_symbology" id="barcode_symbology" required>
<option {{ $product->product_barcode_symbology == 'C128' ? 'selected' : '' }} value="C128">Code 128</option>
<option {{ $product->product_barcode_symbology == 'C39' ? 'selected' : '' }} value="C39">Code 39</option>
<option {{ $product->product_barcode_symbology == 'UPCA' ? 'selected' : '' }} value="UPCA">UPC-A</option>
<option {{ $product->product_barcode_symbology == 'UPCE' ? 'selected' : '' }} value="UPCE">UPC-E</option>
<option {{ $product->product_barcode_symbology == 'EAN13' ? 'selected' : '' }} value="EAN13">EAN-13</option>
<option {{ $product->product_barcode_symbology == 'EAN8' ? 'selected' : '' }} value="EAN8">EAN-8</option>
</select>
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-6">
<div class="form-group">
<label for="product_cost">Cost <span class="text-danger">*</span></label>
<input type="number" class="form-control" name="product_cost" required value="{{ $product->product_cost }}">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="product_price">Price <span class="text-danger">*</span></label>
<input type="number" class="form-control" name="product_price" required value="{{ $product->product_price }}">
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-6">
<div class="form-group">
<label for="product_quantity">Staring Quantity <span class="text-danger">*</span></label>
<input type="number" class="form-control" name="product_quantity" required value="{{ $product->product_quantity }}" min="1">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="product_stock_alert">Alert Quantity <span class="text-danger">*</span></label>
<input type="number" class="form-control" name="product_stock_alert" required value="{{ $product->product_stock_alert }}" min="0">
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-6">
<div class="form-group">
<label for="product_order_tax">Tax (%)</label>
<input type="number" class="form-control" name="product_order_tax" value="{{ $product->product_order_tax }}" min="1">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="product_tax_type">Tax type</label>
<select class="form-control" name="product_tax_type" id="product_tax_type">
<option value="" selected disabled>Select Tax Type</option>
<option {{ $product->product_tax_type == 1 ? 'selected' : '' }} value="1">Exclusive</option>
<option {{ $product->product_tax_type == 2 ? 'selected' : '' }} value="2">Inclusive</option>
</select>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="card h-100">
<div class="card-body">
<div class="form-group">
<label for="image">Product Image</label>
<img class="img-thumbnail img-fluid mb-3" src="{{ $product->getFirstMediaUrl() }}" alt="Product Image">
<input id="image" type="file" name="image" data-max-file-size="500KB">
</div>
</div>
</div>
</div>
</div>
</form>
</div>
@endsection
@section('third_party_scripts')
<script src="https://unpkg.com/filepond-plugin-image-preview/dist/filepond-plugin-image-preview.js"></script>
<script src="https://unpkg.com/filepond-plugin-file-validate-size/dist/filepond-plugin-file-validate-size.js"></script>
<script src="https://unpkg.com/filepond-plugin-file-validate-type/dist/filepond-plugin-file-validate-type.js"></script>
<script src="https://unpkg.com/filepond/dist/filepond.js"></script>
@endsection
@push('page_scripts')
<script>
FilePond.registerPlugin(
FilePondPluginImagePreview,
FilePondPluginFileValidateSize,
FilePondPluginFileValidateType
);
const fileElement = document.querySelector('input[id="image"]');
const pond = FilePond.create( fileElement, {
acceptedFileTypes: ['image/png', 'image/jpg', 'image/jpeg'],
} );
FilePond.setOptions({
server: {
url: "{{ route('filepond.upload') }}",
headers: {
"X-CSRF-TOKEN": "{{ csrf_token() }}"
}
}
});
</script>
@endpush

View File

@ -4,7 +4,12 @@
<a href="{{ route('products.show', $data->id) }}" class="btn btn-primary btn-sm"> <a href="{{ route('products.show', $data->id) }}" class="btn btn-primary btn-sm">
<i class="bi bi-eye"></i> <i class="bi bi-eye"></i>
</a> </a>
<button id="delete" class="btn btn-danger btn-sm" onclick="event.preventDefault();document.getElementById('destroy{{ $data->id }}').submit();"> <button id="delete" class="btn btn-danger btn-sm" onclick="
event.preventDefault();
if (confirm('Are you sure? It will delete the data permanently!')) {
document.getElementById('destroy{{ $data->id }}').submit()
}
">
<i class="bi bi-trash"></i> <i class="bi bi-trash"></i>
<form id="destroy{{ $data->id }}" class="d-none" action="{{ route('products.destroy', $data->id) }}" method="POST"> <form id="destroy{{ $data->id }}" class="d-none" action="{{ route('products.destroy', $data->id) }}" method="POST">
@csrf @csrf

View File

@ -0,0 +1,83 @@
@extends('layouts.app')
@section('title', 'Product Details')
@section('breadcrumb')
<ol class="breadcrumb border-0 m-0">
<li class="breadcrumb-item"><a href="{{ route('home') }}">Home</a></li>
<li class="breadcrumb-item"><a href="{{ route('products.index') }}">Products</a></li>
<li class="breadcrumb-item active">Details</li>
</ol>
@endsection
@section('content')
<div class="container-fluid mb-4">
<div class="row">
<div class="col-lg-7">
<div class="card h-100">
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered table-hover">
<tr>
<th>Product Code</th>
<td>{{ $product->product_code }}</td>
</tr>
<tr>
<th>Name</th>
<td>{{ $product->product_name }}</td>
</tr>
<tr>
<th>Category</th>
<td>{{ $product->category->category_name }}</td>
</tr>
<tr>
<th>Cost</th>
<td>{{ $product->product_cost }}</td>
</tr>
<tr>
<th>Price</th>
<td>{{ $product->product_price }}</td>
</tr>
<tr>
<th>Quantity</th>
<td>{{ $product->product_quantity }}</td>
</tr>
<tr>
<th>Alert Quantity</th>
<td>{{ $product->product_stock_alert }}</td>
</tr>
<tr>
<th>Tax (%)</th>
<td>{{ $product->product_order_tax ?? 'N/A' }}</td>
</tr>
<tr>
<th>Tax Type</th>
<td>
@if($product->product_tax_type == 1)
Exclusive
@elseif($product->product_tax_type == 2)
Inclusive
@else
N/A
@endif
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div class="col-lg-5">
<div class="card h-100">
<div class="card-body">
<img src="{{ $product->getFirstMediaUrl() }}" alt="Product Image" class="img-fluid img-thumbnail">
</div>
</div>
</div>
</div>
</div>
@endsection

View File

@ -6,8 +6,10 @@
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
*/ */
Route::group(['middleware' => 'auth'], function () {
//Product //Product
Route::resource('products', 'ProductController'); Route::resource('products', 'ProductController');
//Product Category //Product Category
Route::resource('product-categories', 'CategoriesController')->except('create', 'show'); Route::resource('product-categories', 'CategoriesController')->except('create', 'show');
});

View File

@ -0,0 +1,33 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateUploadsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('uploads', function (Blueprint $table) {
$table->id();
$table->string('folder');
$table->string('filename');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('uploads');
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace Modules\Upload\Entities;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
class Upload extends Model implements HasMedia
{
use HasFactory, InteractsWithMedia;
protected $guarded = [];
}

View File

@ -5,11 +5,35 @@ namespace Modules\Upload\Http\Controllers;
use Illuminate\Contracts\Support\Renderable; use Illuminate\Contracts\Support\Renderable;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Routing\Controller; use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Storage;
use Intervention\Image\Facades\Image;
use Modules\Upload\Entities\Upload;
class UploadController extends Controller class UploadController extends Controller
{ {
public function filepondUpload(Request $request) { public function filepondUpload(Request $request) {
// $request->validate([
'image' => 'required|image|mimes:png,jpeg,jpg'
]);
if ($request->hasFile('image')) {
$uploaded_file = $request->file('image');
$filename = now()->timestamp . '.' . $uploaded_file->getClientOriginalExtension();
$folder = uniqid() . '-' . now()->timestamp;
$file = Image::make($uploaded_file)->encode($uploaded_file->getClientOriginalExtension());
Storage::put('public/temp/' . $folder . '/' . $filename, $file);
Upload::create([
'folder' => $folder,
'filename' => $filename
]);
return $folder;
}
return false;
} }
} }

View File

@ -11,4 +11,8 @@
| |
*/ */
Route::group(['middleware' => 'auth'], function () {
Route::post('/filepond/upload', 'UploadController@filepondUpload')->name('filepond.upload'); Route::post('/filepond/upload', 'UploadController@filepondUpload')->name('filepond.upload');
});

View File

@ -34,7 +34,7 @@ class ProductCategoriesDataTable extends DataTable
*/ */
public function query(Category $model) public function query(Category $model)
{ {
return $model->newQuery(); return $model->newQuery()->withCount('products');
} }
/** /**
@ -70,6 +70,8 @@ class ProductCategoriesDataTable extends DataTable
->addClass('text-center'), ->addClass('text-center'),
Column::make('category_name') Column::make('category_name')
->addClass('text-center'), ->addClass('text-center'),
Column::make('products_count')
->addClass('text-center'),
Column::computed('action') Column::computed('action')
->exportable(false) ->exportable(false)
->printable(false) ->printable(false)

View File

@ -20,17 +20,15 @@ class ProductDataTable extends DataTable
public function dataTable($query) public function dataTable($query)
{ {
return datatables() return datatables()
->eloquent($query) ->eloquent($query)->with('category')
->addColumn('action', function ($data) { ->addColumn('action', function ($data) {
return view('product::categories.partials.actions', compact('data')); return view('product::products.partials.actions', compact('data'));
}) })
->addColumn('product_image', function ($data) { ->addColumn('product_image', function ($data) {
$url = asset('storage/product_images/' . $data->product_image); $url = $data->getFirstMediaUrl();
return '<img src='.$url.' border="0" width="40" class="img-rounded" align="center" />'; return '<img src="'.$url.'" border="0" width="50" class="img-thumbnail" align="center" />';
}) })
->addColumn('category_name', function ($data) { ->rawColumns(['product_image']);
return $data->category->category_name;
});
} }
@ -42,7 +40,7 @@ class ProductDataTable extends DataTable
*/ */
public function query(Product $model) public function query(Product $model)
{ {
return $model->newQuery(); return $model->newQuery()->with('category');
} }
/** /**
@ -76,36 +74,39 @@ class ProductDataTable extends DataTable
return [ return [
Column::computed('product_image') Column::computed('product_image')
->title('Image') ->title('Image')
->addClass('text-center'), ->addClass('text-center')
->addClass('align-middle'),
Column::make('product_name') Column::make('product_name')
->title('Name') ->title('Name')
->addClass('text-center'), ->addClass('text-center')
->addClass('align-middle'),
Column::make('product_code') Column::make('product_code')
->title('Code') ->title('Code')
->addClass('text-center'), ->addClass('text-center')
->addClass('align-middle'),
Column::make('product_price') Column::make('product_price')
->title('Price') ->title('Price')
->addClass('text-center'), ->addClass('text-center')
->addClass('align-middle'),
Column::make('product_unit')
->title('Unit')
->addClass('text-center'),
Column::make('product_quantity') Column::make('product_quantity')
->title('Quantity') ->title('Quantity')
->addClass('text-center'), ->addClass('text-center')
->addClass('align-middle'),
Column::computed('category_name') Column::make('category.category_name')
->title('Category') ->title('Category')
->addClass('text-center'), ->addClass('text-center')
->addClass('align-middle'),
Column::computed('action') Column::computed('action')
->exportable(false) ->exportable(false)
->printable(false) ->printable(false)
->addClass('text-center'), ->addClass('text-center')
->addClass('align-middle'),
]; ];
} }

View File

@ -2,6 +2,7 @@
namespace App\Providers; namespace App\Providers;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider class AppServiceProvider extends ServiceProvider
@ -23,6 +24,6 @@ class AppServiceProvider extends ServiceProvider
*/ */
public function boot() public function boot()
{ {
// Model::preventLazyLoading(!app()->isProduction());
} }
} }

View File

@ -55,7 +55,7 @@ return [
| |
*/ */
'timer' => env('SWEET_ALERT_TIMER', 5000), 'timer' => env('SWEET_ALERT_TIMER', 3000),
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------

View File

@ -34,4 +34,7 @@
@endforeach @endforeach
</table> </table>
</body> </body>
<script>
window.print();
</script>
</html> </html>

View File

@ -14,5 +14,5 @@ Route::get('/', function () {
Auth::routes(); Auth::routes();
Route::get('/home', 'HomeController@index')->name('home'); Route::get('/home', 'HomeController@index')->name('home')->middleware('auth');