Merge pull request #214 from j122j/voucher-users
Shows who redeemed vouchers
This commit is contained in:
commit
0ddeadfd27
|
@ -4,6 +4,7 @@ namespace App\Http\Controllers\Admin;
|
|||
|
||||
use App\Events\UserUpdateCreditsEvent;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\User;
|
||||
use App\Models\Voucher;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
|
@ -115,6 +116,13 @@ class VoucherController extends Controller
|
|||
return redirect()->back()->with('success', 'voucher has been removed!');
|
||||
}
|
||||
|
||||
public function users(Voucher $voucher)
|
||||
{
|
||||
return view('admin.vouchers.users', [
|
||||
'voucher' => $voucher
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
|
@ -157,6 +165,23 @@ class VoucherController extends Controller
|
|||
]);
|
||||
}
|
||||
|
||||
public function usersDataTable(Voucher $voucher)
|
||||
{
|
||||
$users = $voucher->users();
|
||||
|
||||
return datatables($users)
|
||||
->editColumn('name', function (User $user) {
|
||||
return '<a class="text-info" target="_blank" href="' . route('admin.users.show', $user->id) . '">' . $user->name . '</a>';
|
||||
})
|
||||
->addColumn('credits', function (User $user) {
|
||||
return '<i class="fas fa-coins mr-2"></i> ' . $user->credits();
|
||||
})
|
||||
->addColumn('last_seen', function (User $user) {
|
||||
return $user->last_seen ? $user->last_seen->diffForHumans() : '';
|
||||
})
|
||||
->rawColumns(['name', 'credits', 'last_seen'])
|
||||
->make();
|
||||
}
|
||||
public function dataTable()
|
||||
{
|
||||
$query = Voucher::query();
|
||||
|
@ -164,6 +189,7 @@ class VoucherController extends Controller
|
|||
return datatables($query)
|
||||
->addColumn('actions', function (Voucher $voucher) {
|
||||
return '
|
||||
<a data-content="Users" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.vouchers.users', $voucher->id) . '" class="btn btn-sm btn-primary mr-1"><i class="fas fa-users"></i></a>
|
||||
<a data-content="Edit" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.vouchers.edit', $voucher->id) . '" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
|
||||
|
||||
<form class="d-inline" onsubmit="return submitResult();" method="post" action="' . route('admin.vouchers.destroy', $voucher->id) . '">
|
||||
|
|
|
@ -1,240 +0,0 @@
|
|||
@extends('layouts.main')
|
||||
|
||||
@section('content')
|
||||
<!-- CONTENT HEADER -->
|
||||
<section class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1>Products</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="{{route('home')}}">Dashboard</a></li>
|
||||
<li class="breadcrumb-item"><a href="{{route('admin.users.index')}}">Products</a></li>
|
||||
<li class="breadcrumb-item"><a class="text-muted"
|
||||
href="{{route('admin.products.show' , $product->id)}}">Show</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- END CONTENT HEADER -->
|
||||
|
||||
<!-- MAIN CONTENT -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between">
|
||||
<h5 class="card-title"><i class="fas fa-sliders-h mr-2"></i>Product</h5>
|
||||
<div class="ml-auto">
|
||||
<a data-content="Edit" data-trigger="hover" data-toggle="tooltip" href="{{ route('admin.products.edit', $product->id) }}" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
|
||||
<form class="d-inline" onsubmit="return submitResult();" method="post" action="{{ route('admin.products.destroy', $product->id) }}">
|
||||
{{ csrf_field() }}
|
||||
{{ method_field("DELETE") }}
|
||||
<button data-content="Delete" data-trigger="hover" data-toggle="tooltip" class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>ID</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->id}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>Name</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->name}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>Price</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
<i class="fas fa-coins mr-1"></i>{{$product->price}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>Memory</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->memory}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>CPU</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->cpu}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>Swap</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->swap}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>Disk</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->disk}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>IO</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->io}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>Databases</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->databases}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>Allocations</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->allocations}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>Created At</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->created_at ? $product->created_at->diffForHumans() : ''}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>Description</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span class="d-inline-block text-truncate">
|
||||
{{$product->description}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>Updated At</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->updated_at ? $product->updated_at->diffForHumans() : ''}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title"><i class="fas fa-server mr-2"></i>Servers</h5>
|
||||
</div>
|
||||
<div class="card-body table-responsive">
|
||||
|
||||
@include('admin.servers.table' , ['filter' => '?product=' . $product->id])
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<!-- END CUSTOM CONTENT -->
|
||||
</div>
|
||||
</section>
|
||||
<!-- END CONTENT -->
|
||||
|
||||
|
||||
|
||||
@endsection
|
93
resources/views/admin/vouchers/users.blade.php
Normal file
93
resources/views/admin/vouchers/users.blade.php
Normal file
|
@ -0,0 +1,93 @@
|
|||
@extends('layouts.main')
|
||||
|
||||
@section('content')
|
||||
<!-- CONTENT HEADER -->
|
||||
<section class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1>Vouchers</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="{{ route('home') }}">Dashboard</a></li>
|
||||
<li class="breadcrumb-item"><a href="{{ route('admin.vouchers.index') }}">Vouchers</a></li>
|
||||
<li class="breadcrumb-item"><a class="text-muted"
|
||||
href="{{ route('admin.vouchers.users', $voucher->id) }}">Users</a>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- END CONTENT HEADER -->
|
||||
|
||||
<!-- MAIN CONTENT -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
|
||||
<div class="card">
|
||||
|
||||
<div class="card-header">
|
||||
<div class="d-flex justify-content-between">
|
||||
<h5 class="card-title"><i class="fas fa-users mr-2"></i>Users</h5>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body table-responsive">
|
||||
|
||||
<table id="datatable" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Name</th>
|
||||
<th>Email</th>
|
||||
<th>{{ CREDITS_DISPLAY_NAME }}</th>
|
||||
<th>Last Seen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<!-- END CUSTOM CONTENT -->
|
||||
|
||||
</section>
|
||||
<!-- END CONTENT -->
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
$('#datatable').DataTable({
|
||||
processing: true,
|
||||
serverSide: true,
|
||||
stateSave: true,
|
||||
ajax: "{{ route('admin.vouchers.usersdatatable', $voucher->id) }}",
|
||||
columns: [{
|
||||
data: 'id'
|
||||
}, {
|
||||
data: 'name'
|
||||
},
|
||||
{
|
||||
data: 'email'
|
||||
},
|
||||
{
|
||||
data: 'credits'
|
||||
},
|
||||
{
|
||||
data: 'last_seen'
|
||||
},
|
||||
],
|
||||
fnDrawCallback: function(oSettings) {
|
||||
$('[data-toggle="popover"]').popover();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
@endsection
|
|
@ -119,6 +119,8 @@ Route::middleware(['auth', 'checkSuspended'])->group(function () {
|
|||
Route::resource('usefullinks', UsefulLinkController::class);
|
||||
|
||||
Route::get('vouchers/datatable', [VoucherController::class, 'datatable'])->name('vouchers.datatable');
|
||||
Route::get('vouchers/{voucher}/usersdatatable', [VoucherController::class, 'usersdatatable'])->name('vouchers.usersdatatable');
|
||||
Route::get('vouchers/{voucher}/users', [VoucherController::class, 'users'])->name('vouchers.users');
|
||||
Route::resource('vouchers', VoucherController::class);
|
||||
|
||||
Route::get('api/datatable', [ApplicationApiController::class, 'datatable'])->name('api.datatable');
|
||||
|
|
Loading…
Reference in a new issue