feat: Implement order management with datatable display and updated forms

This commit is contained in:
pbao9
2026-02-14 18:00:15 +07:00
parent d683afc901
commit 5252f9142c
21 changed files with 490 additions and 541 deletions
+44 -6
View File
@@ -34,6 +34,7 @@ use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Yajra\DataTables\Facades\DataTables;
class OrderController extends Controller
@@ -55,11 +56,9 @@ class OrderController extends Controller
) {}
public function index(Request $request)
{
$orders = $this->orderRepository->filter($request->merge(['page' => $request->get('page', 1)])->all(), ['payment', 'customer', 'invoice']);
$title = 'List all orders';
return view('administrator.pages.order.index', compact('title', 'orders'));
return view('administrator.pages.order.index', compact('title'));
}
// Tính billing
@@ -261,12 +260,12 @@ class OrderController extends Controller
public function create()
{
$title = 'Add new Order for Customer';
$customer = Customer::select('id', 'firstname', 'lastname')->where('status', 1)->get();
$customer = Customer::select('id', 'fullname')->where('status', 1)->get();
$payment = Payment::select('id', 'name')->where('status', 1)->get();
$discount = Discount::select('id', 'code', 'save', 'type')->where('status', 1)->get();
$type = Type::select('id', 'name')->where('status', 1)->get();
// $type = Type::select('id', 'name')->where('status', 1)->get();
return view('administrator.pages.order.add', compact('title', 'customer', 'payment', 'discount', 'type'));
return view('administrator.pages.order.add', compact('title', 'customer', 'payment', 'discount'));
}
public function edit(int $id = 0)
@@ -407,4 +406,43 @@ class OrderController extends Controller
return back()->with('success', 'Delete Success');
}
public function datatable(Request $request)
{
$query = $this->orderRepository->filter(
$request->all(),
['payment', 'customer', 'invoice'],
[],
['*'],
true
);
return DataTables::eloquent($query)
->addColumn('order_num', function ($d) {
return view('administrator.pages.order.datatable.order_num', ['row' => $d])->render();
})
->addColumn('date', function ($d) {
return view('administrator.pages.order.datatable.date', ['row' => $d])->render();
})
->addColumn('customer', function ($d) {
return view('administrator.pages.order.datatable.customer', ['row' => $d])->render();
})
->addColumn('payment', function ($d) {
return view('administrator.pages.order.datatable.payment', ['row' => $d])->render();
})
->addColumn('amount', function ($d) {
return view('administrator.pages.order.datatable.amount', ['row' => $d])->render();
})
->addColumn('invoice_status', function ($d) {
return view('administrator.pages.order.datatable.invoice_status', ['row' => $d])->render();
})
->addColumn('status', function ($d) {
return view('administrator.pages.order.datatable.status', ['row' => $d])->render();
})
->addColumn('action', function ($d) {
return view('administrator.pages.order.datatable.action', ['row' => $d])->render();
})
->rawColumns(['order_num', 'date', 'customer', 'payment', 'amount', 'invoice_status', 'status', 'action'])
->make(true);
}
}
@@ -16,8 +16,12 @@ class OrderCachedRepository extends BaseCachedRepository implements OrderReposit
{
return $this->orderRepository->getModel();
}
public function filter(array $data = [], array $relationships = [], array $withCount = [], array $select = ['*'])
public function filter(array $data = [], array $relationships = [], array $withCount = [], array $select = ['*'], bool $returnQuery = false)
{
if ($returnQuery) {
return $this->orderRepository->filter($data, $relationships, $withCount, $select, true);
}
$cacheKey = $this->getCacheKey(md5(json_encode([
'filterItem' => [
'data' => $data,
+6 -1
View File
@@ -12,7 +12,7 @@ class OrderRepository extends BaseRepository implements OrderRepositoryInterface
{
return Order::class;
}
public function filter(array $data = [], array $relationships = [], array $withCount = [], array $select = ['*'])
public function filter(array $data = [], array $relationships = [], array $withCount = [], array $select = ['*'], bool $returnQuery = false)
{
$model = $this->model->with($relationships)->select($select);
if (isset($data['client']) && ! empty($data['client'])) {
@@ -66,6 +66,11 @@ class OrderRepository extends BaseRepository implements OrderRepositoryInterface
if (count($withCount) > 0) {
$model = $model->withCount($withCount);
}
if ($returnQuery) {
return $model;
}
if (isset($data['limit']) && $data['limit']) {
return $model->latest('id')->take($data['limit'])->get();
}
@@ -4,7 +4,7 @@ namespace App\Repositories\Order;
use App\Repositories\BaseRepositoryInterface;
interface OrderRepositoryInterface extends BaseRepositoryInterface{
public function filter(array $data = [],array $relationships = [],array $withCount = [],array $select = ['*']);
public function filter(array $data = [],array $relationships = [],array $withCount = [],array $select = ['*'], bool $returnQuery = false);
public function findWithRelationships(int $id = 0, array $relationships = [],array $withCount = [], array $withSum = []);
public function updateBy(string $key = '',string|int $value = '',array $data =[]);
}
+3
View File
@@ -15,10 +15,13 @@ return [
],
'static' => [
'css' => [
'build/plugins/select2/select2.min.css',
'build/plugins/perfect-scrollbar/perfect-scrollbar.css',
],
'js' => [
'build/plugins/jquery/jquery.min.js',
'build/plugins/bootstrap/bootstrap.bundle.min.js',
'build/plugins/select2/select2.min.js',
'build/plugins/lucide/lucide.min.js',
'build/plugins/perfect-scrollbar/perfect-scrollbar.min.js',
],
+4 -4
View File
@@ -315,9 +315,9 @@ jQuery(function ($) {
});
var initSelect2 = function () {
$(".select2.single__select").select2({
allowClear: true,
width: "100%",
height: "100%",
$('.select2.single__select').select2({
allowClear: false,
width: '100%',
height: '100%',
});
};
@@ -76,13 +76,20 @@
<!-- Global Select2 initialization -->
<script>
window.initSelect2 = function() {
$(".select2.single__select").select2({
allowClear: true,
width: "100%",
height: "100%",
$(".select2").each(function () {
if (!$(this).hasClass('select2-hidden-accessible')) {
$(this).select2({
allowClear: false,
width: "100%",
});
}
});
};
$(document).ready(function () {
window.initSelect2();
});
// Global ModalManager initialization
document.addEventListener('DOMContentLoaded', function() {
if (typeof ModalManager !== 'undefined') {
@@ -99,7 +106,7 @@
<x-modal-confirm-delete />
@stack('custom-scripts')
<script type="text/javascript">
<script type="text/javascript">
var apiMedia = '{{ route('api.GetAllImage') }}';
var apiUpload = '{{ route('media.upload') }}';
</script>
@@ -1,35 +1,42 @@
@extends("administrator.layout.master")
@section("content")
@php use App\Enums\Product\ProductTypeEnums; @endphp
@extends('administrator.layout.master')
@section('breadcrumb')
@php
$breadcrumbItems = [
['label' => 'Order'],
['label' => 'Order Management', 'url' => route('administrator.pages.order.index')],
['label' => 'Add New Order', 'active' => true],
];
@endphp
<x-admin-breadcrumb :items="$breadcrumbItems" />
@endsection
@section('content')
@if(auth()->guard('admins')->user()->can("add order"))
<div class="card card-outline card-primary">
<form action="{{ route('administrator.pages.order.store') }}" method="post">
@csrf
<div class="card-header p-0 border-bottom-0">
<ul class="nav nav-tabs" id="custom-tabs-four-tab" role="tablist">
<li class="nav-item">
<a class="nav-link active" data-toggle="pill"
href="#detail" role="tab"
aria-controls="detail" aria-selected="true">Customer Information</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill"
href="#product" role="tab"
aria-controls="product" aria-selected="false">Product Service</a>
</li>
</ul>
</div>
<div class="card-body">
<div class="tab-content" id="custom-tabs-four-tabContent">
<div class="tab-pane fade active show"
id="detail" role="tabpanel"
aria-labelledby="detail">
<div class="card-body">
{{--Client User--}}
<div class="form-group row">
<label class="col-md-4" for="customer_id">Client User</label>
<div class="col-md-8">
<select class="form-control select2" name="customer_id" id="customer_id"
style="width: 100%">
<form action="{{ route('administrator.pages.order.store') }}" method="post">
@csrf
<div class="row align-items-start">
<div class="col-md-8">
<div class="card card-outline card-primary">
<div class="card-header bg-white">
<ul class="nav nav-tabs" id="custom-tabs-four-tab" role="tablist">
<li class="nav-item">
<a class="nav-link active" data-bs-toggle="tab" href="#detail" role="tab"
aria-controls="detail" aria-selected="true">Customer Information</a>
</li>
<li class="nav-item">
<a class="nav-link" data-bs-toggle="tab" href="#product" role="tab" aria-controls="product"
aria-selected="false">Product Service</a>
</li>
</ul>
</div>
<div class="card-body">
<div class="tab-content" id="custom-tabs-four-tabContent">
<div class="tab-pane fade active show" id="detail" role="tabpanel" aria-labelledby="detail">
<div class="form-group mb-3">
<label for="customer_id">Client User</label>
<select class="form-control select2" name="customer_id" id="customer_id">
@if($customer->count())
@foreach($customer->all() as $item)
<option value="{{ $item->id }}">
@@ -39,113 +46,78 @@
@endif
</select>
</div>
</div>
{{--Payment Method--}}
<div class="form-group row">
<label class="col-md-4" for="payment_id">Payment Method</label>
<div class="col-md-8">
<select class="form-control" name="payment_id" id="payment_id">
<div class="form-group mb-3">
<label for="payment_id">Payment Method</label>
<select class="form-control select2" name="payment_id" id="payment_id">
@if($payment->count())
@foreach($payment->all() as $item)
<option value="{{ $item->id }}">
{{ $item->name }}
</option>
<option value="{{ $item->id }}">{{ $item->name }}</option>
@endforeach
@endif
</select>
</div>
</div>
{{--Promotion Code--}}
<div class="form-group row">
<label class="col-md-4" for="discount_id">Promotion Code</label>
<div class="col-md-8">
<select class="form-control" name="discount_id" id="discount_id">
<div class="form-group mb-3">
<label for="discount_id">Promotion Code</label>
<select class="form-control select2" name="discount_id" id="discount_id">
<option value="">--------</option>
@if($discount->count())
@foreach($discount->all() as $item)
<option value="{{ $item->id }}">
{{ $item->code }}
</option>
<option value="{{ $item->id }}">{{ $item->code }}</option>
@endforeach
@endif
</select>
</div>
</div>
{{--Orders Status--}}
<div class="form-group row">
<label class="col-md-4" for="status">Orders Status</label>
<div class="col-md-8">
<select class="form-control" name="status" id="status">
<div class="form-group mb-3">
<label for="status">Orders Status</label>
<select class="form-control select2" name="status" id="status">
<option value="0">Pending</option>
<option value="1">Active</option>
</select>
</div>
</div>
{{--Orders Action--}}
<div class="form-group row">
<label class="col-md-4" for="status">Orders Status</label>
<div class="col-md-8 form-group row">
<div class="col align-items-center d-flex">
<label class="mr-2" for="Invoice">Create Invoice</label>
<input type="checkbox" name="create_invoice" checked id="Invoice">
<div class="form-group mb-3">
<div class="form-check">
<input type="checkbox" name="create_invoice" id="create_invoice"
class="form-check-input" value="1" checked>
<label class="form-check-label" for="create_invoice">
Create Invoice
</label>
</div>
</div>
</div>
</div>
</div>
<div class="tab-pane fade"
id="product"
role="tabpanel"
aria-labelledby="product">
<div class="row">
<div class="col-md-8">
<div class="card-body append-new__product">
<div class="box clients-summary__box p-4">
{{--Product Type--}}
<div class="row form-group">
<label for="order_product_type" class="col-md-4">Product Type
(*)</label>
<div class="col-md-8">
<select class="form-control order_product_type"
data-append="product[0][product_id]"
name="product[0][type]">
<option value="0">-----------</option>
@if($type->count())
@foreach($type->all() as $item)
<option value="{{ $item->id }}">{{ $item->name }}</option>
@endforeach
@endif
<div class="tab-pane fade" id="product" role="tabpanel" aria-labelledby="product">
<div class="append-new__product mb-3">
<div class="border rounded p-3 mb-3">
<div class="row">
<div class="col-md-6 mb-3">
<label>Product Type (*)</label>
<select class="form-control select2 order_product_type"
data-append="product[0][product_id]" name="product[0][type]"
id="product_type">
<option value="">-----------</option>
@foreach(ProductTypeEnums::cases() as $type)
<option value="{{ $type->value }}">{{ $type->label() }}</option>
@endforeach
</select>
</div>
</div>
{{--Product--}}
<div class="row form-group">
<label for="product_id" class="col-md-4">Product (*)</label>
<div class="col-md-8">
<select class="form-control product_id"
name="product[0][product_id]">
<option value="0">-----------</option>
<div class="col-md-6 mb-3">
<label>Product (*)</label>
<select class="form-control select2 product_id"
name="product[0][product_id]" id="product_id">
<option value="">-----------</option>
</select>
</div>
</div>
{{--Domain--}}
<div class="row form-group">
<label for="Domain" class="col-md-4">Domain</label>
<div class="col-md-8">
<input type="text" class="form-control Domain"
name="product[0][domain]"
value="">
<div class="col-md-6 mb-3">
<label>Domain</label>
<input type="text" class="form-control" name="product[0][domain]" value="">
</div>
</div>
{{--Billing Cycle--}}
<div class="row form-group">
<label for="billing" class="col-md-4">Billing Cycle (*)</label>
<div class="col-md-8">
<select class="form-control billing" name="product[0][billing]">
<div class="col-md-6 mb-3">
<label>Billing Cycle (*)</label>
<select class="form-control select2" name="product[0][billing]">
<option value="0">Free</option>
<option value="1">One Time</option>
<option value="2" selected>Monthly</option>
@@ -154,67 +126,58 @@
<option value="5">Annually</option>
</select>
</div>
</div>
{{--Product Quantity--}}
<div class="row form-group">
<label for="quantity" class="col-md-4">Quantity (*)</label>
<div class="col-md-8">
<input type="number" class="form-control quantity"
name="product[0][quantity]"
value="1" min="1">
<div class="col-md-6 mb-3">
<label>Quantity (*)</label>
<input type="number" class="form-control" name="product[0][quantity]"
value="1" min="1">
</div>
</div>
{{--Product Price--}}
<div class="row form-group">
<label for="price_custom" class="col-md-4">Price Override</label>
<div class="col-md-8">
<input type="number" class="form-control price_custom"
name="product[0][price_custom]" value="" min="1">
<div class="col-md-6 mb-3">
<label>Price Override</label>
<input type="number" class="form-control" name="product[0][price_custom]"
value="" min="1">
</div>
</div>
</div>
</div>
<div class="card-footer">
<a href="javascript:void(0)"
class="btn btn-outline-primary btn-add__newProduct">Add
new Product</a>
</div>
</div>
<div class="col-md-4">
<div class="clients-summary__box">
<h4 class="title">Order Summary</h4>
<!--Box info-->
<div class="summary__box">
<table class="table table-borderless">
<tbody class="append-element__js">
</tbody>
<tfoot>
<tr class="tax">
<td class="fs-20">VAT @ 10.00%</td>
<td></td>
<td class="text-right fs-20" id="tax_append">0đ</td>
</tr>
<tr class="total">
<td class="fs-20">Total</td>
<td></td>
<td class="text-right fs-20" id="total_append">0đ</td>
</tr>
</tfoot>
</table>
</div>
</div>
<button type="button" class="btn btn-outline-primary btn-add__newProduct">
<i class="fas fa-plus"></i> Add new Product
</button>
</div>
</div>
</div>
</div>
</div>
<div class="card-footer text-right">
<a href="{{ route('administrator.pages.order.index') }}" class="btn bg-gradient-secondary">Cancel</a>
<button type="submit" class="btn bg-gradient-primary">Confirm Order</button>
<div class="col-md-4">
<div class="card card-outline card-primary">
<div class="card-header bg-white">
<h5 class="card-title m-0">Order Summary</h5>
</div>
<div class="card-body">
<table class="table table-borderless">
<tbody class="append-element__js"></tbody>
<tfoot>
<tr class="tax">
<td>VAT @ 10.00%</td>
<td class="text-end" id="tax_append">0đ</td>
</tr>
<tr class="total">
<td><strong>Total</strong></td>
<td class="text-end" id="total_append">0đ</td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</form>
</div>
</div>
<x-fixed-action-bar>
<x-button-crm type="button" variant="secondary" size="sm" icon="arrow-left"
route="administrator.pages.order.index">Cancel</x-button-crm>
<x-button-crm type="submit" variant="primary" size="sm" icon="check-circle">Confirm Order</x-button-crm>
</x-fixed-action-bar>
</form>
@else
<div class="alert alert-danger alert-dismissible">
<h5 class="mb-0"><i class="icon fas fa-ban"></i> Access Denied - You are not assigned to any Order
@@ -222,9 +185,9 @@
</div>
@endif
@endsection
@push('scripts')
<script type="text/javascript">
const apiGetProduct = '{{ route('api.getProduct') }}';
const apiGetProductType = '{{route('api.getProductType')}}';
</script>
@endpush
@push('custom-scripts')
@foreach (config('assets.datatable.js') as $datatable)
<script src="{{ asset($datatable) }}"></script>
@endforeach
@endpush
@@ -0,0 +1,47 @@
<div class="dt-action-dropdown dropdown">
<button class="btn btn-sm btn-light d-flex align-items-center gap-1" type="button" data-bs-toggle="dropdown"
aria-expanded="false">
<i data-lucide="more-vertical" width="14" height="14"></i>
</button>
<ul class="dropdown-menu dropdown-menu-end">
<li>
<a class="dropdown-item" href="{{ route('administrator.pages.order.edit', ['id' => $row->id]) }}">
<i data-lucide="pencil" width="14" height="14" class="me-2"></i>
View
</a>
</li>
@if(auth()->guard('admins')->user()->can("delete order"))
<li>
<hr class="dropdown-divider">
<button type="button" class="dropdown-item text-danger" data-bs-toggle="modal" data-bs-target="#deleteModal{{ $row->id }}">
<i data-lucide="trash-2" width="14" height="14" class="me-2 text-danger"></i>
Delete
</button>
</li>
@endif
</ul>
</div>
<div class="modal fade" id="deleteModal{{ $row->id }}" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<form action="{{ route('administrator.pages.order.destroy') }}" method="POST" class="d-inline">
@csrf
@method('DELETE')
<input type="hidden" name="order" value="{{ $row->id }}">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Xoá đơn hàng</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Bạn có chắc chắn muốn xoá đơn hàng này?
<strong>{{ $row->order_num }}</strong>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Huỷ</button>
<button type="submit" class="btn btn-danger">Xoá</button>
</div>
</div>
</form>
</div>
</div>
@@ -0,0 +1 @@
{{ number_format($row->amount, 0, ',', '.') }}đ
@@ -0,0 +1 @@
{{ $row->customer->firstname . ' ' . $row->customer->lastname }}
@@ -0,0 +1 @@
@time($row->date)
@@ -0,0 +1,3 @@
@if ($row->invoice_id !== 0)
{!! $row->invoice->getStatus() !!}
@endif
@@ -0,0 +1,3 @@
<a href="{{ route('administrator.pages.order.edit', ['id' => $row->id]) }}" title="View Order">
{{ $row->order_num }}
</a>
@@ -0,0 +1 @@
{{ $row->payment->name ?? 'VN Pay' }}
@@ -0,0 +1 @@
{!! \App\Http\Helpers\Helper::OrderStatus($row->status) !!}
@@ -1,181 +1,201 @@
@php use Carbon\Carbon; @endphp
@extends("administrator.layout.master")
@section("content")
@extends('administrator.layout.master')
@section('breadcrumb')
@php
$breadcrumbItems = [
['label' => 'Order'],
['label' => 'Order Management', 'url' => route('administrator.pages.order.index')],
['label' => 'View Order', 'active' => true],
];
@endphp
<x-admin-breadcrumb :items="$breadcrumbItems" />
@endsection
@section('content')
@if(auth()->guard('admins')->user()->can("edit order"))
<div class="card card-outline card-primary">
<div class="card-body">
<div class="row form-group">
<table class="form" width="100%" border="0" cellspacing="2" cellpadding="3">
<tbody>
<tr>
<td class="fieldlabel">Date</td>
<td class="fieldarea">{{ Carbon::parse($order->date)->format("d/m/Y H:i:s") }}</td>
<td width="15%" class="fieldlabel">Payment Method</td>
<td class="fieldarea">{{ $order->payment->name ?? 'VN Pay' }}</td>
</tr>
<tr>
<td width="15%" class="fieldlabel">Order #</td>
<td class="fieldarea">{{ $order->order_num }} (ID: {{$order->id}})</td>
<td class="fieldlabel">Amount</td>
<td class="fieldarea">@money($order->amount) đ</td>
</tr>
<tr>
<td class="fieldlabel">Client</td>
<td class="fieldarea">
<a href="{{ route('customer.info',['userid' => $order->customer->id]) }}">{{ $order->customer->firstname . ' ' . $order->customer->lastname }}</a>
<br>
{{ $order->customer->address }}
</td>
<td class="fieldlabel">Invoice #</td>
<td class="fieldarea">{{ $order->invoice_id !== 0 ? $order->invoice_id : "No Invoice" }}</td>
</tr>
<tr>
<td class="fieldlabel">Status</td>
<td class="fieldarea">{!! App\Http\Helpers\Helper::OrderStatus($order->status) !!}</td>
<td class="fieldlabel">IP Address</td>
<td class="fieldarea">
{{ $order->client_ip }}
</td>
</tr>
<tr>
<td class="fieldlabel">Order Placed By</td>
<td class="fieldarea">
@if($order->user)
{{ $order->user->username }} (#ID: {{ $order->user->id }})
<em>{{ $order->user->email }}</em>
@endif
</td>
<td class="fieldlabel">Promotion Code</td>
<td class="fieldarea">
@if($order->discount)
{{ $order->discount->code }}
@endif
</td>
</tr>
</tbody>
</table>
</div>
<div class="row form-group">
<div class="col-md-12">
<h3 class="mb-3">Order Item</h3>
<table class="table table-invoice table-bordered">
<thead>
<tr>
<th>Item</th>
<th>Description</th>
<th>Billing Cycle</th>
<th>Amount</th>
<th style="width: 40px">Status</th>
<th>Payment Status</th>
</tr>
</thead>
<tbody>
@if($order->orderItem->isNotEmpty())
@foreach($order->orderItem->all() as $item)
<form action="{{ route('administrator.pages.order.update', ['id' => $order->id]) }}" method="post">
@csrf
@method('PUT')
<input type="hidden" name="module" value="1">
<div class="row align-items-start">
<div class="col-md-8">
<div class="card card-outline card-primary">
<div class="card-header bg-white">
<h5 class="card-title m-0">Order Information</h5>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-borderless">
<tbody>
<tr>
<td class="text-center">
@if($item->type && in_array($item->Type->id,[3,4]))
<a href="{{ route('customer.product',['userid' => $item->customer_id,'product' =>$item->relid,'type' => $item->type_id ]) }}">
{{ $item->type->name }}
</a>
@else
{{ $item->type->name }}
@endif
</td>
<td>
{{ $item->description }}
</td>
<td class="text-center">
{{ Helper::billing_cycle($item->billing) }}
</td>
<td class="text-center">
@money($item->amount) đ
</td>
<td class="text-center">
@if($item->status)
{!! $item->status->getStatus() !!}
@endif
</td>
<td class="text-center">
@if($order->invoice_id !== 0)
{!! $order->invoice->getStatus() !!}
@else
No Invoice Due
@endif
</td>
<td class="text-muted" style="width: 150px;">Date</td>
<td>{{ Carbon::parse($order->date)->format("d/m/Y H:i:s") }}</td>
<td class="text-muted" style="width: 150px;">Payment Method</td>
<td>{{ $order->payment->name ?? 'VN Pay' }}</td>
</tr>
@endforeach
@endif
</tbody>
</table>
</div>
</div>
@if( $order->status !== 1)
<div class="row mt-2 form-group">
<div class="col-md-12">
<label class="box-input__checker">
<span>Auto Create Product (Hosting/VPS)</span>
<input type="checkbox" name="module_checker" checked="checked">
<span class="checkmark"></span>
</label>
<tr>
<td class="text-muted">Order #</td>
<td>{{ $order->order_num }} (ID: {{ $order->id }})</td>
<td class="text-muted">Amount</td>
<td>@money($order->amount) đ</td>
</tr>
<tr>
<td class="text-muted">Client</td>
<td>
<a href="{{ route('customer.info', ['userid' => $order->customer->id]) }}">
{{ $order->customer->firstname . ' ' . $order->customer->lastname }}
</a>
<br>
<small class="text-muted">{{ $order->customer->address }}</small>
</td>
<td class="text-muted">Invoice #</td>
<td>{{ $order->invoice_id !== 0 ? $order->invoice_id : "No Invoice" }}</td>
</tr>
<tr>
<td class="text-muted">Status</td>
<td>{!! App\Http\Helpers\Helper::OrderStatus($order->status) !!}</td>
<td class="text-muted">IP Address</td>
<td>{{ $order->client_ip }}</td>
</tr>
<tr>
<td class="text-muted">Order Placed By</td>
<td>
@if($order->user)
{{ $order->user->username }} (#ID: {{ $order->user->id }})
<br>
<small class="text-muted">{{ $order->user->email }}</small>
@endif
</td>
<td class="text-muted">Promotion Code</td>
<td>{{ $order->discount?->code }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
@endif
<div class="card card-outline card-primary">
<div class="card-header bg-white">
<h5 class="card-title m-0">Order Item</h5>
</div>
<div class="card-body p-0">
<table class="table table-invoice table-bordered mb-0">
<thead>
<tr>
<th>Item</th>
<th>Description</th>
<th>Billing Cycle</th>
<th>Amount</th>
<th style="width: 100px">Status</th>
<th style="width: 120px">Payment Status</th>
</tr>
</thead>
<tbody>
@if($order->orderItem->isNotEmpty())
@foreach($order->orderItem->all() as $item)
<tr>
<td class="text-center">
@if($item->type && in_array($item->Type->id, [3, 4]))
<a href="{{ route('customer.product', ['userid' => $item->customer_id, 'product' => $item->relid, 'type' => $item->type_id]) }}">
{{ $item->type->name }}
</a>
@else
{{ $item->type->name }}
@endif
</td>
<td>{{ $item->description }}</td>
<td class="text-center">{{ Helper::billing_cycle($item->billing) }}</td>
<td class="text-center">@money($item->amount) đ</td>
<td class="text-center">
@if($item->status)
{!! $item->status->getStatus() !!}
@endif
</td>
<td class="text-center">
@if($order->invoice_id !== 0)
{!! $order->invoice->getStatus() !!}
@else
No Invoice Due
@endif
</td>
</tr>
@endforeach
@endif
</tbody>
</table>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card card-outline card-primary">
<div class="card-header bg-white">
<h5 class="card-title m-0">Order Actions</h5>
</div>
<div class="card-body">
@if($order->status !== 1)
<div class="form-group mb-3">
<label class="box-input__checker">
<span>Auto Create Product (Hosting/VPS)</span>
<input type="checkbox" name="module_checker" checked>
<span class="checkmark"></span>
</label>
</div>
@endif
<div class="d-flex flex-column gap-2">
@if($order->status !== 1)
<x-button-crm type="submit" name="action" value="accept" variant="success" icon="check-circle">
Accept Order
</x-button-crm>
@endif
<x-button-crm type="submit" name="action" value="cancel" variant="secondary" icon="x-circle">
Cancel Order
</x-button-crm>
@if(auth()->guard('admins')->user()->can("delete order"))
<form method="POST" action="{{ route('administrator.pages.order.destroy') }}" class="d-inline">
@csrf
@method('DELETE')
<input type="hidden" name="order" value="{{ $order->id }}">
<x-button-crm type="submit" variant="danger" icon="trash-2">
Delete Order
</x-button-crm>
</form>
@endif
</div>
</div>
</div>
</div>
</div>
<div class="card-footer text-center">
<form
onclick=" {{ $order->status === 1 ? "return false;" : "" }}"
class="d-lg-inline"
action="{{ route('administrator.pages.order.update',['id' => $order->id,'action' => 'accept']) }}"
method="post">
@method('put')
@csrf
<input type="hidden" name="module" value="1">
<button type="submit"
class="btn {{ $order->status === 1 ? "disabled" : "" }} bg-gradient-success">
<i class="far fa-check-circle"></i>
Accept Order
</button>
</form>
<form class="d-lg-inline"
action="{{ route('administrator.pages.order.update',['id' => $order->id,'action' => 'cancel']) }}"
method="post">
@method('put')
@csrf
<button type="submit"
class="btn bg-gradient-secondary">Cancel Order
</button>
</form>
<form class="d-lg-inline" action="{{ route('administrator.pages.order.destroy',['id' => $order->id]) }}"
method="post">
@method('delete')
@csrf
<button type="submit"
class="btn bg-gradient-danger">Delete Order
</button>
</form>
<a href="{{ route('administrator.pages.order.index') }}" class="btn bg-gradient-secondary">
Back
</a>
</div>
</div>
<x-fixed-action-bar>
<x-button-crm type="button" variant="secondary" size="sm" icon="arrow-left"
route="administrator.pages.order.index">Back</x-button-crm>
</x-fixed-action-bar>
</form>
@else
<div class="alert alert-danger alert-dismissible">
<h5 class="mb-0"><i class="icon fas fa-ban"></i> Access Denied - You are not assigned to any Order
management department</h5>
</div>
@endif
@endsection
@push("scripts")
<script type="text/javascript">
$('.box-input__checker span').click(function () {
let inputModule = $('input[name="module"][type="hidden"]');
$('input[name="module_checker"]').prop('checked') ?
inputModule.val(0) :
inputModule.val(1)
@push('custom-scripts')
<script>
document.addEventListener('DOMContentLoaded', function() {
const moduleChecker = document.querySelector('input[name="module_checker"]');
const moduleInput = document.querySelector('input[name="module"]');
if (moduleChecker && moduleInput) {
moduleChecker.addEventListener('change', function() {
moduleInput.value = this.checked ? '0' : '1';
});
}
});
</script>
@endpush
@@ -1,194 +1,43 @@
@php use App\Http\Helpers\Helper; @endphp
@extends("administrator.layout.master")
@section("content")
@if(auth()->guard('admins')->user()->can("manager order"))
<div class="card card-primary card-outline">
<div class="card-header">
<form action="{{ route('administrator.pages.order.index') }}" method="get">
<div class="row form-group mb-0">
<div class="col-md-3">
<div class="form-group">
<label for="inputName">
Order ID </label>
<input type="number" name="order_id" id="inputName" class="form-control"
value="{{ request()->order_id ?? "" }}">
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label for="order_num">
Order Num</label>
<input type="number" name="order_num" id="order_num" class="form-control"
value="{{ request()->order_num ?? "" }}">
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label for="order_amount">
Amount</label>
<input type="number" name="order_amount" id="order_amount" class="form-control"
value="{{ request()->order_amount ?? "" }}">
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label for="reservation">Date range:</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">
<i class="far fa-calendar-alt"></i>
</span>
</div>
<input type="text" class="form-control reservation float-right"
name="order_date"
value="{{ request()->order_date ?? "" }}"
id="reservation">
</div>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label for="paymentStatus">
Payment Status</label>
<select name="payment_status" class="form-control" id="paymentStatus">
<option value="full"
@selected(request()->payment_status === "full")>
Any
</option>
<option value="active"
@selected(request()->payment_status === "active")>
Paid
</option>
<option value="unpaid"
@selected(request()->payment_status === "unpaid")>
Unpaid
</option>
<option value="cancel"
@selected(request()->payment_status === "cancel")>
Cancel
</option>
</select>
</div>
</div>
<div class="col-md-3">
<x-form.customer :model="request()->get('client') ?? null"/>
</div>
<div class="col-md-3">
<div class="form-group">
<label for="inputStatus">
Status</label>
<select name="status" class="form-control" id="inputStatus">
<option value="full"
@selected(request()->status === "full")>
Any
</option>
<option value="active"
@selected(request()->status === "active")>
Active
</option>
<option value="pending"
@selected(request()->status === "pending")>
Pending
</option>
<option value="processing"
@selected(request()->status === "processing")>
Processing
</option>
<option value="cancel"
@selected(request()->status === "cancel")>
Cancel
</option>
</select>
</div>
</div>
<div class="col-md-3">
<label class="clear-search hidden">
@extends('administrator.layout.master')
@push('plugin-styles')
@foreach (config('assets.datatable.css') as $datatable)
<link href="{{ asset($datatable) }}" rel="stylesheet" />
@endforeach
@endpush
</label>
<button type="submit" class="form-control btn btn-block bg-gradient-primary">
<i class="fas fa-search"></i> Search
</button>
</div>
</div>
</form>
<span>{{ $orders->count() }} Records Found</span>
@section('breadcrumb')
@php
$breadcrumbItems = [
['label' => 'Order'],
['label' => 'Order Management'],
['label' => 'Order List', 'active' => true],
];
@endphp
<x-admin-breadcrumb :items="$breadcrumbItems" />
@endsection
@section('content')
@if(auth()->guard('admins')->user()->can("manager order"))
<div class="card card-primary card-outline rounded-4 shadow-none">
<div class="card-header bg-white d-flex justify-content-end gap-2 rounded-top-4">
<a href="{{ route('administrator.pages.order.create') }}" class="btn btn-primary btn-sm">
<i class="fas fa-plus"></i> Add New Order
</a>
</div>
<div class="card-body">
<table class="table table-invoice table-bordered">
<thead>
<tr>
<th style="width: 10px">
<label for=""></label><input type="checkbox" name="check" class="check-all" id="">
</th>
<th>Order #</th>
<th>Date</th>
<th>Client Name</th>
<th>Payment Method</th>
<th>Total</th>
<th>Payment Status</th>
<th>Status</th>
<th style="width: 40px"></th>
<th style="width: 40px"></th>
</tr>
</thead>
<tbody>
@if($orders->count())
@foreach($orders->all() as $item)
<tr>
<td class="text-center">
<input type="checkbox" name="id[]" id="" value="{{ $item->id }}">
</td>
<td class="text-center">
<a href="{{ route("administrator.pages.order.edit",['id' => $item->id]) }}"
title="View Order"> {{ $item->order_num }}</a>
</td>
<td class="text-center">
@time($item->date)
</td>
<td class="text-center">
{{ $item->customer->firstname . ' ' . $item->customer->lastname }}
</td>
<td class="text-center">
{{ $item->Payment->name ?? 'VN Pay' }}
</td>
<td class="text-center">
{{ number_format($item->amount,0,',','.') }}đ
</td>
<td class="text-center">
@if ($item->invoice_id !== 0)
{!! $item->invoice->getStatus() !!}
@endif
</td>
<td class="text-center">
{!! Helper::OrderStatus($item->status) !!}
</td>
<td class="text-center">
<a class="btn btn-warning btn-sm"
href="{{ route('administrator.pages.order.edit',['id' => $item->id ]) }}">
<i class="fas fa-search"></i>
</a>
</td>
<td class="text-center">
@if(auth()->guard('admins')->user()->can("delete order"))
<form method="post" class="d-inline"
action="{{ route('administrator.pages.order.destroy',['order' => $item->id]) }}">
@csrf
@method('delete')
<button type="submit" data-toggle="tooltip" data-placement="top" title=""
class="btn btn-sm btn-danger" data-original-title="Xoá">
<i class="fas fa-trash"></i>
</button>
</form>
@endif
</td>
</tr>
@endforeach
@endif
</tbody>
</table>
</div>
<div class="card-footer">
{{ $orders->withQueryString()->links() }}
<div class="card-body p-0">
@php
$orderColumns = [
['key' => 'order_num', 'label' => 'Order #'],
['key' => 'date', 'label' => 'Date'],
['key' => 'customer', 'label' => 'Client Name'],
['key' => 'payment', 'label' => 'Payment Method'],
['key' => 'amount', 'label' => 'Total'],
['key' => 'invoice_status', 'label' => 'Payment Status'],
['key' => 'status', 'label' => 'Status'],
['key' => 'action', 'label' => 'Action'],
];
@endphp
<x-datatable id="orderTable" ajax="{{ route('administrator.pages.order.datatable') }}" :columns="$orderColumns" />
</div>
</div>
@else
@@ -198,3 +47,8 @@
</div>
@endif
@endsection
@push('plugin-scripts')
@foreach (config('assets.datatable.js') as $datatable)
<script src="{{ asset($datatable) }}"></script>
@endforeach
@endpush
@@ -364,10 +364,6 @@ $breadcrumbItems = [
@endforeach
<script>
$(document).ready(function() {
if ($(".select2").length) {
$(".select2").select2();
}
// Toggle OS/Control Panel sections based on Product Type
function toggleProductSections() {
const productType = $('#product_type').val();
@@ -44,7 +44,7 @@
if ($('#operating_systems').length && !$('#operating_systems').hasClass('select2-hidden-accessible')) {
$('#operating_systems').select2({
placeholder: "Chọn hệ điều hành...",
allowClear: true,
allowClear: false,
width: '100%',
theme: 'default'
});
+1
View File
@@ -373,6 +373,7 @@ Route::prefix('')->group(function () {
Route::get('view-order/{id}', 'edit')->name('administrator.pages.order.edit');
Route::put('view-order/{id}', 'update')->name('administrator.pages.order.update');
Route::delete('remove-order', 'destroy')->name('administrator.pages.order.destroy');
Route::get('order-datatable', 'datatable')->name('administrator.pages.order.datatable');
});
//Task