Add Gamme model (1/2)

This commit is contained in:
Sebastien Hattry 2021-12-20 17:21:09 +01:00
parent 4c68e0e68e
commit daad721b17
18 changed files with 610 additions and 1 deletions

View file

@ -0,0 +1,108 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\StoreGammeRequest;
use App\Http\Requests\UpdateGammeRequest;
use App\Models\Gamme;
class GammesController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$gammes = Gamme::orderBy('created_at', 'DESC')->get();
// $gammes = Gamme::whereNull('parent_id')->orderBy('created_at', 'DESC')->get();
return view('back.gammes.index', compact('gammes'));
}
/**
* Show the form for creating a new resource.
*
* @param Gamme $gamme
* @return \Illuminate\Http\Response
*/
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
public function create(Gamme $gamme)
{
return view('back.gammes.create', compact('gamme'));
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\StoreGammeRequest $request
* @return \Illuminate\Http\Response
*/
public function store(StoreGammeRequest $request)
{
$gamme = new Gamme($request->validated());
$response = $this->changeUniquePostOnTop($gamme->on_top);
if ($response) {
$response = $gamme->saveOrFail();
}
if (!$response) {
return redirect()->route('bo.gammes.edit', $gamme->id)->with('error', 'L\'actualité n\'a pas été créee');
}
return redirect()->route('bo.gammes.edit', $gamme->id)->with('success', 'Actualité créée !');
}
/**
* Show the form for editing the specified resource.
*
* @param Gamme $gamme
* @return \Illuminate\Http\Response
*/
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
public function edit(Gamme $gamme)
{
return view('back.gammes.edit', compact('gamme'));
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\UpdateGammeRequest $request
* @param Gamme $gamme
* @return \Illuminate\Http\Response
*/
public function update(Gamme $gamme, UpdateGammeRequest $request)
{
$gamme->fill($request->validated());
$response = $this->changeUniquePostOnTop($gamme->on_top);
if ($response) {
$response = $gamme->saveOrFail();
}
if (!$response) {
return redirect()->route('bo.gammes.edit', $gamme->id)
->with('error', trans('La modification a échoué'));
}
return redirect()->route('bo.gammes.edit', $gamme->id)
->with('success', trans('Modifications enregistrées !'));
}
/**
* Remove the specified resource from storage.
*
* @param Gamme $gamme
* @return \Illuminate\Http\Response
*/
public function destroy(Gamme $gamme)
{
if (!$gamme->delete()) {
return redirect()->route('bo.gammes.index')->with('error', trans('La suppression a échoué'));
}
return redirect()->route('bo.gammes.index')->with('success', trans('Suppression faite avec succès'));
}
}

View file

@ -0,0 +1,37 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreGammeRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return auth()->check();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'parent_gamme_id' => 'required|exists:gammes,id',
'title' => 'required|max:255',
'text' => 'required|max:255',
'color' => 'sometimes',
'picture' => 'required|image|mimes:jpeg,png,jpg|max:1024|dimensions:width=575,height=375',
'alt_text_picture' => 'required|max:255',
'banner' => 'required|image|mimes:jpeg,png,jpg|max:2048|dimensions:width=1169,height=243',
'alt_text_banner' => 'required|max:255',
];
}
}

View file

@ -0,0 +1,34 @@
<?php
namespace App\Http\Requests;
class UpdateGammeRequest extends StoreGammeRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return array_merge(
parent::rules(),
[
'picture' => [
'sometimes',
'image',
'mimes:jpeg,png,jpg',
'max:1024',
'dimensions:width=575,height=375'
],
'banner' => [
'sometimes',
'image',
'mimes:jpeg,png,jpg',
'max:2048',
'dimensions:width=1169,height=243'
],
]
);
}
}

55
app/Models/Gamme.php Normal file
View file

@ -0,0 +1,55 @@
<?php
namespace App\Models;
use App\Lib\Utils;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Gamme extends Model
{
use HasFactory;
protected $fillable = [
'parent_id',
'title',
'text',
'color',
'picture',
'alt_text_picture',
'banner',
'alt_text_banner',
];
protected static function boot()
{
static::creating(function (Gamme $gamme) {
if ($gamme->picture) {
$gamme->picture = Utils::storeImage($gamme->picture, $gamme->getTable());
}
if ($gamme->banner) {
$gamme->banner = Utils::storeImage($gamme->banner, $gamme->getTable());
}
});
static::updating(function (Gamme $gamme) {
if ($gamme->picture) {
$gamme->picture = Utils::storeImage($gamme->picture, $gamme->getTable());
}
if ($gamme->banner) {
$gamme->banner = Utils::storeImage($gamme->banner, $gamme->getTable());
}
});
parent::boot();
}
public function childGammes()
{
return $this->hasMany(Gamme::class, 'parent_gamme_id');
}
public function parentGamme()
{
return $this->belongsTo(Gamme::class);
}
}

View file

@ -27,4 +27,9 @@ return [
'post_news_image_maxwidth' => '380',
'post_news_image_maxheight' => '298',
'gamme_image_maxwidth' => '575',
'gamme_image_maxheight' => '375',
'gamme_banner_maxwidth' => '1169',
'gamme_banner_maxheight' => '243',
];

View file

@ -0,0 +1,28 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use SplFileInfo;
class GammeFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
'parent_gamme_id' => null,
'title' => $this->faker->word(),
'text' => $this->faker->text(5),
'color' => $this->faker->hexColor(),
'picture' => new SplFileInfo(resource_path('assets/images/cookrange.jpg')),
'alt_text_picture' => $this->faker->sentence(10),
'banner' => new SplFileInfo(resource_path('assets/images/cat_bckg.jpg')),
'alt_text_banner' => $this->faker->sentence(10),
];
}
}

View file

@ -0,0 +1,39 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateGammesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('gammes', function (Blueprint $table) {
$table->id();
$table->smallInteger('parent_gamme_id')->nullable();
$table->string('title');
$table->string('text');
$table->string('color')->nullable();
$table->string('picture')->nullable();
$table->string('alt_text_picture')->nullable();
$table->string('banner')->nullable();
$table->string('alt_text_banner')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('gammes');
}
}

View file

@ -24,6 +24,7 @@ class DatabaseSeeder extends Seeder
TextsSeeder::class,
AdviceSeeder::class,
PostsSeeder::class,
GammesSeeder::class,
]);
}
}

View file

@ -0,0 +1,41 @@
<?php
namespace Database\Seeders;
use App\Models\Gamme;
use Illuminate\Database\Seeder;
use SplFileInfo;
class GammesSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
$tabGammes = [];
Gamme::factory(5)->create()
->each(function (Gamme $gamme) use (&$tabGammes) {
array_push($tabGammes, $gamme->color);
});
foreach ($tabGammes as $key => $value) {
for ($i = 0; $i < 2; $i++) {
$gamme = new Gamme();
$id = $key + 1;
$gamme->parent_gamme_id = $id;
$gamme->title = 'lorem ipsum';
$gamme->text = 'lorem ipsum set doloris';
$gamme->color = $value;
$gamme->picture = new SplFileInfo(resource_path('assets/images/cookrange.jpg'));
$gamme->alt_text_picture = 'lorem utus garis';
$gamme->banner = new SplFileInfo(resource_path('assets/images/cat_bckg.jpg'));
$gamme->alt_text_banner = 'redus faros';
$gamme->save();
}
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 KiB

After

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 KiB

After

Width:  |  Height:  |  Size: 211 KiB

View file

@ -0,0 +1,66 @@
@extends('layouts.backend')
@section('content')
<form action="{{route('bo.slides.store')}}" method="POST" enctype="multipart/form-data">
@csrf
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2"><a href="{{route('bo.slides.index')}}" class="h2 text-decoration-none">
< </a> {{ __('Slides') }} <small class="text-muted">{{ __('Création') }}</small></h1>
<div class="btn-toolbar mb-2 mb-md-0">
<button type="submit" class="btn btn-sm btn-primary">{{ __('Enregistrer') }}</a>
</div>
</div>
@include('back.slides.form-inputs')
</form>
@endsection
@section('scripts')
<script type="text/javascript">
var editorConfig = {
removePlugins: ["Image", "ImageCaption", "ImageStyle", "ImageToolbar", "ImageUpload"],
toolbar: ['heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', '|', 'blockQuote', 'insertTable', '|', 'undo', 'redo'],
heading: {
options: [{
model: 'paragraph',
title: 'Paragraph',
class: 'ck-heading_paragraph'
},
{
model: 'heading1',
view: 'h1',
title: 'Heading 1',
class: 'ck-heading_heading1'
},
{
model: 'heading2',
view: 'h2',
title: 'Heading 2',
class: 'ck-heading_heading2'
},
{
model: 'heading3',
view: 'h3',
title: 'Heading 3',
class: 'ck-heading_heading3'
},
{
model: 'heading4',
view: 'h4',
title: 'Heading 4',
class: 'ck-heading_heading4'
}
]
},
table: {
contentToolbar: ['tableColumn', 'tableRow', 'mergeTableCells']
}
};
ClassicEditor
.create(document.querySelector('#text'), editorConfig)
.catch(error => {
console.error(error);
});
</script>
@endsection

View file

@ -0,0 +1,67 @@
@extends('layouts.backend')
@section('content')
<form action="{{route('bo.slides.update', $slide->id)}}" method="POST" enctype="multipart/form-data">
@method('PUT')
@csrf
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2"><a href="{{route('bo.slides.index')}}" class="h2 text-decoration-none">
< </a> {{ __('Slide') }} <small class="text-muted">{{ __('Edition') }}</small></h1>
<div class="btn-toolbar mb-2 mb-md-0">
<button type="submit" class="btn btn-sm btn-primary">{{ __('Enregistrer') }}</a>
</div>
</div>
@include('back.slides.form-inputs')
</form>
@endsection
@section('scripts')
<script type="text/javascript">
var editorConfig = {
removePlugins: ["Image", "ImageCaption", "ImageStyle", "ImageToolbar", "ImageUpload"],
toolbar: ['heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', '|', 'blockQuote', 'insertTable', '|', 'undo', 'redo'],
heading: {
options: [{
model: 'paragraph',
title: 'Paragraph',
class: 'ck-heading_paragraph'
},
{
model: 'heading1',
view: 'h1',
title: 'Heading 1',
class: 'ck-heading_heading1'
},
{
model: 'heading2',
view: 'h2',
title: 'Heading 2',
class: 'ck-heading_heading2'
},
{
model: 'heading3',
view: 'h3',
title: 'Heading 3',
class: 'ck-heading_heading3'
},
{
model: 'heading4',
view: 'h4',
title: 'Heading 4',
class: 'ck-heading_heading4'
}
]
},
table: {
contentToolbar: ['tableColumn', 'tableRow', 'mergeTableCells']
}
};
ClassicEditor
.create(document.querySelector('#text'), editorConfig)
.catch(error => {
console.error(error);
});
</script>
@endsection

View file

@ -0,0 +1,61 @@
<div class="form-group">
<label for="name">{{ __('Nom') }} *</label>
<input type="text" id="title" name="title" class="form-control" placeholder="{{ __('Nom') }} *" value="{{ old('title', $gamme->title ?? '') }}" required>
@include('back.modules.input-error', ['inputName'=>'title'])
</div>
<div class="form-group">
<label for="name">{{ __('Texte') }}</label>
<input type="text" id="text" name="text" class="form-control" placeholder="{{ __('Texte') }} *" value="{{ old('text', $gamme->text ?? '') }}" required>
@include('back.modules.input-error', ['inputName'=>'text'])
</div>
<div class="form-group">
<label for="picture">{{ __('Vignette') }} <small class="text-muted">- JPEG/PNG, 1Mo max. Dimensions {{ Config::get('bo.gamme_image_maxwidth') }} px par {{ Config::get('bo.gamme_image_maxheight') }} px</small></label><br/>
<input type="file" id="picture" name="picture" accept="image/png, image/jpeg" required>
@if ($gamme->picture !== null)
<br/>
<br/>
<img src="{{$gamme->picture}}" alt="{{$gamme->title}}" style="max-height: 100px;">
@endif
@include('back.modules.input-error', ['inputName'=>'picture'])
</div>
<div class="form-group">
<label for="name">{{ __('Text alternatif de la vignette') }} *</label>
<input type="text" id="alt_text_picture" name="alt_text_picture" class="form-control" placeholder="{{ __('Texte alternatif de la vignette') }} *" value="{{ old('alt_text_picture', $gamme->alt_text_picture ?? '') }}" required>
@include('back.modules.input-error', ['inputName'=>'alt_text_picture'])
</div>
<div class="form-group">
<label for="banner">{{ __('Bannière') }} <small class="text-muted">- JPEG/PNG, 2Mo max. Dimensions {{ Config::get('bo.gamme_banner_maxwidth') }} px par {{ Config::get('bo.gamme_banner_maxheight') }} px</small></label><br/>
<input type="file" id="banner" name="banner" accept="image/png, image/jpeg" required>
@if ($gamme->banner !== null)
<br/>
<br/>
<img src="{{$gamme->banner}}" alt="{{$gamme->title}}" style="max-height: 100px;">
@endif
@include('back.modules.input-error', ['inputName'=>'banner'])
</div>
<div class="form-group">
<label for="name">{{ __('Text alternatif de la bannière') }} *</label>
<input type="text" id="alt_text_banner" name="alt_text_banner" class="form-control" placeholder="{{ __('Texte alternatif de la bannière') }} *" value="{{ old('alt_text_banner', $gamme->alt_text_banner ?? '') }}" required>
@include('back.modules.input-error', ['inputName'=>'alt_text_banner'])
</div>
<div class="form-row">
<div class="form-group col">
<label for="slider_id">{{ __('Gamme parente') }}</label>
<select class="custom-select" id="gamme_parent_id" name="gamme_parent_id">
<option value="0">Pas de parent</option>
@foreach($gammes as $gamme)
<option value="{{$gamme->id}}" @if ($gamme->id === $gamme->gamme_parent_id) selected @endif>{{$gamme->title}}</option>
@endforeach
</select>
</div>
<div class="form-group col"></div>
<div class="form-group col"></div>
<div class="form-group col"></div>
@include('back.modules.input-error', ['inputName'=>'gamme_parent_id'])
</div>
<div class="form-group">
<label for="colorInput" class="form-label">Couleur de la gamme</label>
<input type="color" class="form-control form-control-color" name="colorInput" id="colorInput" value="#563d7c" title="Choisissez la couleur">
@include('back.modules.input-error', ['inputName'=>'colorInput'])
</div>

View file

@ -0,0 +1,49 @@
@extends('layouts.backend')
@section('content')
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">{{ __('Gammes') }} <small class="text-muted">{{ __('Liste') }}</small></h1>
@if ($errors->any())
@foreach($errors->all() as $error)
<span class="float-center text-danger">{{ $error }}</span>
@endforeach
@endif
<a href="{{route('bo.gammes.create')}}" class="btn btn-primary float-right">{{ __('Créer une gamme') }}</a>
</div>
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col">{{ __('Nom') }}</th>
<th scope="col">{{ __('Texte') }}</th>
<th scope="col">{{ __('Vignette') }}</th>
<th scope="col">{{ __('Couleur') }}</th>
<th scope="col">{{ __('Gamme parente') }}</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
@foreach($gammes as $gamme)
<tr>
<td>{{$gamme->title}}</td>
<td>{{$gamme->text}}</td>
<td><img src="{{ asset($gamme->picture) }}" height="50px"></td>
<td><input type="color" class="form-control form-control-color" id="exampleColorInput" value="{{$gamme->color}}" disabled></td>
<td>
@if (isset($gamme->parentGamme))
<a href="{{route('bo.gammes.edit', $gamme->parentGamme->id) }}">{{$gamme->parentGamme->title}}</a>
@endif
</td>
<td>
<a href="{{route('bo.gammes.edit', ['gamme' => $gamme->id])}}" class="btn btn-sm btn-primary">{{ __('Éditer') }}</a>
<form action="{{route('bo.gammes.destroy', $gamme->id)}}" method="POST" class="d-inline">
@method('DELETE')
@csrf
<input type="submit" class="btn btn-sm btn-danger" value="Supprimer" onclick="return confirm('Êtes-vous sûr(e) ?')">
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
@endsection

View file

@ -58,6 +58,22 @@
</div>
</div>
</div>
{{-- PAGE PRODUITS --}}
<div class="accordion-item mb-1">
<h2 class="accordion-header" id="headingGammes">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseGammes" aria-expanded="false" aria-controls="collapseGammes">
{{ __('Gammes') }}
</button>
</h2>
<div id="collapseGammes" class="accordion-collapse collapse" aria-labelledby="headingGammes">
<div class="accordion-body">
<div class="mb-3">
<a class="nav-link py-0 ms-4" href="{{route('bo.gammes.index')}}">{{ __('Toutes les gammes') }}</a>
<a class="nav-link py-0 ms-4" href="{{route('bo.gammes.create')}}">{{ __('Ajouter une gamme') }}</a>
</div>
</div>
</div>
</div>
{{-- PAGE ACTUALITES --}}
<div class="accordion-item mb-1">
<h2 class="accordion-header" id="headingNews">

View file

@ -31,7 +31,7 @@
<path class="cnt" d="M.85,16.34,7.34,9.17.82,2.07C4.21.91,5.86,2.13,11,9.15,5.8,16.53,3.87,18,.85,16.34Z" />
</svg>
</a>
<a href="{{ route('products') }}" class="scroller menu__link">
<a href="{{ route('gammes') }}" class="scroller menu__link">
<li class="menu__item">
Produits
</li>

View file

@ -13,6 +13,7 @@
use App\Http\Controllers\Bo\AdviceController;
use App\Http\Controllers\Bo\EncartsController;
use App\Http\Controllers\Bo\GammesController;
use App\Http\Controllers\Bo\HomeController;
use App\Http\Controllers\Bo\PictoBrandsController;
use App\Http\Controllers\Bo\PictosController;
@ -77,6 +78,7 @@ Route::prefix('bo')
Route::resource('pictos', PictosController::class)->except(['show']);
Route::resource('posts', PostsController::class)->except(['show']);
Route::resource('pictobrands', PictoBrandsController::class)->except(['show']);
Route::resource('gammes', GammesController::class)->except(['show']);
Route::resource('advice', AdviceController::class)
->except(['index', 'create', 'store', 'destroy', 'show']);
Route::resource('texts', TextsController::class)->except(['show']);