Start of ordering

This commit is contained in:
Deon George 2018-08-10 00:10:51 +10:00
parent ca402df525
commit 499d44289e
No known key found for this signature in database
GPG Key ID: 7670E8DC27415254
15 changed files with 554 additions and 73 deletions

View File

@ -0,0 +1,34 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Product;
use Igaster\LaravelTheme\Facades\Theme;
class OrderController extends Controller
{
public function index()
{
return view('order');
}
public function product_order(Product $o)
{
Theme::set('metronic-fe');
return view('widgets.product_order',['o'=>$o]);
}
public function product_info(Product $o)
{
Theme::set('metronic-fe');
return view('widgets.product_description',['o'=>$o]);
}
public function submit(Request $request)
{
}
}

View File

@ -3,6 +3,7 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Auth;
class Product extends Model
{
@ -19,19 +20,56 @@ class Product extends Model
return $this->hasMany(Service::class);
}
public function getCategoryAttribute()
{
return $this->prod_plugin_file;
}
public function getDescriptionAttribute()
{
// @todo If the user has selected a specific language.
return $this->description($this->getDefaultLanguage());
}
public function getNameAttribute()
{
return $this->name(Auth::user()->language);
}
public function getProductIdAttribute()
{
return sprintf('#%04s',$this->id);
}
public function scopeActive()
{
return $this->where('active',TRUE);
}
public function description(Language $lo=NULL)
{
if (is_null($lo))
$lo = $this->getDefaultLanguage();
return $this->descriptions->where('language_id',$lo->id)->first()->description_short;
}
private function getDefaultLanguage()
{
return config('SITE_SETUP')->language;
}
/**
* Get the language name
* Get the product name
*
* @param Language $lo
* @return string Product Name
*/
public function name(Language $lo)
public function name(Language $lo=NULL)
{
if (is_null($lo))
$lo = $this->getDefaultLanguage();
return $this->descriptions->where('language_id',$lo->id)->first()->name;
}
}

View File

@ -77,7 +77,7 @@ class Service extends Model
public function getCategoryAttribute()
{
return $this->product->prod_plugin_file;
return $this->product->category;
}
public function getNameAttribute()

View File

@ -95,6 +95,8 @@ class User extends Authenticatable
return $this->hasMany(static::class,'parent_id','id');
}
/** Attributes **/
public function getActiveDisplayAttribute($value)
{
return sprintf('<span class="btn-sm btn-block btn-%s text-center">%s</span>',$this->active ? 'primary' : 'danger',$this->active ? 'Active' : 'Inactive');
@ -110,24 +112,6 @@ class User extends Authenticatable
return sprintf('%s %s',$this->firstname,$this->lastname);
}
public function getSurFirstNameAttribute()
{
return sprintf('%s, %s',$this->lastname,$this->firstname);
}
/**
* Return a Carbon Date if it has a value.
*
* @param $value
* @return \Leenooks\Carbon
* @todo This attribute is not in the schema
*/
public function getLastAccessAttribute($value)
{
if (! is_null($value))
return new Carbon($value);
}
public function getInvoicesDueAttribute()
{
return $this->invoices
@ -144,6 +128,28 @@ class User extends Authenticatable
return config('SITE_SETUP')->language;
}
/**
* Return a Carbon Date if it has a value.
*
* @param $value
* @return \Leenooks\Carbon
* @todo This attribute is not in the schema
*/
public function getLastAccessAttribute($value)
{
if (! is_null($value))
return new Carbon($value);
}
/**
* @deprecated Use static::getFullNameAttribute()
* @return mixed
*/
public function getNameAttribute()
{
return $this->full_name;
}
public function getPaymentHistoryAttribute()
{
return $this->payments
@ -157,20 +163,16 @@ class User extends Authenticatable
->where('active',TRUE);
}
/**
* @deprecated Use static::getFullNameAttribute()
* @return mixed
*/
public function getNameAttribute()
{
return $this->full_name;
}
public function getServicesCountHtmlAttribute()
{
return sprintf('%s <small>/%s</small>',$this->services->where('active',TRUE)->count(),$this->services->count());
}
public function getSurFirstNameAttribute()
{
return sprintf('%s, %s',$this->lastname,$this->firstname);
}
public function getSwitchUrlAttribute()
{
return sprintf('<a href="/a/switch/start/%s"><i class="fa fa-external-link"></i></a>',$this->id);
@ -186,41 +188,14 @@ class User extends Authenticatable
return sprintf('<a href="/u/account/view/%s">%s</a>',$this->id,$this->user_id);
}
/** Scopes **/
public function scopeActive()
{
return $this->where('active',TRUE);
}
public function isAdmin($id)
{
return $id AND in_array($this->role(),['wholesaler','reseller']) AND in_array($id,$this->all_accounts()->pluck('id')->toArray());
}
public function sendPasswordResetNotification($token)
{
$this->notify(new ResetPasswordNotification($token));
}
// List all the agents, including agents of agents
public function all_agents($level=0)
{
$result = collect();
foreach ($this->agents as $o)
{
if (! $o->active OR ! $o->agents->count())
continue;
$o->level = $level;
$result->push($o);
// Include agents of agents
$result->push($o->all_agents($level+1));
}
return $result->flatten();
}
/** Functions */
public function all_accounts()
{
@ -253,6 +228,49 @@ class User extends Authenticatable
return $result->flatten();
}
// List all the agents, including agents of agents
public function all_agents($level=0)
{
$result = collect();
foreach ($this->agents as $o)
{
if (! $o->active OR ! $o->agents->count())
continue;
$o->level = $level;
$result->push($o);
// Include agents of agents
$result->push($o->all_agents($level+1));
}
return $result->flatten();
}
/**
* Determine if the user is an admin of the account with $id
*
* @param $id
* @return bool
*/
public function isAdmin($id)
{
return $id AND $this->isReseller() AND in_array($id,$this->all_accounts()->pluck('id')->toArray());
}
/**
* Determine if the logged in user is a reseller or wholesaler
*
* @return bool
*/
public function isReseller()
{
return in_array($this->role(),['wholesaler','reseller']);
}
public function role()
{
// If I have agents and no parent, I am the wholesaler
@ -267,4 +285,8 @@ class User extends Authenticatable
elseif (! $this->all_agents()->count() AND ! $this->all_clients()->count())
return 'customer';
}
public function sendPasswordResetNotification($token)
{
$this->notify(new ResetPasswordNotification($token));
}
}

View File

@ -23,7 +23,15 @@
<!-- Main content -->
<section class="content">
<!-- Your Page Content Here -->
@yield('main-content')
<div class="main">
<div class="container">
@yield('breadcrumb')
<div class="row margin-bottom-40">
@yield('main-content')
</div>
</div>
</div>
</section><!-- /.content -->
</div><!-- /.content-wrapper -->
@ -33,19 +41,21 @@
</div><!-- ./wrapper -->
{{-- BEGIN CORE PLUGINS (REQUIRED FOR ALL PAGES) --}}
@js('/site/js/jquery/1.11.2/js/jquery.min.js','jquery')
@js('/site/js/bootstrap/3.3.5/js/bootstrap.min.js','bootstrap-js','jquery')
@js('/site/js/jquery/plugins/migrate/1.2.1/js/jquery-migrate.min.js','jq-migrate','jquery')
@js('/site/js/jquery/plugins/back-to-top/back-to-top.js','back-to-top','jquery')
{{-- END CORE PLUGINS --}}
@section('scripts')
{{-- BEGIN CORE PLUGINS (REQUIRED FOR ALL PAGES) --}}
@js('/site/js/jquery/1.11.2/js/jquery.min.js','jquery')
@js('/site/js/bootstrap/3.3.5/js/bootstrap.min.js','bootstrap-js','jquery')
@js('/site/js/jquery/plugins/migrate/1.2.1/js/jquery-migrate.min.js','jq-migrate','jquery')
@js('/site/js/jquery/plugins/back-to-top/back-to-top.js','back-to-top','jquery')
{{-- END CORE PLUGINS --}}
{{-- Scripts --}}
{!! Asset::scripts() !!}
@include('layouts.partials.scripts')
@section('scripts')
@include('layouts.partials.scripts')
@show
{{-- Scripts --}}
{!! Asset::scripts() !!}
@yield('page-scripts')
@show
</body>
<!-- BODY End-->

View File

@ -0,0 +1,246 @@
@extends('layouts.app')
@section('htmlheader_title')
{{ trans('message.home') }}
@endsection
@section('main-content')
<div class="col-md-12">
<h1>Order Service</h1>
<div class="order-page" id="order-page">
<div class="row">
<div class="col-md-3">
<ul class="tabbable faq-tabbable">
<li class="active">
<a href="#order_1" data-toggle="tab" aria-expanded="true">Order Service</a>
</li>
</ul>
</div>
<div class="col-md-9">
<div class="tab-content" style="padding:0; background: #fff;">
<div class="tab-pane active" id="order_1">
<div class="panel-group" id="accordion1">
<form role="form" method="POST" enctype="multipart/form-data">
{{ csrf_field() }}
<div id="accordion">
<!-- User -->
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">Register or Sign In</h4>
</div>
<div class="panel-collapse">
<div class="panel-body">
<div class="col-md-12">
@if (Auth::user())
{{ Auth::user()->name }}
@else
<a href="{{ url('login') }}">Login</a>
@endif
</div>
<div class="row">
<div class="col-sm-2"><button class="btn btn-block btn-primary next">Next</button></div>
</div>
</div>
</div>
</div>
<!-- Reseller Choose Client -->
@if ($user->isReseller())
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
Client
</h4>
</div>
<div class="panel-collapse">
<div class="panel-body">
<div class="col-md-12">
<div class="col-md-6">
<ul class="nav nav-tabs">
<li class="active">
<a href="#tab_1" data-toggle="tab">New Client</a>
</li>
<li>
<a href="#tab_2" data-toggle="tab">Existing Client</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane row fade in active" id="tab_1">
<div class="control-group form-group col-sm-12 {{ $errors->has('order_email') ? 'has-error' : '' }}">
<label for="order_email">New Client Email</label>
<input type="email" class="form-control" id="order_email" name="order_email" placeholder="New Client Email" value="{{ old('order_email') }}">
<span class="help-block">{{ $errors->first('order_email') }}</span>
</div>
</div>
<div class="tab-pane row fade" id="tab_2">
<div class="control-group form-group col-sm-12 {{ $errors->has('order_email') ? 'has-error' : '' }}">
<label for="order_email">Client Account</label>
<select class="form-control" id="order_email" name="order_email" value="{{ old('order_email') }}">
<option value="">&nbsp;</option>
@foreach ($user->all_clients()->sortBy('sur_first_name') as $o)
<option value="{{ $o->email }}">{{ $o->sur_first_name }}</option>
@endforeach
</select>
<span class="help-block">{{ $errors->first('order_email') }}</span>
</div>
<!-- Account -->
@if (FALSE AND Auth::user()->isBusiness())
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a href="#accordion1_2" data-parent="#accordion1" class="accordion-toggle">
Account
</a>
</h4>
</div>
<div class="panel-collapse collapse" id="accordion1_2">
<div class="panel-body">
</div>
</div>
</div>
@endif
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-2"><button class="btn btn-block btn-primary">Previous</button></div>
<div class="col-sm-2"><button class="btn btn-block btn-primary next">Next</button></div>
</div>
</div>
</div>
</div>
@endif
<!-- Product -->
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">Product</h4>
</div>
<div class="panel-collapse margin-bottom-20">
<div class="panel-body">
<div class="col-md-12">
<div class="control-group form-group col-sm-6 {{ $errors->has('product_id') ? 'has-error' : '' }}">
<label for="order_email">Product</label>
<select class="form-control" id="product_id" name="product_id" value="{{ old('product_id') }}">
<option value="">&nbsp;</option>
@foreach (\App\Models\Product::active()->get()->sortBy('name') as $o)
<option value="{{ $o->id }}">{{ $o->name }}</option>
@endforeach
</select>
<span class="help-block">{{ $errors->first('product_id') }}</span>
</div>
<div class="col-sm-6" id="product_info"></div>
</div>
<div class="col-md-12" id="product_order"></div>
<div class="row">
<div class="col-sm-2"><button class="btn btn-block btn-primary">Previous</button></div>
</div>
<div class="row">
<div class="col-sm-2"><input type="submit" class="btn btn-block btn-primary" value="Submit Order"></div>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
<div class="tab-pane" id="tab-2">
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
@section('page-scripts')
@js('/js/jqBootstrapValidation.js','jq-validation','jquery')
<script src="//code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
$(function () { $("input,select,textarea").not("[type=submit]").jqBootstrapValidation(); } );
$(document).ready(function () {
$('#accordion').accordion({
header: "> div > div",
collapsible: false,
heightStyle: 'content',
disabled: true
});
$('#accordion button').click(function (e) {
e.preventDefault();
e.stopPropagation();
var delta = ($(this).is('.next') ? 2 : -2);
$('#accordion').accordion('option', 'active', ($('#accordion').accordion('option', 'active') + delta));
});
$("select[name=product_id]").change(function() {
// If we select a blank, then dont continue
if (this.value == 0)
return false;
// Send the request and update sub category dropdown
$.ajax({
type: "GET",
//data: "key="+$(this).val(),
dataType: "html",
cache: true,
url: '{{ url('product_info') }}'+'/'+$(this).val(),
timeout: 3000,
error: function(x) {
alert("Failed to submit");
},
success: function(data) {
$("div[id=product_info]").empty().append(data);
}
});
$.ajax({
type: "GET",
//data: "key="+$(this).val(),
dataType: "html",
cache: true,
url: '{{ url('product_order') }}'+'/'+$(this).val(),
timeout: 3000,
error: function(x) {
alert("Failed to submit");
},
success: function(data) {
$("div[id=product_order]").empty().append(data);
}
});
});
});
</script>
<style>
span.help-block > ul {
color: #9d0000;
padding-left: 5px;
list-style-type: none;
}
</style>
@append

View File

@ -0,0 +1,9 @@
<fieldset class="form-group col-sm-12">
<label>ADSL</label>
<div class="form-group col-sm-12 {{ $errors->has('product_options.address') ? 'has-error' : '' }}">
<label for="product_options.address">Site Address</label>
<input type="text" class="form-control" id="product_options.address" name="product_options[address]" placeholder="Site Address" value="{{ old('product_options.address') }}">
<span class="help-block">{{ $errors->first('product_options.address') }} {{ $errors->first('product_options.address') }}</span>
</div>
</fieldset>

View File

@ -0,0 +1,21 @@
<fieldset class="form-group">
<label class="col-md-12">VOIP</label>
<div class="form-group col-sm-6 {{ $errors->has('product_options.phonenumber') ? 'has-error' : '' }}">
<label for="product_options.phonenumber">Phone Number</label>
<input type="text" class="form-control" id="product_options.phonenumber" name="product_options[phonenumber]" placeholder="Phone Number with Area Code" value="{{ old('product_options.phonenumber') }}">
<span class="help-block">{{ $errors->first('product_options.phonenumber') }} {{ $errors->first('product_options.phonenumber') }}</span>
</div>
<div class="form-group col-sm-6 {{ $errors->has('product_options.supplier') ? 'has-error' : '' }}">
<label for="product_order.supplier">Existing Supplier</label>
<input type="text" class="form-control" id="product_options.supplier" name="product_options[supplier]" placeholder="eg: Telstra" value="{{ old('product_options.supplier') }}">
<span class="help-block">{{ $errors->first('product_options.supplier') }} {{ $errors->first('product_options.supplier') }}</span>
</div>
<div class="form-group col-sm-6 {{ $errors->has('product_options.supplieraccnum') ? 'has-error' : '' }}">
<label for="product_options.supplieraccnum">Suppliers Account Number</label>
<input type="text" class="form-control" id="product_options.supplieraccnum" name="product_options[supplieraccnum]" placeholder="Refer to Bill" value="{{ old('product_options.supplieraccnum') }}">
<span class="help-block">{{ $errors->first('product_options.supplieraccnum') }} {{ $errors->first('product_options.supplieraccnum') }}</span>
</div>
</fieldset>

View File

@ -0,0 +1,30 @@
<div class="col-md-12">
<p>{{ $o->description }}</p>
</div>
<table class="table table-condensed">
<tr>
<th>Type</th>
<td class="text-right">ADSL</td>
</tr>
<tr>
<th>Setup Cost</th>
<td class="text-right">TBA</td>
</tr>
<tr>
<th>Monthly Cost</th>
<td class="text-right">TBA</td>
</tr>
<tr>
<th>Default Billing</th>
<td class="text-right">TBA</td>
</tr>
<tr>
<th>Contract Term</th>
<td class="text-right">TBA</td>
</tr>
<tr>
<th>Minimum Costs</th>
<td class="text-right">TBA</td>
</tr>
</table>

View File

@ -0,0 +1,30 @@
<div class="col-md-12">
<p>{{ $o->description }}</p>
</div>
<table class="table table-condensed">
<tr>
<th>Type</th>
<td class="text-right">VOIP</td>
</tr>
<tr>
<th>Setup Cost</th>
<td class="text-right">TBA</td>
</tr>
<tr>
<th>Monthly Cost</th>
<td class="text-right">TBA</td>
</tr>
<tr>
<th>Default Billing</th>
<td class="text-right">TBA</td>
</tr>
<tr>
<th>Contract Term</th>
<td class="text-right">TBA</td>
</tr>
<tr>
<th>Minimum Costs</th>
<td class="text-right">TBA</td>
</tr>
</table>

View File

@ -0,0 +1,13 @@
@if(View::exists('widgets.product.'.$o->category))
<div class="col-md-12">
<div class="box box-primary">
<div class="box-body">
{{-- Return Category Requirements --}}
@include('widgets.product.'.$o->category)
{{-- Return Supplier Requirements --}}
{{-- Return Product Requirements --}}
</div>
</div>
</div>
@endif

View File

@ -0,0 +1,18 @@
@if(View::exists('widgets.order.'.$o->category))
<div class="col-md-12">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">Order Configuration</h3>
</div>
<div class="box-body">
{{-- Return Category Requirements --}}
@include('widgets.order.'.$o->category)
{{-- Return Supplier Requirements --}}
{{-- Return Product Requirements --}}
</div>
</div>
</div>
@endif

View File

@ -0,0 +1,6 @@
<ul class="sidebar-menu" data-widget="tree">
<li class="header"><b>MENU</b></li>
<!-- Optionally, you can add icons to the links -->
<li @if(Route::current()->getName() == 'home')class="active"@endif><a href="{{ url('home') }}"><i class='fa fa-link'></i> <span>{{ trans('adminlte_lang::message.home') }}</span></a></li>
<li @if(Route::current()->getName() == 'order')class="active"@endif><a href="{{ url('order') }}"><i class='fa fa-shopping-cart'></i> <span>Order</span></a></li>
</ul>

View File

@ -29,4 +29,4 @@ Route::group(['middleware'=>'auth:api'], function() {
Route::get('/u/invoices','UserServicesController@invoices');
Route::get('/u/payments','UserServicesController@payments');
Route::get('/u/services','UserServicesController@services');
});
});

View File

@ -46,8 +46,12 @@ Route::group(['middleware'=>['theme:adminlte-be','auth'],'prefix'=>'u'], functio
// Frontend Routes (Non-Authed Users)
Route::group(['middleware'=>['theme:metronic-fe']], function() {
Route::get('/', 'WelcomeController@index');
Route::get('order','OrderController@index');
Route::post('order','OrderController@submit');
});
Route::get('product_order/{o}', 'OrderController@product_order');
Route::get('product_info/{o}', 'OrderController@product_info');
Route::redirect('/home','/u/home');
Route::demoAccess('/uc-access');
Route::redirect('/under-construction','http://www.graytech.net.au');