فهرست منبع

Added voucher system

AVMG20 4 سال پیش
والد
کامیت
a7f8d71f92

+ 142 - 0
app/Http/Controllers/Admin/VoucherController.php

@@ -0,0 +1,142 @@
+<?php
+
+namespace App\Http\Controllers\Admin;
+
+use App\Http\Controllers\Controller;
+use App\Models\Voucher;
+use Illuminate\Contracts\Foundation\Application;
+use Illuminate\Contracts\View\Factory;
+use Illuminate\Contracts\View\View;
+use Illuminate\Http\RedirectResponse;
+use Illuminate\Http\Request;
+use Illuminate\Http\Response;
+
+class VoucherController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return Application|Factory|View
+     */
+    public function index()
+    {
+        return view('admin.vouchers.index');
+    }
+
+    /**
+     * Show the form for creating a new resource.
+     *
+     * @return Application|Factory|View
+     */
+    public function create()
+    {
+        return view('admin.vouchers.create');
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     *
+     * @param Request $request
+     * @return RedirectResponse
+     */
+    public function store(Request $request)
+    {
+        $request->validate([
+            'memo' => 'sometimes|string|max:191',
+            'code' => 'required|string|alpha_dash|max:36',
+            'uses' => 'required|numeric|max:2147483647',
+            'credits' => 'required|numeric|between:0,99999999',
+            'expires_at' => 'required|date|after:today',
+        ]);
+
+        Voucher::create($request->except('_token'));
+
+        return redirect()->route('admin.vouchers.index')->with('success', 'voucher has been created!');
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param Voucher $voucher
+     * @return Response
+     */
+    public function show(Voucher $voucher)
+    {
+        //
+    }
+
+    /**
+     * Show the form for editing the specified resource.
+     *
+     * @param Voucher $voucher
+     * @return Response
+     */
+    public function edit(Voucher $voucher)
+    {
+        //
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param Request $request
+     * @param Voucher $voucher
+     * @return Response
+     */
+    public function update(Request $request, Voucher $voucher)
+    {
+        //
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param Voucher $voucher
+     * @return RedirectResponse
+     */
+    public function destroy(Voucher $voucher)
+    {
+        $voucher->delete();
+        return redirect()->back()->with('success', 'voucher has been removed!');
+    }
+
+    public function dataTable()
+    {
+        $query = Voucher::with(['users']);
+
+        return datatables($query)
+            ->addColumn('actions', function (Voucher $voucher) {
+                return '
+                            <a data-content="Show" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.vouchers.show', $voucher->id) . '" class="btn btn-sm text-white btn-warning mr-1"><i class="fas fa-eye"></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) . '">
+                            ' . csrf_field() . '
+                            ' . method_field("DELETE") . '
+                           <button data-content="Delete" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
+                       </form>
+                ';
+            })
+            ->addColumn('status', function (Voucher $voucher) {
+                $color = 'success';
+                if ($voucher->getStatus() != 'VALID') $color = 'danger';
+                return '<span class="badge badge-'.$color.'">'. $voucher->getStatus() .'</span>';
+            })
+            ->editColumn('uses', function (Voucher $voucher) {
+                $userCount = $voucher->users()->count();
+                return "{$userCount} / {$voucher->uses}";
+            })
+            ->editColumn('credits', function (Voucher $voucher) {
+                return number_format($voucher->credits, 2, '.', '');
+            })
+            ->editColumn('expires_at', function (Voucher $voucher) {
+                return $voucher->expires_at ? $voucher->expires_at->diffForHumans() : '';
+            })
+            ->editColumn('code' , function (Voucher $voucher) {
+                return "<code>{$voucher->code}</code>";
+            })
+            ->rawColumns(['actions' , 'code' , 'status'])
+            ->make();
+    }
+
+}

+ 57 - 0
app/Models/Voucher.php

@@ -0,0 +1,57 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Relations\BelongsToMany;
+
+/**
+ * Class Voucher
+ * @package App\Models
+ */
+class Voucher extends Model
+{
+    use HasFactory;
+
+    /**
+     * @var string[]
+     */
+    protected $fillable = [
+        'memo',
+        'code',
+        'credits',
+        'uses',
+        'expires_at',
+    ];
+
+    protected $dates = [
+        'expires_at'
+    ];
+
+    /**
+     *
+     */
+    public static function boot()
+    {
+        parent::boot();
+
+        static::deleting(function (Voucher $voucher) {
+            $voucher->users()->detach();
+        });
+    }
+
+    public function getStatus(){
+        if ($this->users()->count() >= $this->uses) return 'USES_LIMIT_REACHED';
+        if ($this->expires_at->isPast()) return 'EXPIRED';
+        return 'VALID';
+    }
+
+    /**
+     * @return BelongsToMany
+     */
+    public function users()
+    {
+        return $this->belongsToMany(User::class);
+    }
+}

+ 29 - 0
database/factories/VoucherFactory.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace Database\Factories;
+
+use App\Models\voucher;
+use Illuminate\Database\Eloquent\Factories\Factory;
+
+class VoucherFactory extends Factory
+{
+    /**
+     * The name of the factory's corresponding model.
+     *
+     * @var string
+     */
+    protected $model = voucher::class;
+
+    /**
+     * Define the model's default state.
+     *
+     * @return array
+     */
+    public function definition()
+    {
+        return [
+            'credits'    => $this->faker->numberBetween(100, 1000),
+            'expires_at' => $this->faker->dateTimeBetween(now(), '+30 days')
+        ];
+    }
+}

+ 36 - 0
database/migrations/2021_07_09_190453_create_vouchers_table.php

@@ -0,0 +1,36 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateVouchersTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('vouchers', function (Blueprint $table) {
+            $table->id();
+            $table->string('code', 36)->unique();
+            $table->string('memo')->nullable();
+            $table->unsignedFloat('credits', 10);
+            $table->unsignedInteger('uses')->default(1);
+            $table->timestamp('expires_at')->nullable();
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('vouchers');
+    }
+}

+ 32 - 0
database/migrations/2021_07_09_191913_create_user_voucher_table.php

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateUserVoucherTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('user_voucher', function (Blueprint $table) {
+            $table->foreignId('user_id')->constrained();
+            $table->foreignId('voucher_id')->constrained();
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('user_voucher');
+    }
+}

+ 1 - 1
resources/views/admin/users/edit.blade.php

@@ -72,7 +72,7 @@
                                 <div class="form-group">
                                     <label for="credits">Credits</label>
                                     <input value="{{$user->credits}}" id="credits" name="credits" step="any" min="0"
-                                           max="1000000"
+                                           max="999999"
                                            type="number" class="form-control @error('credits') is-invalid @enderror"
                                            required="required">
                                     @error('credits')

+ 100 - 144
resources/views/admin/vouchers/create.blade.php

@@ -6,12 +6,12 @@
         <div class="container-fluid">
             <div class="row mb-2">
                 <div class="col-sm-6">
-                    <h1>Products</h1>
+                    <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.products.index')}}">Products</a></li>
+                        <li class="breadcrumb-item"><a href="{{route('admin.products.index')}}">Vouchers</a></li>
                         <li class="breadcrumb-item"><a class="text-muted" href="{{route('admin.products.create')}}">Create</a>
                         </li>
                     </ol>
@@ -28,163 +28,94 @@
             <div class="row">
                 <div class="col-lg-6">
                     <div class="card">
+                        <div class="card-header">
+                            <h5 class="card-title">
+                                <i class="fas fa-money-check-alt mr-2"></i>Voucher details
+                            </h5>
+                        </div>
                         <div class="card-body">
-                            <form action="{{route('admin.products.store')}}" method="POST">
+                            <form action="{{route('admin.vouchers.store')}}" method="POST">
                                 @csrf
-                                <div class="d-flex flex-row-reverse">
-                                    <div class="custom-control custom-switch">
-                                        <input type="checkbox" name="disabled" class="custom-control-input custom-control-input-danger" id="switch1">
-                                        <label class="custom-control-label" for="switch1">Disabled <i data-toggle="popover" data-trigger="hover" data-content="Will hide this option from being selected" class="fas fa-info-circle"></i></label>
+
+                                <div class="form-group">
+                                    <label for="memo">Memo</label>
+                                    <input value="{{old('memo')}}" placeholder="Summer break voucher" id="memo"
+                                           name="memo" type="text"
+                                           class="form-control @error('memo') is-invalid @enderror">
+                                    @error('memo')
+                                    <div class="text-danger">
+                                        {{$message}}
                                     </div>
+                                    @enderror
                                 </div>
 
-                                <div class="row">
-                                    <div class="col-lg-6">
-                                        <div class="form-group">
-                                            <label for="name">Name</label>
-                                            <input value="{{old('name')}}" id="name" name="name" type="text"
-                                                   class="form-control @error('name') is-invalid @enderror"
-                                                   required="required">
-                                            @error('name')
-                                            <div class="invalid-feedback">
-                                                {{$message}}
-                                            </div>
-                                            @enderror
-                                        </div>
+                                <div class="form-group">
+                                    <label for="credits">Credits *</label>
+                                    <input value="{{old('credits')}}" placeholder="500" id="credits"
+                                           name="credits" type="number" step="any" min="0"
+                                           max="999999"
+                                           class="form-control @error('credits') is-invalid @enderror">
+                                    @error('credits')
+                                    <div class="text-danger">
+                                        {{$message}}
+                                    </div>
+                                    @enderror
+                                </div>
 
-                                        <div class="form-group">
-                                            <label for="price">Price in credits</label>
-                                            <input value="{{old('price')}}" id="price" name="price"
-                                                   type="number"
-                                                   class="form-control @error('price') is-invalid @enderror"
-                                                   required="required">
-                                            @error('price')
-                                            <div class="invalid-feedback">
-                                                {{$message}}
-                                            </div>
-                                            @enderror
-                                        </div>
 
-                                        <div class="form-group">
-                                            <label for="memory">Memory</label>
-                                            <input value="{{old('memory')}}" id="memory" name="memory"
-                                                   type="number"
-                                                   class="form-control @error('memory') is-invalid @enderror"
-                                                   required="required">
-                                            @error('memory')
-                                            <div class="invalid-feedback">
-                                                {{$message}}
-                                            </div>
-                                            @enderror
-                                        </div>
-
-                                        <div class="form-group">
-                                            <label for="cpu">Cpu</label>
-                                            <input value="{{old('cpu')}}" id="cpu" name="cpu"
-                                                   type="number"
-                                                   class="form-control @error('cpu') is-invalid @enderror"
-                                                   required="required">
-                                            @error('cpu')
-                                            <div class="invalid-feedback">
-                                                {{$message}}
-                                            </div>
-                                            @enderror
+                                <div class="form-group">
+                                    <label for="code">Code *</label>
+                                    <div class="input-group">
+                                        <input value="{{old('code')}}" placeholder="SUMMER" id="code" name="code"
+                                               type="text"
+                                               class="form-control @error('code') is-invalid @enderror"
+                                               required="required">
+                                        <div class="input-group-append">
+                                            <button class="btn btn-info" onclick="setRandomCode()" type="button">
+                                                Random
+                                            </button>
                                         </div>
+                                    </div>
+                                    @error('code')
+                                    <div class="text-danger">
+                                        {{$message}}
+                                    </div>
+                                    @enderror
+                                </div>
 
-                                        <div class="form-group">
-                                            <label for="swap">Swap</label>
-                                            <input value="{{old('swap')}}" id="swap" name="swap"
-                                                   type="number"
-                                                   class="form-control @error('swap') is-invalid @enderror"
-                                                   required="required">
-                                            @error('swap')
-                                            <div class="invalid-feedback">
-                                                {{$message}}
-                                            </div>
-                                            @enderror
+                                <div class="form-group">
+                                    <label for="uses">Uses *</label>
+                                    <div class="input-group">
+                                        <input value="{{old('uses') ?? 1}}" id="uses" min="1" max="2147483647"
+                                               name="uses" type="number"
+                                               class="form-control @error('uses') is-invalid @enderror"
+                                               required="required">
+                                        <div class="input-group-append">
+                                            <button class="btn btn-info" onclick="setMaxUses()" type="button">Max
+                                            </button>
                                         </div>
+                                    </div>
+                                    @error('uses')
+                                    <div class="text-danger">
+                                        {{$message}}
+                                    </div>
+                                    @enderror
+                                </div>
 
-                                        <div class="form-group">
-                                            <label for="description">Description <i data-toggle="popover" data-trigger="hover" data-content="This is what the users sees" class="fas fa-info-circle"></i></label>
-                                            <textarea id="description" name="description"
-                                                      type="text"
-                                                      class="form-control @error('description') is-invalid @enderror"
-                                                      required="required">{{old('description')}}</textarea>
-                                            @error('description')
-                                            <div class="invalid-feedback">
-                                                {{$message}}
-                                            </div>
-                                            @enderror
-                                        </div>
 
+                                <div class="form-group">
+                                    <label for="expires_at">Expires at</label>
+                                    <input value="{{old('expires_at')}}" id="expires_at" name="expires_at"
+                                           type="datetime-local"
+                                           class="form-control @error('expires_at') is-invalid @enderror">
+                                    @error('expires_at')
+                                    <div class="text-danger">
+                                        {{$message}}
                                     </div>
-                                    <div class="col-lg-6">
-                                        <div class="form-group">
-                                            <label for="disk">Disk</label>
-                                            <input value="{{old('disk') ?? 1000}}" id="disk" name="disk"
-                                                   type="number"
-                                                   class="form-control @error('disk') is-invalid @enderror"
-                                                   required="required">
-                                            @error('disk')
-                                            <div class="invalid-feedback">
-                                                {{$message}}
-                                            </div>
-                                            @enderror
-                                        </div>
-                                        <div class="form-group">
-                                            <label for="io">IO</label>
-                                            <input value="{{old('io') ?? 500}}" id="io" name="io"
-                                                   type="number"
-                                                   class="form-control @error('io') is-invalid @enderror"
-                                                   required="required">
-                                            @error('io')
-                                            <div class="invalid-feedback">
-                                                {{$message}}
-                                            </div>
-                                            @enderror
-                                        </div>
-                                        <div class="form-group">
-                                            <label for="databases">Databases</label>
-                                            <input value="{{old('databases') ?? 1}}" id="databases"
-                                                   name="databases"
-                                                   type="number"
-                                                   class="form-control @error('databases') is-invalid @enderror"
-                                                   required="required">
-                                            @error('databases')
-                                            <div class="invalid-feedback">
-                                                {{$message}}
-                                            </div>
-                                            @enderror
-                                        </div>
-                                        <div class="form-group">
-                                            <label for="backups">Backups</label>
-                                            <input value="{{old('backups') ?? 1}}" id="backups"
-                                                   name="backups"
-                                                   type="number"
-                                                   class="form-control @error('backups') is-invalid @enderror"
-                                                   required="required">
-                                            @error('backups')
-                                            <div class="invalid-feedback">
-                                                {{$message}}
-                                            </div>
-                                            @enderror
-                                        </div>
-                                        <div class="form-group">
-                                            <label for="allocations">Allocations</label>
-                                            <input value="{{old('allocations') ?? 0}}"
-                                                   id="allocations" name="allocations"
-                                                   type="number"
-                                                   class="form-control @error('allocations') is-invalid @enderror"
-                                                   required="required">
-                                            @error('allocations')
-                                            <div class="invalid-feedback">
-                                                {{$message}}
-                                            </div>
-                                            @enderror
-                                        </div>
-                                    </div>
+                                    @enderror
                                 </div>
 
+
                                 <div class="form-group text-right">
                                     <button type="submit" class="btn btn-primary">
                                         Submit
@@ -201,5 +132,30 @@
     <!-- END CONTENT -->
 
 
+    <script>
+        function setMaxUses() {
+            let element = document.getElementById('uses')
+            element.value = element.max;
+            console.log(element.max)
+        }
+
+
+        function setRandomCode() {
+            let element = document.getElementById('code')
+            element.value = getRandomCode(36)
+        }
+
+        function getRandomCode(length) {
+            let result = '';
+            let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-';
+            let charactersLength = characters.length;
+            for (let i = 0; i < length; i++) {
+                result += characters.charAt(Math.floor(Math.random() *
+                    charactersLength));
+            }
+            return result;
+        }
+    </script>
+
 
 @endsection

+ 8 - 7
resources/views/admin/vouchers/edit.blade.php

@@ -12,7 +12,7 @@
                     <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.products.index')}}">Vouchers</a></li>
-                        <li class="breadcrumb-item"><a class="text-muted" href="{{route('admin.products.create')}}">Create</a>
+                        <li class="breadcrumb-item"><a class="text-muted" href="{{route('admin.products.edit' , $voucher->id)}}">Edit</a>
                         </li>
                     </ol>
                 </div>
@@ -34,12 +34,13 @@
                             </h5>
                         </div>
                         <div class="card-body">
-                            <form action="{{route('admin.vouchers.store')}}" method="POST">
+                            <form action="{{route('admin.vouchers.update' , $voucher->id)}}" method="POST">
                                 @csrf
+                                @method('PATCH')
 
                                 <div class="form-group">
                                     <label for="memo">Memo</label>
-                                    <input value="{{old('memo')}}" placeholder="Summer break voucher" id="memo"
+                                    <input value="{{ $voucher->memo }}" placeholder="Summer break voucher" id="memo"
                                            name="memo" type="text"
                                            class="form-control @error('memo') is-invalid @enderror">
                                     @error('memo')
@@ -51,7 +52,7 @@
 
                                 <div class="form-group">
                                     <label for="credits">Credits *</label>
-                                    <input value="{{old('credits')}}" placeholder="500" id="credits"
+                                    <input value="{{ $voucher->credits }}" placeholder="500" id="credits"
                                            name="credits" type="number" step="any" min="0"
                                            max="999999"
                                            class="form-control @error('credits') is-invalid @enderror">
@@ -66,7 +67,7 @@
                                 <div class="form-group">
                                     <label for="code">Code *</label>
                                     <div class="input-group">
-                                        <input value="{{old('code')}}" placeholder="SUMMER" id="code" name="code"
+                                        <input value="{{ $voucher->code }}" placeholder="SUMMER" id="code" name="code"
                                                type="text"
                                                class="form-control @error('code') is-invalid @enderror"
                                                required="required">
@@ -86,7 +87,7 @@
                                 <div class="form-group">
                                     <label for="uses">Uses *</label>
                                     <div class="input-group">
-                                        <input value="{{old('uses') ?? 1}}" id="uses" min="1" max="2147483647"
+                                        <input value="{{ $voucher->uses }}" id="uses" min="1" max="2147483647"
                                                name="uses" type="number"
                                                class="form-control @error('uses') is-invalid @enderror"
                                                required="required">
@@ -105,7 +106,7 @@
 
                                 <div class="form-group">
                                     <label for="expires_at">Expires at</label>
-                                    <input value="{{old('expires_at')}}" id="expires_at" name="expires_at"
+                                    <input value="{{ $voucher->expires_at }}" id="expires_at" name="expires_at"
                                            type="datetime-local"
                                            class="form-control @error('expires_at') is-invalid @enderror">
                                     @error('expires_at')

+ 17 - 31
resources/views/admin/vouchers/index.blade.php

@@ -6,13 +6,13 @@
         <div class="container-fluid">
             <div class="row mb-2">
                 <div class="col-sm-6">
-                    <h1>Products</h1>
+                    <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 class="text-muted"
-                                                       href="{{route('admin.products.index')}}">Products</a></li>
+                                                       href="{{route('admin.vouchers.index')}}">Vouchers</a></li>
                     </ol>
                 </div>
             </div>
@@ -28,8 +28,8 @@
 
                 <div class="card-header">
                     <div class="d-flex justify-content-between">
-                        <h5 class="card-title"><i class="fas fa-sliders-h mr-2"></i>Products</h5>
-                        <a href="{{route('admin.products.create')}}" class="btn btn-sm btn-primary"><i
+                        <h5 class="card-title"><i class="fas fa-money-check-alt mr-2"></i>Vouchers</h5>
+                        <a href="{{route('admin.vouchers.create')}}" class="btn btn-sm btn-primary"><i
                                 class="fas fa-plus mr-1"></i>Create new</a>
                     </div>
                 </div>
@@ -39,19 +39,12 @@
                     <table id="datatable" class="table table-striped">
                         <thead>
                         <tr>
-                            <th>Active</th>
-                            <th>Name</th>
-                            <th>Price</th>
-                            <th>Memory</th>
-                            <th>Cpu</th>
-                            <th>Swap</th>
-                            <th>Disk</th>
-                            <th>IO</th>
-                            <th>Databases</th>
-                            <th>Backups</th>
-                            <th>Allocations</th>
-                            <th>Servers</th>
-                            <th>Created at</th>
+                            <th>Status</th>
+                            <th>Code</th>
+                            <th>Memo</th>
+                            <th>Credits</th>
+                            <th>Used / Uses</th>
+                            <th>Expires</th>
                             <th></th>
                         </tr>
                         </thead>
@@ -79,21 +72,14 @@
                 processing: true,
                 serverSide: true,
                 stateSave: true,
-                ajax: "{{route('admin.products.datatable')}}",
+                ajax: "{{route('admin.vouchers.datatable')}}",
                 columns: [
-                    {data: 'disabled'},
-                    {data: 'name'},
-                    {data: 'price'},
-                    {data: 'memory'},
-                    {data: 'cpu'},
-                    {data: 'swap'},
-                    {data: 'disk'},
-                    {data: 'io'},
-                    {data: 'databases'},
-                    {data: 'backups'},
-                    {data: 'allocations'},
-                    {data: 'servers', sortable: false},
-                    {data: 'created_at'},
+                    {data: 'status'},
+                    {data: 'code'},
+                    {data: 'memo'},
+                    {data: 'credits'},
+                    {data: 'uses'},
+                    {data: 'expires_at'},
                     {data: 'actions', sortable: false},
                 ],
                 fnDrawCallback: function( oSettings ) {

+ 20 - 1
resources/views/layouts/main.blade.php

@@ -96,6 +96,10 @@
                             Log back in
                         </a>
                     @endif
+                    <a class="dropdown-item" data-toggle="modal" data-target="#redeemVoucherModal" href="javascript:void(0)">
+                        <i class="fas fa-money-check-alt fa-sm fa-fw mr-2 text-gray-400"></i>
+                        Redeem code
+                    </a>
                     <div class="dropdown-divider"></div>
                     <form method="post" action="{{route('logout')}}">
                         @csrf
@@ -253,6 +257,14 @@
                             </a>
                         </li>
 
+                        <li class="nav-item">
+                            <a href="{{route('admin.vouchers.index')}}"
+                               class="nav-link @if(Request::routeIs('admin.vouchers.*')) active @endif">
+                                <i class="nav-icon fas fa-money-check-alt"></i>
+                                <p>Vouchers</p>
+                            </a>
+                        </li>
+
                         <li class="nav-item">
                             <a href="{{route('admin.usefullinks.index')}}"
                                class="nav-link @if(Request::routeIs('admin.usefullinks.*')) active @endif">
@@ -261,7 +273,6 @@
                             </a>
                         </li>
 
-
                     @endif
 
                 </ul>
@@ -289,6 +300,8 @@
         @endif
 
         @yield('content')
+
+        @include('models.redeem_voucher_modal')
     </div>
     <!-- /.content-wrapper -->
     <footer class="main-footer">
@@ -319,6 +332,12 @@
 <script>
     $(document).ready(function () {
         $('[data-toggle="popover"]').popover();
+
+        $.ajaxSetup({
+            headers: {
+                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
+            }
+        });
     });
 </script>
 <script>

+ 51 - 0
resources/views/models/redeem_voucher_modal.blade.php

@@ -0,0 +1,51 @@
+<!-- Button to Open the Modal -->
+<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#redeemVoucherModal">
+    Open modal
+</button>
+
+<!-- The Modal -->
+<div class="modal fade" id="redeemVoucherModal">
+    <div class="modal-dialog">
+        <div class="modal-content">
+
+            <!-- Modal Header -->
+            <div class="modal-header">
+                <h4 class="modal-title">Redeem voucher code</h4>
+                <button type="button" class="close" data-dismiss="modal">&times;</button>
+            </div>
+
+            <!-- Modal body -->
+            <div class="modal-body">
+                <form>
+                    <div class="form-group">
+                        <label for="code">Code</label>
+                        <div class="input-group">
+                            <div class="input-group-prepend">
+                                <div class="input-group-text">
+                                    <i class="fas fa-money-check-alt"></i>
+                                </div>
+                            </div>
+                            <input id="code" name="code" placeholder="SUMMER" type="text" class="form-control">
+                        </div>
+                    </div>
+                </form>
+            </div>
+
+            <!-- Modal footer -->
+            <div class="modal-footer">
+                <button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
+                <button name="submit" type="button" class="btn btn-primary">Redeem</button>
+            </div>
+
+        </div>
+    </div>
+</div>
+
+
+<script>
+    function validateCode(){
+        $.ajax({
+            
+        })
+    }
+</script>

+ 4 - 0
routes/web.php

@@ -12,6 +12,7 @@ use App\Http\Controllers\Admin\ServerController as AdminServerController;
 use App\Http\Controllers\Admin\SettingsController;
 use App\Http\Controllers\Admin\UsefulLinkController;
 use App\Http\Controllers\Admin\UserController;
+use App\Http\Controllers\Admin\VoucherController;
 use App\Http\Controllers\Auth\SocialiteController;
 use App\Http\Controllers\HomeController;
 use App\Http\Controllers\NotificationController;
@@ -110,6 +111,9 @@ Route::middleware('auth')->group(function () {
         Route::get('usefullinks/datatable', [UsefulLinkController::class, 'datatable'])->name('usefullinks.datatable');
         Route::resource('usefullinks', UsefulLinkController::class);
 
+        Route::get('vouchers/datatable', [VoucherController::class, 'datatable'])->name('vouchers.datatable');
+        Route::resource('vouchers', VoucherController::class);
+
         Route::get('api/datatable', [ApplicationApiController::class, 'datatable'])->name('api.datatable');
         Route::resource('api', ApplicationApiController::class)->parameters([
             'api' => 'applicationApi',