Add question UI + Fix search and filters

This commit is contained in:
Jérémy Munsch 2021-09-10 15:43:27 +02:00
parent a8aa32af19
commit 7cbbeb3cb4
26 changed files with 660 additions and 21 deletions

View file

@ -95,9 +95,10 @@ class ApiError extends BaseEnumRoutable
'customerExists' => 'L\'utilisateur est déjà enregistré sur ce site',
'customerNotActivated' => 'Le compte n\'est pas activé',
'customerAlreadyActive' => 'Le compte est déjà activé',
'singleOptinCustomerExists' => 'Le signle optin ne peut être ajouté car un compte existe.',
'authFailed' => 'Echec de l\'authentification',
'singleOptinCustomerExists' => 'Le single optin ne peut être ajouté car un compte existe.',
'authFailed' => 'Echec de l\'authentification du compte',
'needAuth' => 'Vous devez être authentifié',
'apiAuthFailed' => 'Echec de l\'authentification client à l\'Api LDC-CRM pour ce service',
'methodNotAllowed' => 'This method is not allowed for this request',
'wrongTimeStamp' => 'Your request is malformed, please check timestamp header and parameter',
'missingParameter' => 'The request is missing some parameters',

View file

@ -0,0 +1,42 @@
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\Answer;
use Illuminate\Database\Eloquent\Builder;
use Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
class AnswerController extends Controller
{
use CrudController {
index as crudIndex;
}
/** @var Log */
public static $modelClass = Answer::class;
public static $layout = 'layouts.app';
public function indexQuery(Builder $query): Builder
{
$parent = request()->question;
if ($parent) {
$query->whereHas('question', function ($q) use ($parent) {
return $q->whereId($parent->id);
});
}
return $query;
}
public function index(CrudIndexRequest $request)
{
/** @var \Illuminate\View\View */
$view = $this->crudIndex($request);
if ($request->ajax()) {
return $view;
}
return view('answer.index', $view->getData());
}
}

View file

@ -9,6 +9,7 @@ use App\Models\Customer;
use App\Models\CustomerInfo;
use App\Models\CustomerLogin;
use App\Models\SingleOptin;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Schema;
@ -21,15 +22,25 @@ class CustomerController extends Controller
{
public function index(Request $request)
{
$modelTable = (new Customer())->getTable();
$modelClass = Customer::class;
$modelTable = (new CustomerInfo())->getTable();
$modelClass = CustomerInfo::class;
$brands = Brand::select('id', 'name')->get();
$columns = ['lastname', 'firstname', 'opt_in'];
// Jointure pour pouvoir trier les colonnes
/** @var \Illuminate\Database\Eloquent\Builder */
$query = CustomerInfo::with(['customer']);
$query = CustomerInfo::join('customer_logins', function (JoinClause $join) {
$join->on('customer_logins.brand_id', '=', 'customer_infos.brand_id')
->on('customer_logins.customer_id', '=', 'customer_infos.customer_id');
})
->join('customers', function (JoinClause $join) {
$join->on('customers.id', '=', 'customer_infos.customer_id');
})
->join('brands', function (JoinClause $join) {
$join->on('brands.id', '=', 'customer_infos.brand_id');
});
if (request()->brand) {
$query = $query->where('brand_id', $request->brand);
$query = $query->where('customer_infos.brand_id', $request->brand);
}
// Search on crud Label column
@ -37,9 +48,8 @@ class CustomerController extends Controller
foreach ($columns as $column) {
$query = $query->orWhere($column, 'LIKE', "%$request->search%");
}
$query = $query->orWhereHas('customer', function ($q) use ($request) {
$q->where('email', 'LIKE', "%$request->search%");
});
$query = $query->orWhere('customers.email', 'LIKE', "%$request->search%");
$query = $query->orWhere('customer_logins.last_connection', 'LIKE', "%$request->search%");
}
// Sort columns
@ -57,7 +67,16 @@ class CustomerController extends Controller
if (
Session::has("crud.$modelTable.sort_col") and
Session::has("crud.$modelTable.sort_way") and
Schema::hasColumn($modelTable, Session::get("crud.$modelTable.sort_col"))
(Schema::hasColumn($modelTable, Session::get("crud.$modelTable.sort_col")) or
in_array(Session::get("crud.$modelTable.sort_col"), [
'brands.name',
'customers.email',
'customer_infos.firstname',
'customer_infos.lastname',
'customer_infos.opt_in',
'customer_logins.last_connection',
'customer_logins.status'
]))
) {
$query = $query->orderBy(
Session::get("crud.$modelTable.sort_col"),

View file

@ -0,0 +1,39 @@
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\Question;
use Illuminate\Database\Eloquent\Builder;
use Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
class QuestionController extends Controller
{
use CrudController {
index as crudIndex;
}
/** @var Question */
public static $modelClass = Question::class;
public static $layout = 'layouts.app';
public function index(CrudIndexRequest $request)
{
/** @var \Illuminate\View\View */
$view = $this->crudIndex($request);
if ($request->ajax()) {
return $view;
}
return view('question.index', $view->getData());
}
public function indexQuery(Builder $query): Builder
{
if (request()->brand) {
$query = $query->where('brand_id', '=', request()->brand);
}
return $query;
}
}

View file

@ -4,15 +4,45 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
use Kwaadpepper\CrudPolicies\Enums\CrudAction;
use Kwaadpepper\CrudPolicies\Enums\CrudType;
use Kwaadpepper\CrudPolicies\Traits\IsCrudModel;
class Answer extends Model
{
use HasFactory;
use IsCrudModel;
protected $crudLabelColumn = 'answer';
protected $crudValueColumn = 'id';
protected $fillable = [
'answer'
];
public function __construct(array $attributes = [])
{
self::$editableProperties = [
'answer' => [
'label' => Str::ucfirst(trans('models.common.answer')),
'type' => CrudType::string(),
'validate' => [
'min:1',
'max:255'
],
'actions' => [
CrudAction::viewAny(),
CrudAction::view(),
CrudAction::create(),
CrudAction::update()
]
]
];
parent::__construct($attributes);
}
/**
* Question BelongsTo relation
*

View file

@ -101,9 +101,9 @@ class CustomerInfo extends Model
}
/**
* CustomerLogin HasOneThrough relation
* get Login
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
* @return \App\Models\CustomerLogin
*/
public function login()
{

View file

@ -5,12 +5,21 @@ namespace App\Models;
use App\Enums\QuestionType;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
use Kwaadpepper\CrudPolicies\Enums\CrudAction;
use Kwaadpepper\CrudPolicies\Enums\CrudType;
use Kwaadpepper\CrudPolicies\Traits\IsCrudModel;
use Kwaadpepper\Enum\Traits\CastsEnums;
class Question extends Model
{
use CastsEnums;
use HasFactory;
use IsCrudModel;
protected $crudLabelColumn = 'question';
protected $crudValueColumn = 'id';
protected $enumCasts = [
'type' => QuestionType::class
@ -21,6 +30,57 @@ class Question extends Model
'type'
];
public function __construct(array $attributes = [])
{
self::$editableProperties = [
'question' => [
'label' => Str::ucfirst(trans('models.common.question')),
'type' => CrudType::string(),
'validate' => [
'min:10',
'max:255'
],
'actions' => [
CrudAction::viewAny(),
CrudAction::view(),
CrudAction::create(),
CrudAction::update()
]
],
'type' => [
'label' => Str::ucfirst(trans('models.common.type')),
'type' => CrudType::enum(),
'enum' => QuestionType::class,
'actions' => [
CrudAction::view(),
CrudAction::create(),
CrudAction::update(),
]
],
'brand_id' => [
'label' => Str::ucfirst(trans('models.classes.brand')),
'type' => CrudType::belongsTo(),
'belongsTo' => Brand::class,
'actions' => [
CrudAction::viewAny(),
CrudAction::view(),
CrudAction::create(),
CrudAction::update(),
]
],
'answers' => [
'label' => Str::ucfirst(Str::plural(trans('models.classes.answers'))),
'type' => CrudType::belongsToMany(),
'belongsToMany' => Answer::class,
'belongsToManyLabel' => 'answer',
'actions' => [
CrudAction::view()
]
]
];
parent::__construct($attributes);
}
/**
* Brand BelongsTo relation
*

View file

@ -0,0 +1,29 @@
<?php
namespace App\Policies;
use App\Policies\Rules\UserStaticRules as USR;
use Kwaadpepper\CrudPolicies\Policies\RootPolicy;
class AnswerPolicy extends RootPolicy
{
/**
* Init policies on call
*
* @return void
*/
public function setPolicies()
{
/**
* This first rule to return true in a policy action authorises the action
*/
$this->policies = [
'answer' => [
'viewAny' => USR::make('everyOne'),
'update' => USR::make('everyOne'),
'create' => USR::make('everyOne'),
'delete' => USR::make('everyOne')
]
];
}
}

View file

@ -0,0 +1,30 @@
<?php
namespace App\Policies;
use App\Policies\Rules\UserStaticRules as USR;
use Kwaadpepper\CrudPolicies\Policies\RootPolicy;
class QuestionPolicy extends RootPolicy
{
/**
* Init policies on call
*
* @return void
*/
public function setPolicies()
{
/**
* This first rule to return true in a policy action authorises the action
*/
$this->policies = [
'question' => [
'viewAny' => USR::make('everyOne'),
'view' => USR::make('everyOne'),
'update' => USR::make('everyOne'),
'create' => USR::make('everyOne'),
'delete' => USR::make('everyOne')
]
];
}
}

View file

@ -2,9 +2,11 @@
namespace App\Providers;
use App\Models\Answer;
use App\Models\Brand;
use App\Models\Customer;
use App\Models\CustomerInfo;
use App\Models\Question;
use App\Models\Service;
use App\Models\SingleOptin;
use Illuminate\Cache\RateLimiting\Limit;
@ -42,6 +44,8 @@ class RouteServiceProvider extends ServiceProvider
Route::model('brand', Brand::class);
Route::model('service', Service::class);
Route::model('single_optin', SingleOptin::class);
Route::model('question', Question::class);
Route::model('answer', Answer::class);
Route::bind('customer', function ($value) {
if (\ctype_digit($value)) {

View file

@ -231,6 +231,7 @@ return [
'CustomerExportType' => App\Enums\CustomerExportType::class,
'Brand' => App\Models\Brand::class,
'Customer' => App\Models\Customer::class,
'Answer' => App\Models\Answer::class,
],
];

View file

@ -6,6 +6,8 @@ return [
'brands' => 'Brands',
'brand' => 'Brand',
'customers' => 'Customers',
'questions' => 'Questions',
'answers' => 'Answers',
'singleoptins' => 'Single Opt-ins'
],
'common' => [
@ -17,6 +19,9 @@ return [
'published' => 'Published',
'group' => 'Group',
'default' => 'Default',
'optinDate' => 'Date opt-in'
'optinDate' => 'Date opt-in',
'question' => 'Question',
'answer' => 'Answer',
'type' => 'Type'
]
];

View file

@ -5,6 +5,8 @@ return [
'services' => 'Services',
'brands' => 'Marques',
'brand' => 'Marque',
'questions' => 'Questions',
'answers' => 'Réponses',
'customers' => 'Clients',
'singleoptins' => 'Opt-ins uniques'
],
@ -17,6 +19,9 @@ return [
'published' => 'Publié',
'group' => 'Groupe',
'default' => 'Par défaut',
'optinDate' => 'Date opt-in'
'optinDate' => 'Date opt-in',
'question' => 'Question',
'type' => 'Type',
'answer' => 'Réponse'
]
];

View file

@ -0,0 +1,119 @@
@extends($viewLayout)
@section('title', sprintf('%s - %s', transFb(sprintf('models.classes.%s', strtolower(Str::plural(class_basename($modelClass)))), Str::plural(class_basename($modelClass))), __('crud-policies::crud.viewAny')))
@section('description', sprintf('%s %s', __('crud-policies::crud.viewAny'), trans(Str::plural(class_basename($modelClass)))))
@section('metaIndex', 'noindex,nofollow')
@section('content')
<div class="card">
@include('crud-policies::crud.modules.flashMessage')
<div class="card-header">
@include('crud-policies::crud.modules.breadcrumb', ['action' => CrudAction::viewAny()])
@include('crud-policies::crud.modules.actionbar.bar', ['action' => CrudAction::viewAny()])
</div>
<div class="card-body">
<div class="row justify-content-center">
<div class="col">
{{ $models->links() }}
</div>
<div class="col">
<form action="{{ url()->current() }}">
<div class="input-group mb-3">
<input type="search" name="search" class="form-control" value="{{ request()->search }}"/>
<input type="text" name="sort_col" class="d-none" value="{{ request()->sort_col }}"/>
<input type="text" name="sort_way" class="d-none" value="{{ request()->sort_way }}"/>
<a class="btn btn-danger" href="{{ url()->current() }}">{{ __('crud-policies::crud.reset') }}</a>
<button type="submit" class="btn btn-primary">
{{ __('crud-policies::crud.search') }}
</button>
</div>
</form>
</div>
</div>
<div class="row justify-content-center">
<h2>{{ request()->question->question }}</h2>
</div>
<table class="table text-center">
<thead class="thead-dark">
@include('crud-policies::crud.modules.sorter')
</thead>
<tbody>
@if(count($models))
{{-- INIT QUERIES for OPTIMIZING --}}
@foreach ($modelClass::getEditableProperties() as $fieldName => $prop)
@if($prop['type']->equals(CrudType::order()))
@php ${"$modelTable$fieldName"} = $modelClass::max($fieldName); @endphp
@endif
@if($prop['type']->equals(CrudType::belongsTo()))
@php try { $models->load(Str::singular((new $prop['belongsTo']())->getTable())); } catch(\Exception $e) {} @endphp
@endif
@if($prop['type']->equals(CrudType::belongsToMany()))
@php $models->load("$fieldName"); @endphp
@endif
@endforeach
{{-- DISPLAY MODELS --}}
@foreach($models as $model)
<tr>
@foreach ($modelClass::getEditableProperties() as $fieldName => $prop)
@if(in_array(CrudAction::viewAny(), $prop['actions']))
@switch($prop['type'])
@case(CrudType::belongsToMany() and $prop['belongsToMany'] === \App\Models\Project::class)
<td>
@foreach($model->{$fieldName} as $pSite)
<a href="{{ CrudController::getRoutePrefixed($pSite->getTable().'.show', $pSite) }}">{{ $pSite->{$prop['belongsToManyLabel']} }}</a>
@endforeach
</td>
@break
@case(CrudType::password())
{{-- Ignore --}}
@break
@default
<td>@include('crud-policies::crud.printfield', [
'action' => CrudAction::viewAny(),
'field' => $model->{$fieldName},
'props' => $prop,
"$modelTable$fieldName" => ${"$modelTable$fieldName"} ?? null
])</td>
@endswitch
@endif
@endforeach
{{-- MODEL ACTIONS --}}
<td>
<div class="btn-group" role="group" aria-label="{{ Str::plural(__('crud-policies::crud.action')) }}">
@can('view', $model)
<a href="{{ CrudController::getRoutePrefixed("$modelTable.show", $model) }}" class="btn btn-sm btn-primary">{{ __('crud-policies::crud.view') }}</a>
@endcan
@can('update', $model)
<a href="{{ CrudController::getRoutePrefixed("$modelTable.edit", $model) }}" class="btn btn-sm btn-info">{{ __('crud-policies::crud.edit') }}</a>
@endcan
@can('delete', $model)
<form action="{{ CrudController::getRoutePrefixed("$modelTable.destroy", $model) }}" method="POST" onsubmit="__CRUD.confirmDelete(event)">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-danger">{{ __('crud-policies::crud.delete') }}</button>
</form>
@endcan
</div>
</td>
</tr>
@endforeach
@else
<tr>
<td colspan="{{ count($modelClass::getEditableProperties()) }}">
{{ __('crud-policies::crud.nothingtoshow') }}
</td>
</tr>
@endif
</tbody>
</table>
{{ $models->links() }}
</div>
<div class="row justify-content-center mt-5 mb-5">
<div class="col-1">{{ $models->links() }}</div>
</div>
</div>
@include('crud-policies::crud.modules.scriptConstants')
@endsection

View file

@ -1,8 +1,15 @@
<th scope="col">
@php $colname = 'customers.email' @endphp
{{ __('Email')}}
@if(!session("crud.$modelTable.sort_way") or session("crud.$modelTable.sort_col") !== $colname or (session("crud.$modelTable.sort_way") === 'desc' and session("crud.$modelTable.sort_col") === $colname))
<a class="col_sort text-secondary lead asc" href="{{ request()->fullUrlWithQuery(['sort_col' => $colname, 'sort_way' => 'asc', 'rst' => null]) }}">&nbsp;&darr;&nbsp;</a>
@endif
@if(!session("crud.$modelTable.sort_way") or session("crud.$modelTable.sort_col") !== $colname or (session("crud.$modelTable.sort_way") === 'asc' and session("crud.$modelTable.sort_col") === $colname))
<a class="col_sort text-secondary lead desc" href="{{ request()->fullUrlWithQuery(['sort_col' => $colname, 'sort_way' => 'desc', 'rst' => null]) }}">&nbsp;&uarr;&nbsp;</a>
@endif
</th>
<th scope="col">
@php $colname = 'lastname' @endphp
@php $colname = 'customer_infos.lastname' @endphp
{{ __('Nom')}}
@if(!session("crud.$modelTable.sort_way") or session("crud.$modelTable.sort_col") !== $colname or (session("crud.$modelTable.sort_way") === 'desc' and session("crud.$modelTable.sort_col") === $colname))
<a class="col_sort text-secondary lead asc" href="{{ request()->fullUrlWithQuery(['sort_col' => $colname, 'sort_way' => 'asc', 'rst' => null]) }}">&nbsp;&darr;&nbsp;</a>
@ -12,7 +19,7 @@
@endif
</th>
<th scope="col">
@php $colname = 'firstname' @endphp
@php $colname = 'customer_infos.firstname' @endphp
{{ __('Prénom')}}
@if(!session("crud.$modelTable.sort_way") or session("crud.$modelTable.sort_col") !== $colname or (session("crud.$modelTable.sort_way") === 'desc' and session("crud.$modelTable.sort_col") === $colname))
<a class="col_sort text-secondary lead asc" href="{{ request()->fullUrlWithQuery(['sort_col' => $colname, 'sort_way' => 'asc', 'rst' => null]) }}">&nbsp;&darr;&nbsp;</a>
@ -22,7 +29,7 @@
@endif
</th>
<th scope="col">
@php $colname = 'opt_in' @endphp
@php $colname = 'customer_infos.opt_in' @endphp
{{ __('Opt-In')}}
@if(!session("crud.$modelTable.sort_way") or session("crud.$modelTable.sort_col") !== $colname or (session("crud.$modelTable.sort_way") === 'desc' and session("crud.$modelTable.sort_col") === $colname))
<a class="col_sort text-secondary lead asc" href="{{ request()->fullUrlWithQuery(['sort_col' => $colname, 'sort_way' => 'asc', 'rst' => null]) }}">&nbsp;&darr;&nbsp;</a>
@ -32,10 +39,34 @@
@endif
</th>
<th scope="col">
@php $colname = 'brands.name' @endphp
{{ __('Marque')}}
@if(!session("crud.$modelTable.sort_way") or session("crud.$modelTable.sort_col") !== $colname or (session("crud.$modelTable.sort_way") === 'desc' and session("crud.$modelTable.sort_col") === $colname))
<a class="col_sort text-secondary lead asc" href="{{ request()->fullUrlWithQuery(['sort_col' => $colname, 'sort_way' => 'asc', 'rst' => null]) }}">&nbsp;&darr;&nbsp;</a>
@endif
@if(!session("crud.$modelTable.sort_way") or session("crud.$modelTable.sort_col") !== $colname or (session("crud.$modelTable.sort_way") === 'asc' and session("crud.$modelTable.sort_col") === $colname))
<a class="col_sort text-secondary lead desc" href="{{ request()->fullUrlWithQuery(['sort_col' => $colname, 'sort_way' => 'desc', 'rst' => null]) }}">&nbsp;&uarr;&nbsp;</a>
@endif
</th>
<th scope="col">
@php $colname = 'customer_logins.status' @endphp
{{ __('Activé ?')}}
@if(!session("crud.$modelTable.sort_way") or session("crud.$modelTable.sort_col") !== $colname or (session("crud.$modelTable.sort_way") === 'desc' and session("crud.$modelTable.sort_col") === $colname))
<a class="col_sort text-secondary lead asc" href="{{ request()->fullUrlWithQuery(['sort_col' => $colname, 'sort_way' => 'asc', 'rst' => null]) }}">&nbsp;&darr;&nbsp;</a>
@endif
@if(!session("crud.$modelTable.sort_way") or session("crud.$modelTable.sort_col") !== $colname or (session("crud.$modelTable.sort_way") === 'asc' and session("crud.$modelTable.sort_col") === $colname))
<a class="col_sort text-secondary lead desc" href="{{ request()->fullUrlWithQuery(['sort_col' => $colname, 'sort_way' => 'desc', 'rst' => null]) }}">&nbsp;&uarr;&nbsp;</a>
@endif
</th>
<th scope="col">
@php $colname = 'customer_logins.last_connection' @endphp
{{ __('Dernière connexion')}}
@if(!session("crud.$modelTable.sort_way") or session("crud.$modelTable.sort_col") !== $colname or (session("crud.$modelTable.sort_way") === 'desc' and session("crud.$modelTable.sort_col") === $colname))
<a class="col_sort text-secondary lead asc" href="{{ request()->fullUrlWithQuery(['sort_col' => $colname, 'sort_way' => 'asc', 'rst' => null]) }}">&nbsp;&darr;&nbsp;</a>
@endif
@if(!session("crud.$modelTable.sort_way") or session("crud.$modelTable.sort_col") !== $colname or (session("crud.$modelTable.sort_way") === 'asc' and session("crud.$modelTable.sort_col") === $colname))
<a class="col_sort text-secondary lead desc" href="{{ request()->fullUrlWithQuery(['sort_col' => $colname, 'sort_way' => 'desc', 'rst' => null]) }}">&nbsp;&uarr;&nbsp;</a>
@endif
</th>
<th scope="col">
{{ __('Voir')}}

View file

@ -1,7 +1,7 @@
@extends('layouts.app')
@section('title', sprintf('%s - %s', transFb(sprintf('models.classes.%s', strtolower(Str::plural(class_basename($modelClass)))), Str::plural(class_basename($modelClass))), __('crud-policies::crud.viewAny')))
@section('description', sprintf('%s %s', __('crud-policies::crud.viewAny'), trans(Str::plural(class_basename($modelClass)))))
@section('title', sprintf('%s - %s', Str::ucfirst(Str::plural(trans('models.classes.customers'))), __('crud-policies::crud.viewAny')))
@section('description', sprintf('%s %s', __('crud-policies::crud.viewAny'), Str::ucfirst(Str::plural(trans('models.classes.customers')))))
@section('metaIndex', 'noindex,nofollow')
@section('content')
@ -73,7 +73,10 @@
{{ $customerInfo->brand->name }}
</td>
<td>
{{ $customerInfo->login()->status ? 'Oui' :'Non' }}
{{ $customerInfo->status ? 'Oui' :'Non' }}
</td>
<td>
{{ $customerInfo->last_connection }}
</td>
{{-- MODEL ACTIONS --}}

View file

@ -18,7 +18,8 @@
</ul>
<hr>
@foreach($modelsClasses as $crudModel)
@php if($crudModel === Customer::class) continue; @endphp
@php if($crudModel === \App\Models\Answer::class) continue; @endphp
@php if($crudModel === \App\Models\Customer::class) continue; @endphp
@if(
auth()->user()->can('viewAny', $crudModel) or
auth()->user()->can('create', $crudModel)

View file

@ -0,0 +1,4 @@
@if(request()->question)
<a href="{{ route('questions.show', request()->question) }}" class="btn btn-success float-end">{{ Str::ucfirst(__('models.common.question')) }}</a>
<a href="{{ route('questions.answers.index', request()->question) }}" class="btn btn-dark float-end">{{ Str::ucfirst(__('models.classes.answers')) }}</a>
@endif

View file

@ -0,0 +1,44 @@
@if ($message = Session::get('success'))
<div class="alert alert-success alert-dismissible fade show">
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
<strong>{!! nl2br(e($message)) !!}</strong>
</div>
@endif
@if ($message = Session::get('error'))
<div class="alert alert-danger alert-dismissible fade show">
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
<strong>{!! nl2br(e($message)) !!}</strong>
</div>
@endif
@if ($message = Session::get('warning'))
<div class="alert alert-warning alert-dismissible fade show">
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
<strong>{!! nl2br(e($message)) !!}</strong>
</div>
@endif
@if ($message = Session::get('info'))
<div class="alert alert-info alert-dismissible fade show">
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
<strong>{!! nl2br(e($message)) !!}</strong>
</div>
@endif
@if ($errors->any())
<div class="alert alert-danger alert-dismissible fade show">
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
@if ($errors->any())
<ul class="list-unstyled">
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
@endif
</div>
@endif

View file

@ -0,0 +1,126 @@
@extends($viewLayout)
@section('title', sprintf('%s - %s', transFb(sprintf('models.classes.%s', strtolower(Str::plural(class_basename($modelClass)))), Str::plural(class_basename($modelClass))), __('crud-policies::crud.viewAny')))
@section('description', sprintf('%s %s', __('crud-policies::crud.viewAny'), trans(Str::plural(class_basename($modelClass)))))
@section('metaIndex', 'noindex,nofollow')
@section('content')
<div class="card">
@include('crud-policies::crud.modules.flashMessage')
<div class="card-header">
@include('crud-policies::crud.modules.breadcrumb', ['action' => CrudAction::viewAny()])
@include('crud-policies::crud.modules.actionbar.bar', ['action' => CrudAction::viewAny()])
</div>
<div class="card-body">
<div class="row justify-content-center">
<div class="row justify-content-center">
<div class="col">
<form action="{{ url()->current() }}">
<div class="input-group mb-3">
<label class="input-group-text" for="brandSelect">{{ __('Filter par Marque') }}</label>
<select class="form-select" id="brandSelect">
<option value="0" @if(!request()->brand) selected @endif>{{ __('Sélectionnez une marque..') }}</option>
@foreach(Brand::all() as $brand)
<option value="{{ $brand->id }}" @if(request()->brand == "$brand->id") selected @endif>{{ $brand->name }}</option>
@endforeach
</select>
<label class="input-group-text bg-warning" for="searchField">🔍🠚</label>
<input type="search" id="searchField" name="search" class="form-control" value="{{ request()->search }}" placeholder="Recherche.."/>
<input type="text" name="sort_col" class="d-none" value="{{ request()->sort_col }}"/>
<input type="text" name="sort_way" class="d-none" value="{{ request()->sort_way }}"/>
@if(request()->brand)
<input type="hidden" name="brand" class="d-none" value="{{ request()->brand }}"/>
@endif
<a class="btn btn-danger" href="{{ url()->current() }}">{{ __('crud-policies::crud.reset') }}</a>
<button type="submit" class="btn btn-primary">
{{ __('crud-policies::crud.search') }}
</button>
</div>
</form>
</div>
</div>
{{ $models->appends(Request::except('rst'))->links() }}
<table class="table text-center">
<thead class="thead-dark">
@include('crud-policies::crud.modules.sorter')
</thead>
<tbody>
@if(count($models))
{{-- INIT QUERIES for OPTIMIZING --}}
@foreach ($modelClass::getEditableProperties() as $fieldName => $prop)
@if($prop['type']->equals(CrudType::order()))
@php ${"$modelTable$fieldName"} = $modelClass::max($fieldName); @endphp
@endif
@if($prop['type']->equals(CrudType::belongsTo()))
@php try { $models->load(Str::singular((new $prop['belongsTo']())->getTable())); } catch(\Exception $e) {} @endphp
@endif
@if($prop['type']->equals(CrudType::belongsToMany()))
@php $models->load("$fieldName"); @endphp
@endif
@endforeach
{{-- DISPLAY MODELS --}}
@foreach($models as $model)
<tr>
@foreach ($modelClass::getEditableProperties() as $fieldName => $prop)
@if(in_array(CrudAction::viewAny(), $prop['actions']))
@switch($prop['type'])
@case(CrudType::belongsToMany() and $prop['belongsToMany'] === \App\Models\Project::class)
<td>
@foreach($model->{$fieldName} as $pSite)
<a href="{{ CrudController::getRoutePrefixed($pSite->getTable().'.show', $pSite) }}">{{ $pSite->{$prop['belongsToManyLabel']} }}</a>
@endforeach
</td>
@break
@case(CrudType::password())
{{-- Ignore --}}
@break
@default
<td>@include('crud-policies::crud.printfield', [
'action' => CrudAction::viewAny(),
'field' => $model->{$fieldName},
'props' => $prop,
"$modelTable$fieldName" => ${"$modelTable$fieldName"} ?? null
])</td>
@endswitch
@endif
@endforeach
{{-- MODEL ACTIONS --}}
<td>
<div class="btn-group" role="group" aria-label="{{ Str::plural(__('crud-policies::crud.action')) }}">
@can('view', $model)
<a href="{{ CrudController::getRoutePrefixed("$modelTable.show", $model) }}" class="btn btn-sm btn-primary">{{ __('crud-policies::crud.view') }}</a>
@endcan
@can('update', $model)
<a href="{{ CrudController::getRoutePrefixed("$modelTable.edit", $model) }}" class="btn btn-sm btn-info">{{ __('crud-policies::crud.edit') }}</a>
@endcan
@can('delete', $model)
<form action="{{ CrudController::getRoutePrefixed("$modelTable.destroy", $model) }}" method="POST" onsubmit="__CRUD.confirmDelete(event)">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-danger">{{ __('crud-policies::crud.delete') }}</button>
</form>
@endcan
@can('viewAny', \App\Models\Answer::class)
<a href="{{ CrudController::getRoutePrefixed("questions.answers.index", $model) }}" class="btn btn-sm btn-dark">{{ Str::ucfirst(__('models.classes.answers')) }}</a>
@endcan
</div>
</td>
</tr>
@endforeach
@else
<tr>
<td colspan="{{ count($modelClass::getEditableProperties()) }}">
{{ __('crud-policies::crud.nothingtoshow') }}
</td>
</tr>
@endif
</tbody>
</table>
{{ $models->links() }}
</div>
</div>
@include('crud-policies::crud.modules.scriptConstants')
@endsection

View file

@ -0,0 +1,21 @@
<div class="btn-group float-end" role="group" aria-label="{{ Str::plural(__('crud-policies::crud.action')) }}">
@switch($action)
@case(CrudAction::viewAny())
@include('modules.crudAction')
@include('crud-policies::crud.modules.actionbar.create')
@break
@case(CrudAction::view())
@include('modules.crudAction')
@include('crud-policies::crud.modules.actionbar.update')
@include('crud-policies::crud.modules.actionbar.delete')
@break
@case(CrudAction::create())
@include('modules.crudAction')
@break
@case(CrudAction::update())
@include('modules.crudAction')
@include('crud-policies::crud.modules.actionbar.view')
@include('crud-policies::crud.modules.actionbar.delete')
@break
@endswitch
</div>

View file

@ -0,0 +1,3 @@
@can('create', $modelClass)
<a href="{{ CrudController::getRoutePrefixed("$modelTable.create") }}" class="btn btn-primary float-end">{{ __('crud-policies::crud.create') }}</a>
@endcan

View file

@ -0,0 +1,7 @@
@can('delete', $model)
<form action="{{ CrudController::getRoutePrefixed("$modelTable.destroy", $model)}}" method="POST" onsubmit="__CRUD.confirmDelete(event)">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger">{{ __('crud-policies::crud.delete') }}</button>
</form>
@endcan

View file

@ -0,0 +1,3 @@
@can('update', $model)
<a href="{{ CrudController::getRoutePrefixed("$modelTable.edit", $model)}}" class="btn btn-info ">{{ __('crud-policies::crud.update') }}</a>
@endcan

View file

@ -0,0 +1,3 @@
@can('view', $model)
<a href="{{ CrudController::getRoutePrefixed("$modelTable.show", $model) }}" class="btn btn-primary ">{{ __('crud-policies::crud.view') }}</a>
@endcan

View file

@ -1,8 +1,10 @@
<?php
use App\Http\Controllers\AnswerController;
use App\Http\Controllers\BrandController;
use App\Http\Controllers\CustomerController;
use App\Http\Controllers\LoginController;
use App\Http\Controllers\QuestionController;
use App\Http\Controllers\ServiceController;
use App\Http\Controllers\SingleOptinController;
use Illuminate\Support\Facades\Route;
@ -50,4 +52,11 @@ Route::middleware(['auth'])->group(function () {
// Single optins
Route::resource('single_optins', SingleOptinController::class);
Route::post('/single_optins/{id}/delete', [SingleOptinController::class, 'delete'])->name('single-optins-delete');
// Questions
Route::resource('questions', QuestionController::class);
Route::resource('questions.answers', AnswerController::class);
// Answers
// Route::resource('answers', AnswerController::class);
});