Merge branch 'develop' into trunk
This commit is contained in:
commit
49c926cc8b
53 changed files with 2452 additions and 253 deletions
|
|
@ -19,5 +19,6 @@ enum ApproachTypeEnum: int
|
|||
private const LABELS = [
|
||||
self::label->name => 'validation.custom.label',
|
||||
self::demarche->name => 'validation.custom.demarche',
|
||||
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ enum StaticPageType: int
|
|||
case search = 20;
|
||||
case sitemap = 21;
|
||||
case rules = 22;
|
||||
case exitOutside = 23;
|
||||
case ouiCBon = 24;
|
||||
|
||||
/**
|
||||
* Optionnal labels definition.
|
||||
|
|
@ -59,6 +61,8 @@ enum StaticPageType: int
|
|||
self::search->name => 'Recherche',
|
||||
self::sitemap->name => 'Plan du site',
|
||||
self::rules->name => 'Règlement du jeu',
|
||||
self::exitOutside->name => 'Sortir à l\'extérieur',
|
||||
self::ouiCBon->name => 'Oui c\'est bon'
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
|||
200
app/Http/Controllers/Bo/CategoryApproachesController.php
Normal file
200
app/Http/Controllers/Bo/CategoryApproachesController.php
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Bo\CategoryApproaches\CategoryApproachRequest;
|
||||
use App\Models\CategoryApproach;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class CategoryApproachesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create the controller instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->authorizeResource(CategoryApproach::class, 'categories_approach');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(Request $request): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$categories = CategoryApproach::query();
|
||||
$count = CategoryApproach::count();
|
||||
/** @var string $search Search field */
|
||||
$search = $request->search;
|
||||
if ($search) {
|
||||
$this->searchQuery(
|
||||
$categories,
|
||||
$search,
|
||||
null,
|
||||
'name',
|
||||
);
|
||||
}
|
||||
$searchFields = \implode(', ', [
|
||||
trans('validation.attributes.name'),
|
||||
]);
|
||||
|
||||
/** Sort columns with a query */
|
||||
$this->sortQuery($categories);
|
||||
$categories = $categories->getModels();
|
||||
|
||||
return view(
|
||||
'bo.pages.categories_approaches.index',
|
||||
compact('categories', 'count', 'searchFields', 'search')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @param \App\Models\CategoryApproach $categoryApproaches
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function create(CategoryApproach $categoryApproaches)
|
||||
{
|
||||
$count = CategoryApproach::count();
|
||||
if ($count >= CategoryApproach::MAX_CATEGORIES) {
|
||||
return redirect()
|
||||
->route('bo.categories.approaches.index')
|
||||
->with('error', "Limite atteinte : vous ne pouvez pas créer plus de " . CategoryApproach::MAX_CATEGORIES . " catégories.");
|
||||
}
|
||||
|
||||
return view('bo.pages.categories_approaches.create', ['categoryApproachesModel' => $categoryApproaches]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\CategoryApproaches\CategoryApproachRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(CategoryApproachRequest $request): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
if (CategoryApproach::count() >= CategoryApproach::MAX_CATEGORIES) {
|
||||
throw ValidationException::withMessages([
|
||||
'name' => "Limite atteinte : maximum " . CategoryApproach::MAX_CATEGORIES . " catégories."
|
||||
]);
|
||||
}
|
||||
return DB::transaction(function () use ($request) {
|
||||
$category = new CategoryApproach();
|
||||
$category->fill($request->validated());
|
||||
|
||||
if ($category->saveOrFail()) {
|
||||
return redirect()->route('bo.categories.approaches.index')
|
||||
->with('success', trans('crud.messages.has_been_created', [
|
||||
'model' => Str::ucfirst(trans('validation.custom.category'))
|
||||
]));
|
||||
}
|
||||
});
|
||||
return redirect()->back()
|
||||
->with('error', trans('crud.messages.cannot_be_created', [
|
||||
'model' => Str::ucfirst(trans('validation.custom.category'))
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\CategoryApproach $categories_approach
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit(CategoryApproach $categories_approach): \Illuminate\Contracts\View\View
|
||||
{
|
||||
return view('bo.pages.categories_approaches.edit', [
|
||||
'categoryApproachesModel' => $categories_approach
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\CategoryApproach $categories_approach
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function show(CategoryApproach $categories_approach): \Illuminate\Contracts\View\View
|
||||
{
|
||||
return view('bo.pages.categories_approaches.show', [
|
||||
'categoryApproachesModel' => $categories_approach
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Request\Bo\CategoryApproaches\CategoryApproachRequest $request
|
||||
* @param \App\Models\CategoryApproach $categories_approach
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(CategoryApproachRequest $request, CategoryApproach $categories_approach)
|
||||
{
|
||||
|
||||
if ($categories_approach->update($request->validated())) {
|
||||
return redirect()
|
||||
->route('bo.categories.approaches.index')
|
||||
->with('success', trans('crud.messages.has_been_updated', [
|
||||
'model' => Str::ucfirst(trans_choice('models.classes.categoryApproach', 1))]));
|
||||
}
|
||||
return redirect()->route('bo.categories.approaches.edit', $categories_approach)
|
||||
->with('error', trans('crud.messages.cannot_be_updated', [
|
||||
'model' => Str::ucfirst(trans_choice('models.classes.categoryApproach', 1))
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\CategoryApproach $categories_approach
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function destroy(CategoryApproach $categories_approach): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
|
||||
if (CategoryApproach::count() === CategoryApproach::MIN_CATEGORIES) {
|
||||
return redirect()
|
||||
->route('bo.categories.approaches.index')
|
||||
->with('error', "Limite atteinte : vous ne pouvez pas supprimer toutes les catégories (une catégorie minimum).");
|
||||
}
|
||||
if ($categories_approach->delete()) {
|
||||
return redirect()
|
||||
->route('bo.categories.approaches.index')
|
||||
->with('success', trans('crud.messages.has_been_deleted', [
|
||||
'model' => Str::ucfirst(trans_choice('models.classes.categoryApproach', 1))]));
|
||||
}
|
||||
return redirect()->back()
|
||||
->with('success', trans('crud.messages.cannot_be_deleted', [
|
||||
'model' => Str::ucfirst(trans_choice('models.classes.categoryApproach', 1))]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param CategoryApproach $section_approach
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function duplicate(CategoryApproach $categories_approach)
|
||||
{
|
||||
return $this->create($categories_approach->replicate());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a paginate resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function jsonPaginateCategory(Request $request): \Illuminate\Http\JsonResponse
|
||||
{
|
||||
$categoryApproachModel = $request->targetModel::query()->orderBy('name', 'ASC')->paginate();
|
||||
return \response()->json($categoryApproachModel);
|
||||
}
|
||||
}
|
||||
202
app/Http/Controllers/Bo/SectionApproachController.php
Normal file
202
app/Http/Controllers/Bo/SectionApproachController.php
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Enums\StaticPageType;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Bo\SectionApproaches\SectionApproachRequest;
|
||||
use App\Models\SectionApproach;
|
||||
use App\Services\SectionApproach\SectionApproachService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class SectionApproachController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Create the controller instance.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly SectionApproachService $sectionApproachService
|
||||
) {
|
||||
$this->authorizeResource(SectionApproach::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(Request $request): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$sections = SectionApproach::with(['category', 'page']);
|
||||
$formData = $this->sectionApproachService->getFormData();
|
||||
/** @var string $search Search field */
|
||||
$search = $request->search;
|
||||
if ($search) {
|
||||
$this->searchQuery(
|
||||
$sections,
|
||||
$search,
|
||||
null,
|
||||
'title',
|
||||
);
|
||||
}
|
||||
$searchFields = \implode(', ', [
|
||||
trans_choice('models.classes.sectionApproach', 1),
|
||||
]);
|
||||
$this->sortQuery($sections);
|
||||
|
||||
$sections = $this->paginate($sections);
|
||||
|
||||
return view(
|
||||
'bo.pages.sections_approaches.index',
|
||||
compact('sections', 'search', 'searchFields') + $formData
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @param \App\Models\SectionApproach $section_approach
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function create(SectionApproach $section_approach): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$formData = $this->sectionApproachService->getFormData();
|
||||
|
||||
return view('bo.pages.sections_approaches.create', [
|
||||
'sectionApproachModel' => $section_approach,
|
||||
'categoryApproachModel' => $formData['categories'],
|
||||
'staticPageModel' => $formData['pages'],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\SectionApproaches\SectionApproachRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(SectionApproachRequest $request): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
try {
|
||||
$section = $this->sectionApproachService->store($request->validated());
|
||||
|
||||
return redirect()
|
||||
->route('bo.sections.approaches.edit', $section)
|
||||
->with('success', trans('crud.messages.has_been_created', [
|
||||
'model' => Str::ucfirst(trans_choice('models.classes.sectionApproach', 1)),
|
||||
]));
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->back()->withInput()->withErrors(['category_id' => $e->getMessage()]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the specified resource.
|
||||
*
|
||||
* @param \App\Models\SectionApproach $section_approach
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function show(SectionApproach $section_approach): \Illuminate\Contracts\View\View
|
||||
{
|
||||
return view(
|
||||
'bo.pages.sections_approaches.show',
|
||||
['sectionApproachModel' => $section_approach]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\SectionApproach $section_approach
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit(SectionApproach $section_approach): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$formData = $this->sectionApproachService->getFormData();
|
||||
return view(
|
||||
'bo.pages.sections_approaches.edit',
|
||||
['sectionApproachModel' => $section_approach]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\SectionApproaches\SectionApproachRequest $request
|
||||
* @param \App\Models\SectionApproach $section_approach
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(SectionApproachRequest $request, SectionApproach $section_approach): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request, $section_approach) {
|
||||
try {
|
||||
$this->sectionApproachService->update($section_approach, $request->validated());
|
||||
|
||||
return redirect()
|
||||
->route('bo.sections.approaches.edit', $section_approach)
|
||||
->with('success', trans('crud.messages.has_been_updated', [
|
||||
'model' => Str::ucfirst(trans_choice('models.classes.sectionApproach', 1)),
|
||||
]));
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->back()->withInput()->withErrors(['category_id' => $e->getMessage()]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param SectionApproach $section_approach
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function destroy(SectionApproach $section_approach): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($section_approach) {
|
||||
try {
|
||||
$this->sectionApproachService->destroy($section_approach);
|
||||
|
||||
return redirect()
|
||||
->route('bo.sections.approaches.index')
|
||||
->with('success', trans('crud.messages.has_been_deleted', [
|
||||
'model' => Str::ucfirst(trans_choice('models.classes.sectionApproach', 1)),
|
||||
]));
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->back()->withErrors(['delete' => $e->getMessage()]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicate the specified section approach by pre-filling the create form.
|
||||
*
|
||||
* @param SectionApproach $section_approach
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
|
||||
*/
|
||||
public function duplicate(SectionApproach $section_approach): \Illuminate\Contracts\View\View
|
||||
{
|
||||
return $this->create($section_approach->replicate());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a paginate resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function jsonPaginatePage(Request $request): \Illuminate\Http\JsonResponse
|
||||
{
|
||||
$staticPageModel = $request->targetModel::whereIn('type', [
|
||||
StaticPageType::ouiCBon,
|
||||
StaticPageType::exitOutside,
|
||||
])->paginate();
|
||||
|
||||
return response()->json($staticPageModel);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,10 +4,8 @@ namespace App\Http\Controllers\Club;
|
|||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Club\MesBr\PrintCouponsRequest;
|
||||
use App\Models\Customer;
|
||||
use App\Models\Discount;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
class DiscountController extends Controller
|
||||
{
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class MessageController extends Controller
|
|||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(): \Illuminate\Contracts\View\View
|
||||
{
|
||||
{
|
||||
return view('club.pages.messages.index');
|
||||
}
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ class MessageController extends Controller
|
|||
->choose();
|
||||
return $conversation;
|
||||
})->all();
|
||||
|
||||
|
||||
// * Notifications
|
||||
$notifications = $customer->notifications()
|
||||
->where('notifiable_type', Message::class)
|
||||
|
|
|
|||
|
|
@ -2,9 +2,13 @@
|
|||
|
||||
namespace App\Http\Controllers\Fo;
|
||||
|
||||
use App\Enums\StaticPageType;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Lib\Helpers\CollectionHelper;
|
||||
use App\Models\CategoryApproach;
|
||||
use App\Models\NewsBreeding;
|
||||
use App\Models\OcbBreeder;
|
||||
use App\Models\SectionApproach;
|
||||
use App\Models\StaticPage;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
|
|
@ -63,4 +67,25 @@ class BreedingController extends Controller
|
|||
'asideNewsModels' => $asideNewsModels
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the given breeding page.
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function exitOutsidePage(): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$staticPage = StaticPage::query()->where('type', StaticPageType::exitOutside)->first();
|
||||
$sliderImages = CollectionHelper::mapSlidesToFields($staticPage->data);
|
||||
$categoryApproachModels = CategoryApproach::all();
|
||||
$sections = SectionApproach::query()->where('page_id', $staticPage->id)->get();
|
||||
$sectionApproachModels = CollectionHelper::mapItemsToCards($sections->toArray(), $categoryApproachModels->toArray());
|
||||
|
||||
return view('fo.pages.breeding.sortant-a-l-exterieur', [
|
||||
'staticPageModel' => $staticPage,
|
||||
'sliderImages' => $sliderImages,
|
||||
'categoryApproachModels' => $categoryApproachModels,
|
||||
'sectionApproachModels' => $sectionApproachModels
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@
|
|||
|
||||
namespace App\Http\Controllers\Fo;
|
||||
|
||||
use App\Models\StaticPage;
|
||||
use App\Models\OptinConsent;
|
||||
use Illuminate\Http\Request;
|
||||
use LDC\LDCCRM\Models\SingleOptin;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Fo\ConsentRequest;
|
||||
|
|
@ -23,7 +21,6 @@ class ConsentController extends Controller
|
|||
* @throws \LDC\LDCCRM\Exceptions\CrmException CrmException
|
||||
* @throws \LDC\LDCCRM\Exceptions\ApiErrorException ApiErrorException
|
||||
*/
|
||||
|
||||
public function consent(ConsentRequest $request): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$isSubscribed = false;
|
||||
|
|
|
|||
|
|
@ -54,13 +54,13 @@ class ContactController extends Controller
|
|||
if (ContactFormType::make($validatedData['type'])->equals(ContactFormType::complain)) {
|
||||
// Send to Passerelle if it is a complain about a product.
|
||||
\dispatch(new SendPasserelleMail($data, $joinFilePath));
|
||||
} else if (isset($validatedData['locale']) && ContactFormType::make($validatedData['locale'])->equals(ContactFormType::nl)) {
|
||||
} elseif (isset($validatedData['locale']) && ContactFormType::make($validatedData['locale'])->equals(ContactFormType::nl)) {
|
||||
// Send to Export Mailing List if it is a complain from NL page.
|
||||
app()->setLocale('nl');
|
||||
\dispatch(new SendNLMail($data, $joinFilePath));
|
||||
} else {
|
||||
// Send to the CRM.
|
||||
if ($joinFilePath) {
|
||||
if ($joinFilePath) {
|
||||
$relativePath = str_replace(storage_path('app/public') . '/', '', $joinFilePath);
|
||||
$binary = Storage::disk('public')->get($relativePath);
|
||||
$base64 = base64_encode($binary);
|
||||
|
|
@ -83,7 +83,7 @@ class ContactController extends Controller
|
|||
|
||||
// Send mail.
|
||||
\dispatch(new SendClaimMail($data, $joinFilePath));
|
||||
}
|
||||
}//end if
|
||||
|
||||
return back()->with('success', trans('contact.message_contact_send'));
|
||||
} catch (AbortContactMailer $e) {
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ class HomeController extends Controller
|
|||
*/
|
||||
public function index(): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$productCacheKey = 'HomeProductsViews' . (auth('club')->user() ? '_' . auth('club')->user()->id : '');
|
||||
$recipeCacheKey = 'HomeRecipesViews' . (auth('club')->user() ? '_' . auth('club')->user()->id : '');
|
||||
$productCacheKey = 'HomeProductsViews' . (auth('club')->user() ? '_' . auth('club')->user()->id : '');
|
||||
$recipeCacheKey = 'HomeRecipesViews' . (auth('club')->user() ? '_' . auth('club')->user()->id : '');
|
||||
$staticPageModel = StaticPage::getCachedStaticPage(StaticPageType::home);
|
||||
$mainSlideModels = MainSlide::getPublishedOrderedWithApproaches();
|
||||
$demarcheSlideModels = DemarcheSlide::getPublishedOrdered();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Bo\CategoryApproaches;
|
||||
|
||||
use App\Models\CategoryApproach;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
class CategoryApproachRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return Gate::check('create', CategoryApproach::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'nullable|string|between:3,255',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get custom attributes for validator errors.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function attributes(): array
|
||||
{
|
||||
return [
|
||||
'name' => trans('validation.attributes.name'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Bo\SectionApproaches;
|
||||
|
||||
use App\Models\SectionApproach;
|
||||
use App\Rules\WysiwygLength;
|
||||
use App\Traits\Requests\HasPicture;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
class SectionApproachRequest extends FormRequest
|
||||
{
|
||||
use HasPicture;
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return Gate::check('create', SectionApproach::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the data for validation.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->mergePicture('picture');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'title' => 'required|string|between:3,255',
|
||||
'content' => ['required','string',new WysiwygLength()],
|
||||
'picture_alt' => 'required_with:picture|nullable|between:3,255',
|
||||
'picture_title' => 'required_with:picture|nullable|between:3,255',
|
||||
'category_id' => 'required|exists:category_approaches,id',
|
||||
'page_id' => 'required|exists:static_pages,id'
|
||||
];
|
||||
return \array_merge(
|
||||
$rules,
|
||||
$this->pictureRules('picture', 75, 45, 90, 90)
|
||||
);
|
||||
}
|
||||
|
||||
public function attributes()
|
||||
{
|
||||
return [
|
||||
'name' => trans('validation.attributes.name'),
|
||||
'picture' => trans('validation.attributes.image'),
|
||||
'picture_alt' => trans('validation.custom.attribute_alt'),
|
||||
'picture_title' => trans('validation.custom.attribute_title'),
|
||||
'category_id' => trans('validattion.custom.category'),
|
||||
'page_id' => trans('validattion.custom.static_page_id'),
|
||||
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -67,6 +67,19 @@ class UpdateStaticPageRequest extends UpdateMiniCrudRequest
|
|||
) {
|
||||
$this->mergePicture('picture');
|
||||
}
|
||||
// check nullable value of image's slider
|
||||
if ($staticPageModel->type->equals(StaticPageType::exitOutside)) {
|
||||
$test = $this->data;
|
||||
foreach ($test as $key => $value) {
|
||||
if (Str::startsWith($key, 'slider_image_')) {
|
||||
$checkValue = isset($value['value']) ? $value['value'] : null;
|
||||
$test[$key]['value'] = $checkValue;
|
||||
$test[$key]['alt'] = (!is_null($checkValue) ? $value['alt'] : null);
|
||||
$test[$key]['title'] = (!is_null($checkValue) ? $value['title'] : null);
|
||||
}
|
||||
}
|
||||
$this->merge(['data' => $test]);
|
||||
}
|
||||
parent::prepareForValidation();
|
||||
}
|
||||
|
||||
|
|
@ -133,7 +146,9 @@ class UpdateStaticPageRequest extends UpdateMiniCrudRequest
|
|||
!$staticPageModel->type->equals(StaticPageType::legals) &&
|
||||
!$staticPageModel->type->equals(StaticPageType::confidentiality) &&
|
||||
!$staticPageModel->type->equals(StaticPageType::selling) &&
|
||||
!$staticPageModel->type->equals(StaticPageType::accessibility)
|
||||
!$staticPageModel->type->equals(StaticPageType::accessibility) &&
|
||||
!$staticPageModel->type->equals(StaticPageType::exitOutside) &&
|
||||
!$staticPageModel->type->equals(StaticPageType::ouiCBon)
|
||||
) {
|
||||
$rules = \array_merge(
|
||||
$rules,
|
||||
|
|
@ -149,7 +164,9 @@ class UpdateStaticPageRequest extends UpdateMiniCrudRequest
|
|||
!$staticPageModel->type->equals(StaticPageType::product) &&
|
||||
!$staticPageModel->type->equals(StaticPageType::home) &&
|
||||
!$staticPageModel->type->equals(StaticPageType::contact) &&
|
||||
!$staticPageModel->type->equals(StaticPageType::search)
|
||||
!$staticPageModel->type->equals(StaticPageType::search) &&
|
||||
!$staticPageModel->type->equals(StaticPageType::exitOutside) &&
|
||||
!$staticPageModel->type->equals(StaticPageType::ouiCBon)
|
||||
) {
|
||||
$rules = \array_merge(
|
||||
$rules,
|
||||
|
|
|
|||
|
|
@ -102,4 +102,105 @@ class CollectionHelper
|
|||
return view($path, [$key => $item])->render();
|
||||
})->toArray();
|
||||
}
|
||||
|
||||
public static function mapSlidesToFields(array $fields): array
|
||||
{
|
||||
return collect($fields)
|
||||
->filter(fn($field, $key) => str_starts_with($key, 'slider_image_'))
|
||||
->filter(fn($field) => !empty($field['value']))
|
||||
->sortKeys()
|
||||
->map(fn($field) => [
|
||||
'image' => [
|
||||
'path' => $field['value'],
|
||||
'title' => $field['title'] ?? '',
|
||||
'alt' => $field['alt'] ?? '',
|
||||
],
|
||||
])
|
||||
->values()
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform and merge 2 arrays to get homogeneous result
|
||||
*
|
||||
* @param array $items sections array
|
||||
* @param array $categories categories array
|
||||
* @return array
|
||||
*/
|
||||
public static function mapItemsToCards(array $items, array $categories): array
|
||||
{
|
||||
$categoriesById = collect($categories)->keyBy('id');
|
||||
$result = [];
|
||||
|
||||
foreach ($items as $item) {
|
||||
$category = $categoriesById->get($item['category_id']);
|
||||
if (!$category) {
|
||||
continue;
|
||||
}
|
||||
$categoryKey = $category['name'];
|
||||
$parsed = self::parseContent($item['content']);
|
||||
|
||||
$result[$categoryKey][] = [
|
||||
'category' => $item['title'],
|
||||
'icon' => [
|
||||
'path' => $item['picture'],
|
||||
'alt' => $item['picture_alt'],
|
||||
'description' => $item['picture_title'],
|
||||
],
|
||||
'content' => [
|
||||
[
|
||||
'title' => $parsed['title'],
|
||||
'points' => $parsed['points'],
|
||||
'asterisc' => $parsed['asterisc'],
|
||||
],
|
||||
],
|
||||
'class' => 'card-template-sm',
|
||||
];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
private static function parseContent(string $html): array
|
||||
{
|
||||
$dom = new \DOMDocument();
|
||||
@$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
|
||||
|
||||
// Extract h3
|
||||
$title = '';
|
||||
$h3 = $dom->getElementsByTagName('h3');
|
||||
if ($h3->length > 0) {
|
||||
$title = $h3->item(0)->textContent;
|
||||
}
|
||||
|
||||
// Extract li
|
||||
$points = [];
|
||||
$liNodes = $dom->getElementsByTagName('li');
|
||||
foreach ($liNodes as $li) {
|
||||
$points[] = trim($li->textContent);
|
||||
}
|
||||
|
||||
// Extract last <p> *
|
||||
$lastAsterisc = null;
|
||||
$pNodes = $dom->getElementsByTagName('p');
|
||||
foreach ($pNodes as $p) {
|
||||
$text = trim($p->textContent);
|
||||
if (str_starts_with($text, '*')) {
|
||||
$lastAsterisc = $text;
|
||||
}
|
||||
}
|
||||
// if nothing to extract
|
||||
if (empty($title) && empty($points)) {
|
||||
$body = $dom->getElementsByTagName('body')->item(0);
|
||||
$rawText = trim($body ? $body->textContent : strip_tags($html));
|
||||
if (!empty($rawText)) {
|
||||
$points[] = $rawText;
|
||||
}
|
||||
}
|
||||
return [
|
||||
'title' => $title,
|
||||
'points' => $points,
|
||||
'asterisc' => $lastAsterisc ?? '',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
98
app/Models/CategoryApproach.php
Normal file
98
app/Models/CategoryApproach.php
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
/**
|
||||
* CategoryApproach Model
|
||||
*
|
||||
* @property string $name Name of the category approach.
|
||||
* @property-read \Carbon\Carbon $created_at Creation timestamp.
|
||||
* @property-read \Carbon\Carbon $updated_at Last update timestamp.
|
||||
*/
|
||||
class CategoryApproach extends Model
|
||||
{
|
||||
/**
|
||||
* Maximum number of category approaches allowed in the system.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public const MAX_CATEGORIES = 5;
|
||||
|
||||
/**
|
||||
* Minimum number of category approaches required in the system.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public const MIN_CATEGORIES = 1;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* Defines which attributes can be filled via mass assignment operations.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name'
|
||||
];
|
||||
|
||||
/**
|
||||
* Validate that the maximum number of category approaches has not been exceeded.
|
||||
*
|
||||
* @return void
|
||||
* @throws \Exception If the maximum number of categories has been exceeded.
|
||||
*/
|
||||
protected function validateMaxCategoryCount(): void
|
||||
{
|
||||
if (static::count() > self::MAX_CATEGORIES) {
|
||||
throw new \Exception('Cannot create more than ' . self::MAX_CATEGORIES . ' category approaches.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that the minimum number of category approaches is maintained.
|
||||
*
|
||||
* @return void
|
||||
* @throws \Exception If deletion would violate the minimum category requirement.
|
||||
*/
|
||||
protected static function validateMinCategoryCount(): void
|
||||
{
|
||||
if (static::count() <= self::MIN_CATEGORIES) {
|
||||
throw new \Exception('At least ' . self::MIN_CATEGORIES . ' category approach is required.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booting(): void
|
||||
{
|
||||
static::creating(function (self $model) {
|
||||
$model->validateMaxCategoryCount();
|
||||
});
|
||||
|
||||
static::updating(function (self $model) {
|
||||
$model->validateMaxCategoryCount();
|
||||
});
|
||||
|
||||
static::deleting(function (self $model) {
|
||||
static::validateMinCategoryCount();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all section approaches associated with this category approach.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function sectionsApproaches(): HasMany
|
||||
{
|
||||
return $this->hasMany(SectionApproach::class, 'category_id');
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,6 @@ namespace App\Models;
|
|||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
|
||||
/**
|
||||
* @property string $email Email of the customer.
|
||||
* @property string $hashcode Hashcode of the customer.
|
||||
|
|
|
|||
133
app/Models/SectionApproach.php
Normal file
133
app/Models/SectionApproach.php
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Lib\Helpers\FileStorageHelper;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
/**
|
||||
* SectionApproach Model
|
||||
*
|
||||
* @property int $id Unique identifier of the section
|
||||
* @property string $title Title of the section
|
||||
* @property string $content Textual content of the section
|
||||
* @property string|null $picture Storage path of the image
|
||||
* @property string|null $picture_alt Alternative text of the image (accessibility)
|
||||
* @property string|null $picture_title Title of the image
|
||||
* @property int $category_id Identifier of the associated category
|
||||
* @property int $page_id Identifier of the associated static page
|
||||
* @property-read \Carbon\Carbon $created_at Creation timestamp.
|
||||
* @property-read \Carbon\Carbon $updated_at Last update timestamp.
|
||||
*
|
||||
* @property-read CategoryApproach $category Associated category
|
||||
* @property-read StaticPage $page Associated static page
|
||||
*/
|
||||
class SectionApproach extends Model
|
||||
{
|
||||
/**
|
||||
* Maximum number of sections allowed
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public const MAX_SECTIONS = 6;
|
||||
|
||||
/**
|
||||
* Minimum number of sections required
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public const MIN_SECTIONS = 2;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'title',
|
||||
'content',
|
||||
'picture',
|
||||
'picture_alt',
|
||||
'picture_title',
|
||||
'category_id',
|
||||
'page_id'
|
||||
];
|
||||
|
||||
/**
|
||||
* Validates that the maximum number of sections has not been exceeded.
|
||||
*
|
||||
* @return void
|
||||
* @throws \Exception If the maximum number of sections has been exceeded.
|
||||
*/
|
||||
protected function validateMaxSectionCount(): void
|
||||
{
|
||||
$sectionCount = static::where('category_id', $this->category_id)->where('page_id', $this->page_id)->count();
|
||||
if ($sectionCount >= self::MAX_SECTIONS) {
|
||||
throw new \Exception('Cannot create more than ' . self::MAX_SECTIONS . ' sections per category.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the minimum number of sections is maintained.
|
||||
*
|
||||
* @return void
|
||||
* @throws \Exception If deletion would violate the minimum section requirement.
|
||||
*/
|
||||
protected static function validateMinSectionCount(self $approach): void
|
||||
{
|
||||
$sectionCount = static::where('category_id', $approach->category_id)->where('page_id', $approach->page_id)->count();
|
||||
if ($sectionCount <= self::MIN_SECTIONS) {
|
||||
throw new \Exception('At least ' . self::MIN_SECTIONS . ' sections are required per category.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::creating(function (self $approach) {
|
||||
$approach->validateMaxSectionCount();
|
||||
$approach->picture = FileStorageHelper::storeFile($approach, $approach->picture, true);
|
||||
});
|
||||
|
||||
static::updating(function (self $approach) {
|
||||
$approach->picture = FileStorageHelper::storeFile($approach, $approach->picture, true);
|
||||
});
|
||||
|
||||
static::updated(function (self $approach) {
|
||||
FileStorageHelper::removeOldFile($approach, 'picture');
|
||||
});
|
||||
|
||||
static::deleting(function (self $approach) {
|
||||
static::validateMinSectionCount($approach);
|
||||
});
|
||||
|
||||
static::deleted(function (self $approach) {
|
||||
FileStorageHelper::removeFile($approach, 'picture');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Relationship: belongs to a category approach
|
||||
*
|
||||
* @return BelongsTo Returns the associated category
|
||||
*/
|
||||
public function category(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(CategoryApproach::class, 'category_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Relationship: belongs to a static page
|
||||
*
|
||||
* @return BelongsTo Returns the associated static page
|
||||
*/
|
||||
public function page(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(StaticPage::class);
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ use App\Traits\Models\ActivityLog;
|
|||
use App\Traits\Models\MiniCrudModel;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Str;
|
||||
use Spatie\SchemaOrg\Schema;
|
||||
|
|
@ -295,4 +296,9 @@ class StaticPage extends Model implements SchemaOrgInterface, RedirectableInterf
|
|||
{
|
||||
return $this->hasMany(NewsBreeding::class);
|
||||
}
|
||||
|
||||
public function sectionsApproaches(): HasMany
|
||||
{
|
||||
return $this->hasMany(SectionApproach::class, 'page_id');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
78
app/Policies/CategoryApproachPolicy.php
Normal file
78
app/Policies/CategoryApproachPolicy.php
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Enums\Users\RoleEnum;
|
||||
use App\Models\CategoryApproach;
|
||||
use App\Models\User;
|
||||
use App\Policies\Rules\UserStaticRules;
|
||||
|
||||
class CategoryApproachPolicy
|
||||
{
|
||||
/**
|
||||
* Determine whether the user can view any models.
|
||||
*/
|
||||
public function viewAny(): bool
|
||||
{
|
||||
return UserStaticRules::everyOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can view the model.
|
||||
*
|
||||
* @param \App\Models\User $authUser
|
||||
* @return boolean
|
||||
*/
|
||||
public function view(User $authUser): bool
|
||||
{
|
||||
return UserStaticRules::atLeastRole($authUser, RoleEnum::admin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can create a new model.
|
||||
*
|
||||
* @param \App\Models\User $authUser
|
||||
* @return boolean
|
||||
*/
|
||||
public function create(User $authUser): bool
|
||||
{
|
||||
if (CategoryApproach::count() <= CategoryApproach::MAX_CATEGORIES) {
|
||||
return UserStaticRules::atLeastRole($authUser, RoleEnum::admin);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*
|
||||
* @param \App\Models\User $authUser
|
||||
* @return boolean
|
||||
*/
|
||||
public function update(User $authUser): bool
|
||||
{
|
||||
return UserStaticRules::atLeastRole($authUser, RoleEnum::admin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can delete the model.
|
||||
*
|
||||
* @param \App\Models\User $authUser
|
||||
* @param \App\Models\CategoryApproach $category
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete(User $authUser): bool
|
||||
{
|
||||
return UserStaticRules::atLeastRole($authUser, RoleEnum::admin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can duplicate the model.
|
||||
*
|
||||
* @param \App\Models\User $authUser
|
||||
* @return boolean
|
||||
*/
|
||||
public function duplicate(User $authUser): bool
|
||||
{
|
||||
return UserStaticRules::atLeastRole($authUser, RoleEnum::admin);
|
||||
}
|
||||
}
|
||||
75
app/Policies/SectionApproachPolicy.php
Normal file
75
app/Policies/SectionApproachPolicy.php
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Enums\Users\RoleEnum;
|
||||
use App\Models\SectionApproach;
|
||||
use App\Models\User;
|
||||
use App\Policies\Rules\UserStaticRules;
|
||||
|
||||
class SectionApproachPolicy
|
||||
{
|
||||
/**
|
||||
* Determine whether the user can view any models.
|
||||
*/
|
||||
public function viewAny(): bool
|
||||
{
|
||||
return UserStaticRules::everyOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can view the model.
|
||||
*
|
||||
* @param \App\Models\User $authUser
|
||||
* @return boolean
|
||||
*/
|
||||
public function view(User $authUser): bool
|
||||
{
|
||||
return UserStaticRules::atLeastRole($authUser, RoleEnum::admin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can create a new model.
|
||||
*
|
||||
* @param \App\Models\User $authUser
|
||||
* @return boolean
|
||||
*/
|
||||
public function create(User $authUser): bool
|
||||
{
|
||||
return UserStaticRules::atLeastRole($authUser, RoleEnum::admin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*
|
||||
* @param \App\Models\User $authUser
|
||||
* @return boolean
|
||||
*/
|
||||
public function update(User $authUser, SectionApproach $section_approaches): bool
|
||||
{
|
||||
return UserStaticRules::atLeastRole($authUser, RoleEnum::admin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can delete the model.
|
||||
*
|
||||
* @param \App\Models\User $authUser
|
||||
* @param \App\Models\SectionApproaches $section
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete(User $authUser, SectionApproach $section_approaches): bool
|
||||
{
|
||||
return UserStaticRules::atLeastRole($authUser, RoleEnum::admin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can duplicate the model.
|
||||
*
|
||||
* @param \App\Models\User $authUser
|
||||
* @return boolean
|
||||
*/
|
||||
public function duplicate(User $authUser): bool
|
||||
{
|
||||
return UserStaticRules::atLeastRole($authUser, RoleEnum::admin);
|
||||
}
|
||||
}
|
||||
|
|
@ -133,6 +133,8 @@ class ViewServiceProvider extends ServiceProvider
|
|||
['name' => 'breedingHealthStaticPageModel', 'value' => StaticPage::getCachedStaticPage(StaticPageType::breedingHealth)],
|
||||
['name' => 'newsStaticPageModel', 'value' => StaticPage::getCachedStaticPage(StaticPageType::news)],
|
||||
['name' => 'searchStaticPageModel', 'value' => StaticPage::getCachedStaticPage(StaticPageType::search)],
|
||||
['name' => 'exitOutsideStaticPageModel', 'value' => StaticPage::getCachedStaticPage(StaticPageType::exitOutside)],
|
||||
['name' => 'ouiCestBonStaticPageModel', 'value' => StaticPage::getCachedStaticPage(StaticPageType::ouiCBon)],
|
||||
])->map(function ($array) {
|
||||
View::share($array['name'], (function () use ($array) {
|
||||
return $array['value'] ?: null;
|
||||
|
|
|
|||
140
app/Services/SectionApproach/SectionApproachService.php
Normal file
140
app/Services/SectionApproach/SectionApproachService.php
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services\SectionApproach;
|
||||
|
||||
use App\Models\CategoryApproach;
|
||||
use App\Models\SectionApproach;
|
||||
use App\Models\StaticPage;
|
||||
use App\Enums\StaticPageType;
|
||||
|
||||
class SectionApproachService
|
||||
{
|
||||
/**
|
||||
* Retrieve the data needed to populate create/edit forms.
|
||||
* Returns paginated categories and eligible static pages.
|
||||
*/
|
||||
public function getFormData(): array
|
||||
{
|
||||
return [
|
||||
'categories' => CategoryApproach::query()->orderBy('name', 'ASC')->paginate(),
|
||||
'pages' => StaticPage::whereIn('type', [StaticPageType::ouiCBon, StaticPageType::exitOutside])->paginate(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and persist a new section approach.
|
||||
* Throws an exception if the maximum number of sections per category/page is reached.
|
||||
*
|
||||
* @param array $validated rules validated in request
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function store(array $validated): SectionApproach
|
||||
{
|
||||
$pageId = (int) $validated['page_id'];
|
||||
$categoryId = (int) $validated['category_id'];
|
||||
|
||||
$page = StaticPage::findOrFail($pageId);
|
||||
$category = CategoryApproach::findOrFail($categoryId);
|
||||
|
||||
$count = SectionApproach::query()
|
||||
->where('page_id', $pageId)
|
||||
->where('category_id', $categoryId)
|
||||
->lockForUpdate()
|
||||
->count();
|
||||
|
||||
if ($count >= SectionApproach::MAX_SECTIONS) {
|
||||
throw new \Exception(
|
||||
"Limite atteinte : La catégorie ''{$category->name}'' dans la page ''{$page->title}'' contient déjà " . SectionApproach::MAX_SECTIONS . " sections."
|
||||
);
|
||||
}
|
||||
|
||||
$section = new SectionApproach();
|
||||
$section->fill($validated);
|
||||
$section->save();
|
||||
|
||||
return $section;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing section approach
|
||||
*
|
||||
* @param \App\Models\SectionApproach $section_approach model
|
||||
* @param array $validated rules validated in request
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function update(SectionApproach $section_approach, array $validated): SectionApproach
|
||||
{
|
||||
$section = SectionApproach::query()
|
||||
->whereKey($section_approach->id)
|
||||
->lockForUpdate()
|
||||
->firstOrFail();
|
||||
|
||||
$oldPageId = (int) $section->page_id;
|
||||
$oldCategoryId = (int) $section->category_id;
|
||||
$newPageId = (int) ($validated['page_id'] ?? $oldPageId);
|
||||
$newCategoryId = (int) ($validated['category_id'] ?? $oldCategoryId);
|
||||
$isMoving = ($oldPageId !== $newPageId) || ($oldCategoryId !== $newCategoryId);
|
||||
|
||||
if ($isMoving) {
|
||||
// Checkcategory retains the minimum number of sections
|
||||
$sourceCount = SectionApproach::query()
|
||||
->where('page_id', $oldPageId)
|
||||
->where('category_id', $oldCategoryId)
|
||||
->lockForUpdate()
|
||||
->count();
|
||||
|
||||
if ($sourceCount <= SectionApproach::MIN_SECTIONS) {
|
||||
throw new \Exception(
|
||||
"Déplacement impossible : la catégorie d'origine doit garder au minimum " . SectionApproach::MIN_SECTIONS . " sections."
|
||||
);
|
||||
}
|
||||
|
||||
// Check category has not reached the maximum number of sections
|
||||
$targetCount = SectionApproach::query()
|
||||
->where('page_id', $newPageId)
|
||||
->where('category_id', $newCategoryId)
|
||||
->lockForUpdate()
|
||||
->count();
|
||||
|
||||
if ($targetCount >= SectionApproach::MAX_SECTIONS) {
|
||||
throw new \Exception(
|
||||
"Déplacement impossible : la catégorie cible contient déjà " . SectionApproach::MAX_SECTIONS . " sections pour cette page."
|
||||
);
|
||||
}
|
||||
}//end if
|
||||
|
||||
$section->fill($validated);
|
||||
$section->save();
|
||||
|
||||
return $section;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a section approach.
|
||||
* Throws an exception if the category would fall below the minimum required sections.
|
||||
*
|
||||
* @param App\Models\SectionApproach $section_approach
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function destroy(SectionApproach $section_approach): void
|
||||
{
|
||||
$section = SectionApproach::query()
|
||||
->whereKey($section_approach->id)
|
||||
->lockForUpdate()
|
||||
->firstOrFail();
|
||||
|
||||
$count = SectionApproach::query()
|
||||
->where('page_id', $section->page_id)
|
||||
->where('category_id', $section->category_id)
|
||||
->lockForUpdate()
|
||||
->count();
|
||||
|
||||
if ($count <= SectionApproach::MIN_SECTIONS) {
|
||||
throw new \Exception(
|
||||
"Suppression impossible : une catégorie doit contenir au minimum " . SectionApproach::MIN_SECTIONS . " sections dans une page."
|
||||
);
|
||||
}
|
||||
|
||||
$section->delete();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('category_approaches', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('category_approaches');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('section_approaches', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('title');
|
||||
$table->text('content')->comment('content.');
|
||||
$table->string('picture')->comment('picture path.');
|
||||
$table->string('picture_alt')->comment('Picture alt attribute.');
|
||||
$table->string('picture_title')->comment('Picture title attribute.');
|
||||
$table->foreignId('category_id')->constrained('category_approaches')->cascadeOnDelete();
|
||||
$table->foreignId('page_id')->constrained('static_pages')->cascadeOnDelete();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('section_approaches');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
<?php
|
||||
|
||||
use App\Enums\StaticPageType;
|
||||
use App\Models\StaticPage;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
//SORTIR A L' EXTERIEUR
|
||||
StaticPage::updateOrCreate(
|
||||
['type' => StaticPageType::exitOutside],
|
||||
['data' => [
|
||||
'title' => [
|
||||
'label' => 'Cahier de charge : Titre',
|
||||
'inputType' => 11,
|
||||
'value' => '',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'description' => [
|
||||
'label' => 'Cahier de charge : Description',
|
||||
'inputType' => 12,
|
||||
'value' => '',
|
||||
'validate' => 'required|string|min:15',
|
||||
'required' => true
|
||||
],
|
||||
'picto' => [
|
||||
'label' => 'Cahier de charge : Picto',
|
||||
'inputType' => 4,
|
||||
'dimensions' => [
|
||||
'width' => 90,
|
||||
'height' => 90
|
||||
],
|
||||
'alt' => '',
|
||||
'title' => '',
|
||||
'value' => '',
|
||||
'validate' => 'required',
|
||||
'required' => true
|
||||
],
|
||||
'galery_title' => [
|
||||
'label' => 'Slider : Titre',
|
||||
'inputType' => 11,
|
||||
'value' => '',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'slider_image_1' => [
|
||||
'label' => 'Slider : Image 1',
|
||||
'inputType' => 4,
|
||||
'dimensions' => [
|
||||
'width' => 338,
|
||||
'height' => 222
|
||||
],
|
||||
'alt' => '',
|
||||
'title' => '',
|
||||
'value' => '',
|
||||
'validate' => 'required',
|
||||
'required' => true
|
||||
],
|
||||
'slider_image_2' => [
|
||||
'label' => 'Slider : Image 2',
|
||||
'inputType' => 4,
|
||||
'dimensions' => [
|
||||
'width' => 338,
|
||||
'height' => 222
|
||||
],
|
||||
'alt' => '',
|
||||
'title' => '',
|
||||
'value' => '',
|
||||
'validate' => 'required',
|
||||
'required' => true
|
||||
],
|
||||
'slider_image_3' => [
|
||||
'label' => 'Slider : Image 3',
|
||||
'inputType' => 4,
|
||||
'dimensions' => [
|
||||
'width' => 338,
|
||||
'height' => 222
|
||||
],
|
||||
'alt' => '',
|
||||
'title' => '',
|
||||
'value' => '',
|
||||
'validate' => 'required',
|
||||
'required' => true
|
||||
],
|
||||
'slider_image_4' => [
|
||||
'label' => 'Slider : Image 4',
|
||||
'inputType' => 4,
|
||||
'dimensions' => [
|
||||
'width' => 338,
|
||||
'height' => 222
|
||||
],
|
||||
'alt' => '',
|
||||
'title' => '',
|
||||
'value' => '',
|
||||
'validate' => 'nullable',
|
||||
'required' => false
|
||||
],
|
||||
'slider_image_5' => [
|
||||
'label' => 'Slider : Image 5',
|
||||
'inputType' => 4,
|
||||
'dimensions' => [
|
||||
'width' => 338,
|
||||
'height' => 222
|
||||
],
|
||||
'alt' => '',
|
||||
'title' => '',
|
||||
'value' => '',
|
||||
'validate' => 'nullable',
|
||||
'required' => false
|
||||
],
|
||||
'slider_image_6' => [
|
||||
'label' => 'Slider : Image 6',
|
||||
'inputType' => 4,
|
||||
'dimensions' => [
|
||||
'width' => 338,
|
||||
'height' => 222
|
||||
],
|
||||
'alt' => '',
|
||||
'title' => '',
|
||||
'value' => '',
|
||||
'validate' => 'nullable',
|
||||
'required' => false
|
||||
]
|
||||
]]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('static_pages', function () {
|
||||
$staticPage = StaticPage::query()->where('type', StaticPageType::exitOutside)->first();
|
||||
if ($staticPage) {
|
||||
$staticPage->data = [];
|
||||
$staticPage->saveQuietly();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -40,5 +40,7 @@ return [
|
|||
'discount' => 'réduction',
|
||||
'sell_item' => 'objet en vente|objets en vente',
|
||||
'rating' => 'note',
|
||||
'categoryApproach' => 'categorie|categories',
|
||||
'sectionApproach' => 'section|sections'
|
||||
]
|
||||
];
|
||||
|
|
|
|||
|
|
@ -344,6 +344,6 @@ return [
|
|||
'saturated_fatty_acids' => 'dont Acides Gras Saturés',
|
||||
'dietary_fiber' => 'fibres alimentaires',
|
||||
'salt' => 'sel',
|
||||
]
|
||||
],
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -131,9 +131,7 @@
|
|||
padding: 0.5rem 0.75rem;
|
||||
}
|
||||
|
||||
#chicken-button-outside,
|
||||
#chicken-button,
|
||||
#turkey-button {
|
||||
.category-btn {
|
||||
--bs-btn-padding-y: .25rem;
|
||||
--bs-btn-padding-x: .5rem;
|
||||
--bs-btn-font-size: .75rem;
|
||||
|
|
|
|||
|
|
@ -1,48 +1,41 @@
|
|||
document.addEventListener("DOMContentLoaded", function () {
|
||||
if (!document.querySelector("#oui-c-est-bon")) {
|
||||
return;
|
||||
}
|
||||
const buttons = document.querySelectorAll<HTMLButtonElement>(".category-btn");
|
||||
|
||||
const chickenButton = document.getElementById("chicken-button");
|
||||
const turkeyButton = document.getElementById("turkey-button");
|
||||
if (!buttons.length) return;
|
||||
|
||||
function toggleCards(selectedType: "chicken" | "turkey") {
|
||||
const chickenCards = document.querySelectorAll(".chicken-card");
|
||||
const turkeyCards = document.querySelectorAll(".turkey-card");
|
||||
const groups = document.querySelectorAll<HTMLElement>("[data-category]");
|
||||
|
||||
// Here I toggle visibility of cards
|
||||
chickenCards.forEach(card => card.classList.toggle("d-none", selectedType !== "chicken"));
|
||||
turkeyCards.forEach(card => card.classList.toggle("d-none", selectedType !== "turkey"));
|
||||
|
||||
function toggleCards(selectedCategory: string) {
|
||||
groups.forEach(group => {
|
||||
if (group.dataset.category === selectedCategory) {
|
||||
group.style.display = "contents";
|
||||
} else {
|
||||
group.style.display = "none";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handleButtonClick(event: MouseEvent) {
|
||||
const target = event.target as HTMLElement;
|
||||
const selectedType = target.id === "chicken-button" ? "chicken" : "turkey";
|
||||
const isChicken = selectedType === "chicken";
|
||||
if (chickenButton) {
|
||||
chickenButton.classList.toggle("btn-secondary", isChicken);
|
||||
chickenButton.classList.toggle("btn-light", !isChicken);
|
||||
}
|
||||
// Here we toggle buttons classes
|
||||
if (turkeyButton) {
|
||||
turkeyButton.classList.toggle("btn-secondary", !isChicken);
|
||||
turkeyButton.classList.toggle("btn-light", isChicken);
|
||||
}
|
||||
const target = event.target as HTMLButtonElement;
|
||||
const selectedCategory = target.dataset.category ?? "";
|
||||
|
||||
buttons.forEach(btn => {
|
||||
btn.classList.toggle("btn-secondary", btn.dataset.category === selectedCategory);
|
||||
btn.classList.toggle("btn-light", btn.dataset.category !== selectedCategory);
|
||||
});
|
||||
|
||||
// Show/Hide cards
|
||||
toggleCards(selectedType);
|
||||
toggleCards(selectedCategory);
|
||||
}
|
||||
|
||||
if (chickenButton) {
|
||||
chickenButton.addEventListener("click", handleButtonClick);
|
||||
}
|
||||
buttons.forEach(btn => btn.addEventListener("click", handleButtonClick));
|
||||
|
||||
if (turkeyButton) {
|
||||
turkeyButton.addEventListener("click", handleButtonClick);
|
||||
}
|
||||
const firstCategory = buttons[0].dataset.category ?? "";
|
||||
|
||||
// Set default card to chicken
|
||||
// things will change if data come from db
|
||||
toggleCards("chicken");
|
||||
});
|
||||
buttons.forEach(btn => {
|
||||
btn.classList.toggle("btn-secondary", btn.dataset.category === firstCategory);
|
||||
btn.classList.toggle("btn-light", btn.dataset.category !== firstCategory);
|
||||
});
|
||||
|
||||
toggleCards(firstCategory);
|
||||
});
|
||||
|
|
@ -1130,6 +1130,88 @@
|
|||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{{-- DEMARCHES --}}
|
||||
<div class="dropdown">
|
||||
<button data-bs-toggle="dropdown" type="button" aria-expanded="false" @class([
|
||||
'btn btn-primary text-start w-100 dropdown-toggle mt-1',
|
||||
'fw active' =>
|
||||
request()->routeIs('bo.approaches.*'),
|
||||
])>
|
||||
<i @class([
|
||||
'fa-solid fa-people-arrows fa-fw',
|
||||
'fa-lg' =>
|
||||
request()->routeIs('bo.approaches.*'),
|
||||
])></i>
|
||||
{{ __('Démarches') }}
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
{{-- PAGE SORTIR-A-L-EXTERIEUR --}}
|
||||
@if (isset($exitOutsideStaticPageModel))
|
||||
<li>
|
||||
<a href="{{ route('bo.static_pages.edit', $exitOutsideStaticPageModel) }}" @class([
|
||||
'dropdown-item px-3 py-2',
|
||||
'fw-bold text-bg-secondary' =>
|
||||
url()->current() ===
|
||||
route('bo.static_pages.edit', $exitOutsideStaticPageModel),
|
||||
])>
|
||||
<i @class([
|
||||
'fa-solid fa-file fa-fw',
|
||||
'fa-lg' =>
|
||||
url()->current() ===
|
||||
route('bo.static_pages.edit', $exitOutsideStaticPageModel),
|
||||
])></i>
|
||||
{{ str(__("Page Sortir à l'éxterieur"))->ucFirst() }}
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
{{-- OUI-C-BON --}}
|
||||
@if (isset($ouiCestBonStaticPageModel))
|
||||
<li>
|
||||
<a href="{{ route('bo.static_pages.edit', $ouiCestBonStaticPageModel ) }}" @class([
|
||||
'dropdown-item px-3 py-2',
|
||||
'fw-bold text-bg-secondary' =>
|
||||
url()->current() ===
|
||||
route('bo.static_pages.edit', $ouiCestBonStaticPageModel),
|
||||
|
||||
])>
|
||||
<i @class([
|
||||
'fa-solid fa-file fa-fw fa-fw',
|
||||
'fa-lg' =>
|
||||
url()->current() ===
|
||||
route('bo.static_pages.edit', $ouiCestBonStaticPageModel),
|
||||
])></i>
|
||||
{{ str(__("Page Oui c'est bon"))->ucFirst() }}
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
<hr>
|
||||
{{-- crud sections & categories --}}
|
||||
<li>
|
||||
<a href="{{ route('bo.sections.approaches.index') }}" @class([
|
||||
'dropdown-item px-3 py-2',
|
||||
'fw-bold text-bg-secondary' => request()->routeIs('bo.sections.approaches.*'),
|
||||
])>
|
||||
<i @class([
|
||||
'fa-solid fa-tags fa-fw',
|
||||
'fa-lg' => request()->routeIs('bo.sections.approaches.*'),
|
||||
])></i>
|
||||
{{ str(__('sections'))->ucFirst() }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ route('bo.categories.approaches.index') }}" @class([
|
||||
'dropdown-item px-3 py-2',
|
||||
'fw-bold text-bg-secondary' => request()->routeIs('bo.categories.approaches.*'),
|
||||
])>
|
||||
<i @class([
|
||||
'fa-solid fa-tags fa-fw',
|
||||
'fa-lg' => request()->routeIs('bo.categories.approaches.*'),
|
||||
])></i>
|
||||
{{ str(__('catégories'))->ucFirst() }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<hr>
|
||||
{{-- CONTACT --}}
|
||||
@if(isset($contactStaticPageModel))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
@extends('bo.layout', ['brParam' => $categoryApproachesModel])
|
||||
|
||||
@php
|
||||
$inter = __('validation.custom.of_the.female');
|
||||
$model = __(trans_choice('models.classes.categoryApproach', 1));
|
||||
@endphp
|
||||
@section('title', __('Création :inter :model', ['model' => trans_choice('models.classes.categoryApproach', 1), 'inter' => $inter]))
|
||||
@section('description', __('Création d\'un tout nouveau :model', ['model' => trans_choice('models.classes.categoryApproach', 1)]))
|
||||
@section('breadcrumb', request()->route()->getName())
|
||||
|
||||
@section('content')
|
||||
<div class="d-flex justify-content-between flex-md-nowrap align-items-center flex-wrap pb-3">
|
||||
<div class="d-flex align-items-start flex-row">
|
||||
<a class="btn btn-primary text-decoration-none m-0 me-2" data-bs-toggle="tooltip"
|
||||
href="{{ route('bo.categories.approaches.index') }}"
|
||||
title="{{ __('crud.helpers.list_all', ['model' => str(trans_choice('models.classes.categoryApproach', 2))->plural()]) }}">
|
||||
<i class="fa-solid fa-arrow-left"></i>
|
||||
</a>
|
||||
@include('modules.breadcrumbs.breadcrumb-body', [
|
||||
'brParam' => $categoryApproachesModel])
|
||||
</div>
|
||||
<div class="mb-md-0 mb-2">
|
||||
<button class="btn btn-primary" id="formSubmitClone" data-bs-toggle="tooltip" type="submit"
|
||||
title="{{ __('crud.helpers.save_model', ['model' => __(trans_choice('models.classes.categoryApproach', 1))]) }}">
|
||||
{{ str(__('crud.actions.save'))->ucfirst() }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<form
|
||||
action="{{ route('bo.categories.approaches.store') }}"
|
||||
method="POST" enctype="multipart/form-data">
|
||||
@csrf
|
||||
|
||||
@include('bo.pages.categories_approaches.form')
|
||||
@include('bo.partials.script-button-clone')
|
||||
<div class="row mt-3">
|
||||
<div class="col text-center">
|
||||
<button class="btn btn-primary" id="formSubmit" data-bs-toggle="tooltip" type="submit"
|
||||
title="{{ __('crud.helpers.save_model', ['model' => trans_choice('models.classes.categoryApproach', 1)]) }}">
|
||||
{{ str(__('crud.actions.save'))->ucfirst() }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@endsection
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
@extends('bo.layout', ['brParam' => $categoryApproachesModel])
|
||||
|
||||
@php
|
||||
$inter = __('validation.custom.of_the.female');
|
||||
$model = __(trans_choice('models.classes.categoryApproach', 1));
|
||||
@endphp
|
||||
@section('title', __('Édition :inter :model', ['model' => trans_choice('models.classes.categoryApproach', 1), 'inter' => $inter]))
|
||||
@section('description', __('Création d\'un tout nouveau :model', ['model' => trans_choice('models.classes.categoryApproach', 1)]))
|
||||
@section('breadcrumb', request()->route()->getName())
|
||||
|
||||
@section('content')
|
||||
<div class="d-flex justify-content-between flex-md-nowrap align-items-center flex-wrap pb-3">
|
||||
<div class="d-flex align-items-start flex-row">
|
||||
<a class="btn btn-primary text-decoration-none m-0 me-2" data-bs-toggle="tooltip"
|
||||
href="{{ route('bo.categories.approaches.index') }}"
|
||||
title="{{ __('crud.helpers.list_all', ['model' => str(trans_choice('models.classes.categoryApproach', 2))]) }}">
|
||||
<i class="fa-solid fa-arrow-left"></i>
|
||||
</a>
|
||||
@include('modules.breadcrumbs.breadcrumb-body', [
|
||||
'brParam' => $categoryApproachesModel])
|
||||
</div>
|
||||
<div class="mb-md-0 mb-2">
|
||||
<button class="btn btn-primary" id="formSubmitClone" data-bs-toggle="tooltip" type="submit"
|
||||
title="{{ __('crud.helpers.save_model', ['model' => __(trans_choice('models.classes.categoryApproach', 1))]) }}">
|
||||
{{ str(__('crud.actions.save'))->ucfirst() }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<form
|
||||
action="{{ route('bo.categories.approaches.update', $categoryApproachesModel) }}"
|
||||
method="POST" enctype="multipart/form-data">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
@include('bo.pages.categories_approaches.form')
|
||||
@include('bo.partials.script-button-clone')
|
||||
<div class="row mt-3">
|
||||
<div class="col text-center">
|
||||
<button class="btn btn-primary" id="formSubmit" data-bs-toggle="tooltip" type="submit"
|
||||
title="{{ __('crud.helpers.save_model', ['model' => trans_choice('models.classes.categoryApproach', 1)]) }}">
|
||||
{{ str(__('crud.actions.save'))->ucfirst() }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@endsection
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<div class="row">
|
||||
<div class="col-12 mb-3">
|
||||
<fieldset class="h-100 border p-3">
|
||||
<legend>{{ str(__('validation.attributes.name'))->ucfirst() }}</legend>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
@include('bo.partials.inputs.varchar', [
|
||||
'id' => 'approachName',
|
||||
'label' => str(
|
||||
__(':field :inter:model', [
|
||||
'field' => __('validation.attributes.name'),
|
||||
'inter' => $inter,
|
||||
'model' => trans_choice('models.classes.categoryApproach', 1),
|
||||
]))->ucfirst(),
|
||||
'hasWordCounter' => true,
|
||||
'name' => 'name',
|
||||
'required' => true,
|
||||
'model' => $categoryApproachesModel ?? null,
|
||||
'helper' => __('validation.between.string', [
|
||||
'attribute' => __(':field :inter:model', [
|
||||
'field' => __('validation.attributes.name'),
|
||||
'inter' => $inter,
|
||||
'model' => $model,
|
||||
]),
|
||||
'min' => 3,
|
||||
'max' => 255,
|
||||
]),
|
||||
'placeholder' => __('Un beau titre'),
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
<table class="table-hover table-fix-action m-0 table">
|
||||
@if (count($categories) > 0)
|
||||
<thead>
|
||||
@include('bo.modules.table-col-sorter', [
|
||||
'cols' => [
|
||||
'name' => str(__('validation.attributes.name'))->ucfirst(),
|
||||
'updated_at' => str(__('validation.attributes.updated_at'))->ucfirst(),
|
||||
],
|
||||
])
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($categories as $category)
|
||||
<tr class="border-bottom">
|
||||
<td class="text-center align-middle">{{ $category->name }}</td>
|
||||
<td class="text-center align-middle">
|
||||
<span class="badge text-bg-secondary">{{ $category->updated_at->isoFormat('LLLL') }}</span>
|
||||
</td>
|
||||
<td class="text-end align-middle">
|
||||
@canAny(['view', 'duplicate', 'update', 'delete'], $category)
|
||||
<form class="btn-group confirmDeleteTS"
|
||||
action="{{ route('bo.categories.approaches.destroy', $category) }}" method="POST"
|
||||
novalidate>
|
||||
@can('view', $category)
|
||||
<a class="btn btn-sm btn-warning" data-bs-toggle="tooltip"
|
||||
href="{{ route('bo.categories.approaches.show', $category) }}"
|
||||
title="{{ str(__('crud.actions.update'))->ucfirst() }}">
|
||||
<i class="fa-solid fa-eye"></i>
|
||||
</a>
|
||||
@endcan
|
||||
@can('update', $category)
|
||||
<a class="btn btn-sm btn-primary" data-bs-toggle="tooltip"
|
||||
href="{{ route('bo.categories.approaches.edit', $category) }}"
|
||||
title="{{ str(__('crud.actions.update'))->ucfirst() }}">
|
||||
<i class="fa-solid fa-pencil"></i>
|
||||
</a>
|
||||
@endcan
|
||||
@can('duplicate', $category)
|
||||
<a class="btn btn-sm btn-secondary" data-bs-toggle="tooltip"
|
||||
href="{{ route('bo.categories.approaches.duplicate', $category) }}"
|
||||
title="{{ str(__('crud.actions.duplicate'))->ucfirst() }}">
|
||||
<i class="fa-solid fa-copy"></i>
|
||||
</a>
|
||||
@endcan
|
||||
@can('delete', $category)
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button class="btn btn-sm btn-danger" data-bs-toggle="tooltip" type="submit"
|
||||
title="{{ str(__('crud.actions.delete'))->ucfirst() }}">
|
||||
<i class="fa-solid fa-trash"></i>
|
||||
</button>
|
||||
@endcan
|
||||
</form>
|
||||
@else
|
||||
<span class="text-danger" data-bs-toggle="tooltip" title="{{ __('list.right') }}">
|
||||
<i class="fa-solid fa-ban"></i>
|
||||
</span>
|
||||
@endcan
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
@else
|
||||
<tr>
|
||||
<td class="border-0">
|
||||
{{ trans_choice('crud.other.no_model_found', 2, ['model' => trans_choice('models.classes.categoryApproach', 2)]) }}
|
||||
</td>
|
||||
</tr>
|
||||
@endif
|
||||
</table>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
@extends('bo.layout')
|
||||
@section('title', __(' :model', ['model' => trans_choice('models.classes.categoryApproach', 2)]))
|
||||
@section('description', __('Liste de tous les :model déjà existant', ['model' => trans_choice('models.classes.categoryApproach', 1)]))
|
||||
@section('breadcrumb')
|
||||
|
||||
@section('content')
|
||||
<div class="d-flex justify-content-between flex-md-nowrap align-items-center flex-wrap">
|
||||
@include('modules.breadcrumbs.breadcrumb-body')
|
||||
@can('create', \App\Models\CategoryApproach::class)
|
||||
<a class="btn btn-primary float-right" data-bs-toggle="tooltip"
|
||||
href="{{ route('bo.categories.approaches.create') }}"
|
||||
title="{{ __('crud.helpers.create_model', ['model' => trans_choice('models.classes.categoryApproach', 1)]) }}">
|
||||
<i class="fa-solid fa-plus"></i>
|
||||
</a>
|
||||
@endcan
|
||||
</div>
|
||||
@include('bo.modules.search-bar')
|
||||
<div class="table-responsive mb-3">
|
||||
@include('bo.pages.categories_approaches.index-list')
|
||||
</div>
|
||||
@endsection
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
@extends('bo.layout', ['brParam' => $categoryApproachesModel])
|
||||
|
||||
@section('title', __('Aperçu d\'un :model', ['model' => trans_choice('models.classes.categoryApproach', 1)]))
|
||||
@section('description', __('Détail d\'un :model déjà existant', ['model' => trans_choice('models.classes.categoryApproach', 1)]))
|
||||
@section('breadcrumb', request()->route()->getName())
|
||||
|
||||
@section('content')
|
||||
<div class="d-flex justify-content-between flex-md-nowrap align-items-center flex-wrap pb-3">
|
||||
<div class="d-flex align-items-start flex-row">
|
||||
<a class="btn btn-primary text-decoration-none m-0 me-2" data-bs-toggle="tooltip"
|
||||
href="{{ route('bo.categories.approaches.index', $categoryApproachesModel) }}"
|
||||
title="{{ __('crud.helpers.list_all', ['model' => trans_choice('models.classes.categoryApproach', \INF)]) }}">
|
||||
<i class="fa-solid fa-arrow-left"></i>
|
||||
</a>
|
||||
@include('modules.breadcrumbs.breadcrumb-body', ['brParam' => $categoryApproachesModel])
|
||||
</div>
|
||||
<div class="btn-group mb-md-0 mb-2">
|
||||
@canAny(['view', 'duplicate', 'update', 'delete'], $categoryApproachesModel)
|
||||
<form class="btn-group confirmDeleteTS" action="{{ route('bo.categories.approaches.destroy', $categoryApproachesModel) }}" method="POST" novalidate>
|
||||
@can('duplicate', $categoryApproachesModel)
|
||||
<a class="btn btn-secondary" data-bs-toggle="tooltip"
|
||||
href="{{ route('bo.categories.approaches.duplicate', ['categories_approach' => $categoryApproachesModel]) }}"
|
||||
title="{{ str(__('crud.actions.duplicate'))->ucfirst() }}">
|
||||
<i class="fa-solid fa-copy"></i>
|
||||
</a>
|
||||
@endcan
|
||||
@can('update', $categoryApproachesModel)
|
||||
<a class="btn btn-primary" data-bs-toggle="tooltip" href="{{ route('bo.categories.approaches.edit', ['categories_approach' => $categoryApproachesModel]) }}"
|
||||
title="{{ str(__('crud.actions.update'))->ucfirst() }}">
|
||||
<i class="fa-solid fa-pencil"></i>
|
||||
</a>
|
||||
@endcan
|
||||
@can('delete', $categoryApproachesModel)
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button class="btn btn-danger" data-bs-toggle="tooltip" type="submit" title="{{ str(__('crud.actions.delete'))->ucfirst() }}">
|
||||
<i class="fa-solid fa-trash"></i>
|
||||
</button>
|
||||
@endcan
|
||||
</form>
|
||||
@endcan
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="table-responsive mb-3">
|
||||
<table class="table-hover m-0 table">
|
||||
<tbody>
|
||||
<tr class="border-bottom">
|
||||
<td class="w-50 fw-bold text-center align-middle">
|
||||
{{ str(__('validation.attributes.name'))->ucfirst() }}
|
||||
</td>
|
||||
<td class="w-50 text-center align-middle">
|
||||
{{ $categoryApproachesModel->name }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="border-bottom">
|
||||
<td class="w-50 fw-bold text-center align-middle">{{ str(__('validation.attributes.created_at'))->ucfirst() }}</td>
|
||||
<td class="w-50 text-center align-middle">
|
||||
{{ str($categoryApproachesModel->created_at->isoFormat('LLLL'))->ucFirst() }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="border-bottom">
|
||||
<td class="w-50 fw-bold text-center align-middle">{{ str(__('validation.attributes.updated_at'))->ucfirst() }}</td>
|
||||
<td class="w-50 text-center align-middle">
|
||||
{{ str($categoryApproachesModel->updated_at->isoFormat('LLLL'))->ucFirst() }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
@extends('bo.layout', ['brParam' => $sectionApproachModel])
|
||||
|
||||
<?php $condition = trans_choice('models.classes.sectionApproach', 1); ?>
|
||||
|
||||
@section('title', __('Création d\'une :model', ['model' => $condition]))
|
||||
@section('description', __('Création d\'un tout nouveau :model', ['model' => trans_choice('models.classes.sectionApproach', 1)]))
|
||||
@section('breadcrumb')
|
||||
|
||||
@section('content')
|
||||
<div class="d-flex justify-content-between flex-md-nowrap align-items-center flex-wrap pb-3">
|
||||
<div class="d-flex align-items-start flex-row">
|
||||
<a class="btn btn-primary text-decoration-none m-0 me-2" data-bs-toggle="tooltip"
|
||||
href="{{ route('bo.sections.approaches.index') }}"
|
||||
title="{{ __('crud.helpers.list_all', ['model' => trans_choice('models.classes.sectionApproach', 2)]) }}">
|
||||
<i class="fa-solid fa-arrow-left"></i>
|
||||
</a>
|
||||
@include('modules.breadcrumbs.breadcrumb-body', [
|
||||
'brParam' => $sectionApproachModel
|
||||
])
|
||||
</div>
|
||||
<div class="mb-md-0 mb-2">
|
||||
<button class="btn btn-primary" id="formSubmitClone" data-bs-toggle="tooltip" type="submit"
|
||||
title="{{ __('crud.helpers.save_model', ['model' => trans_choice('models.classes.sectionApproach', 1)]) }}">
|
||||
{{ str(__('crud.actions.save'))->ucfirst() }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<form
|
||||
action="{{ route('bo.sections.approaches.store') }}"
|
||||
method="POST" enctype="multipart/form-data">
|
||||
@csrf
|
||||
@include('bo.pages.sections_approaches.form')
|
||||
@include('bo.partials.script-button-clone')
|
||||
<div class="row mt-3">
|
||||
<div class="col text-center">
|
||||
<button class="btn btn-primary" id="formSubmit" data-bs-toggle="tooltip" type="submit"
|
||||
title="{{ __('crud.helpers.save_model', ['model' => trans_choice('models.classes.sectionApproach', 1) ]) }}">
|
||||
{{ str(__('crud.actions.save'))->ucfirst() }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@endsection
|
||||
45
resources/views/bo/pages/sections_approaches/edit.blade.php
Normal file
45
resources/views/bo/pages/sections_approaches/edit.blade.php
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
@extends('bo.layout', ['brParam' => $sectionApproachModel])
|
||||
|
||||
<?php $condition = trans_choice('models.classes.sectionApproach', 1); ?>
|
||||
|
||||
@section('title', __('Édition :inter :model', ['model' => $condition]))
|
||||
@section('description', __('Édition :inter :model',
|
||||
['model' => $condition, 'inter' => __('validation.custom.female') ]))
|
||||
@section('breadcrumb', request()->route()->getName())
|
||||
|
||||
@section('content')
|
||||
<div class="d-flex justify-content-between flex-md-nowrap align-items-center flex-wrap pb-3">
|
||||
<div class="d-flex align-items-start flex-row">
|
||||
<a class="btn btn-primary text-decoration-none m-0 me-2" data-bs-toggle="tooltip"
|
||||
href="{{ route('bo.sections.approaches.index') }}"
|
||||
title="{{ __('crud.helpers.list_all', ['model' => str($condition)->plural()]) }}">
|
||||
<i class="fa-solid fa-arrow-left"></i>
|
||||
</a>
|
||||
@include('modules.breadcrumbs.breadcrumb-body', [
|
||||
'brParam' => $sectionApproachModel
|
||||
])
|
||||
</div>
|
||||
<div class="mb-md-0 mb-2">
|
||||
<button class="btn btn-primary" id="formSubmitClone" data-bs-toggle="tooltip" type="submit"
|
||||
title="{{ __('crud.helpers.save_model', ['model' => $condition]) }}">
|
||||
{{ str(__('crud.actions.save'))->ucfirst() }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<form
|
||||
action="{{ route('bo.sections.approaches.update', $sectionApproachModel) }}"
|
||||
method="POST" enctype="multipart/form-data">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
@include('bo.pages.sections_approaches.form')
|
||||
@include('bo.partials.script-button-clone')
|
||||
<div class="row mt-3">
|
||||
<div class="col text-center">
|
||||
<button class="btn btn-primary" id="formSubmit" data-bs-toggle="tooltip" type="submit"
|
||||
title="{{ __('crud.helpers.save_model', ['model' => $condition ]) }}">
|
||||
{{ str(__('crud.actions.save'))->ucfirst() }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@endsection
|
||||
200
resources/views/bo/pages/sections_approaches/form.blade.php
Normal file
200
resources/views/bo/pages/sections_approaches/form.blade.php
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
@php
|
||||
$inter = $condition ? __('validation.custom.of_the.female') : __('validation.custom.of_the.male');
|
||||
$model = __('models.classes.sectionApproach');
|
||||
@endphp
|
||||
<div class="row">
|
||||
{{-- Page --}}
|
||||
<div class="col-6 col-md-3 mb-3">
|
||||
<fieldset class="h-100 border p-3">
|
||||
<legend>{{ str(trans_choice('models.classes.static_page', 1))->ucFirst() }}</legend>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
@include('bo.partials.inputs.search-belongs-to-dropdown', [
|
||||
'id' => 'pageId',
|
||||
'label' => __(':model associé', [
|
||||
'model' => str(trans_choice('models.classes.static_page', 1))->ucFirst(),
|
||||
]),
|
||||
'name' => 'page_id',
|
||||
'relation' => 'page',
|
||||
'model' => $sectionApproachModel,
|
||||
'targetClass' => 'App\Models\StaticPage',
|
||||
'modelListPaginate' => $staticPageModel ?? [],
|
||||
'routeName' => 'bo.sections.approaches.json-paginate',
|
||||
'fieldName' => 'title',
|
||||
'multiple' => false,
|
||||
'required' => true,
|
||||
'disabled' => false,
|
||||
'placeholder' => __('Rechercher un :model', [
|
||||
'model' => trans_choice('models.classes.static_page', 1),
|
||||
]),
|
||||
'helper' => __(
|
||||
'Sélectionner une :model qui sera associé parmis la liste (une seul et unique :model doit être choisi).',
|
||||
['model' => trans_choice('models.classes.static_page', 1)]),
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
{{-- Category --}}
|
||||
<div class="col-6 col-md-3 mb-3">
|
||||
<fieldset class="h-100 border p-3">
|
||||
<legend>{{ str(trans_choice('models.classes.static_page', 1))->ucFirst() }}</legend>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
@include('bo.partials.inputs.search-belongs-to-dropdown', [
|
||||
'id' => 'categoryId',
|
||||
'label' => __(':model associé', [
|
||||
'model' => str(trans_choice('models.classes.categoryApproach', 1))->ucFirst(),
|
||||
]),
|
||||
'name' => 'category_id',
|
||||
'relation' => 'category',
|
||||
'model' => $sectionApproachModel,
|
||||
'targetClass' => 'App\Models\CategoryApproach',
|
||||
'modelListPaginate' => $categoryApproachModel ?? [],
|
||||
'routeName' => 'bo.categories.approaches.json-paginate',
|
||||
'fieldName' => 'name',
|
||||
'multiple' => false,
|
||||
'required' => true,
|
||||
'disabled' => false,
|
||||
'placeholder' => __('Rechercher un :model', [
|
||||
'model' => trans_choice('models.classes.categoryApproach', 1),
|
||||
]),
|
||||
'helper' => __(
|
||||
'Sélectionner une :model qui sera associé parmis la liste (une seul et unique :model doit être choisi).',
|
||||
['model' => trans_choice('models.classes.categoryApproach', 1)]),
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
{{-- TITLE --}}
|
||||
<div class="col-12 col-lg-6 mb-3">
|
||||
<fieldset class="h-100 border p-3">
|
||||
<legend>{{ str(__('validation.attributes.name'))->ucfirst() }}</legend>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
@include('bo.partials.inputs.varchar', [
|
||||
'id' => 'approachName',
|
||||
'label' => str(
|
||||
__(':field :inter:model', [
|
||||
'field' => __('validation.attributes.title'),
|
||||
'inter' => $inter,
|
||||
'model' => __('section'),
|
||||
]))->ucfirst(),
|
||||
'hasWordCounter' => true,
|
||||
'name' => 'title',
|
||||
'required' => true,
|
||||
'model' => $sectionApproachModel ?? null,
|
||||
'helper' => __('validation.between.string', [
|
||||
'attribute' => __(':field :inter:model', [
|
||||
'field' => __('validation.attributes.title'),
|
||||
'inter' => $inter,
|
||||
'model' => $model,
|
||||
]),
|
||||
'min' => 3,
|
||||
'max' => 255,
|
||||
]),
|
||||
'placeholder' => __('Un beau titre'),
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
{{-- CONTENT --}}
|
||||
<div class="col-12 mb-3">
|
||||
<fieldset class="border p-3">
|
||||
<legend>{{ str(__('validation.attributes.content'))->ucfirst() }}</legend>
|
||||
<div class="row mb-3">
|
||||
<div class="col-12">
|
||||
@include('bo.partials.inputs.text-html', [
|
||||
'id' => 'sectionContent',
|
||||
'label' => __(':field :inter:model', [
|
||||
'field' => str(__('validation.attributes.content'))->ucfirst(),
|
||||
'inter' => __('validation.custom.of_the.female'),
|
||||
'model' => trans_choice('section', 1),
|
||||
]),
|
||||
'name' => 'content',
|
||||
'editorConfig' => \App\Enums\CkEditorConfigName::basic->label(),
|
||||
'model' => $sectionApproachModel ?? null,
|
||||
'required' => true,
|
||||
'helper' => __('crud.minicrud.text_warning'),
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
{{-- PICTURE --}}
|
||||
<div class="col-12 pb-3">
|
||||
<fieldset class="h-100 border p-3">
|
||||
<legend>{{ str(__('validation.attributes.image'))->ucfirst() }}</legend>
|
||||
<div class="row mb-3">
|
||||
{{-- PICTURE_ALT --}}
|
||||
<div class="col-12 col-lg-6 m-lg-0 mb-3">
|
||||
@include('bo.partials.inputs.varchar', [
|
||||
'id' => 'approachPictureAlt',
|
||||
'label' => __(':field1 :inter1:field2 :inter2:model', [
|
||||
'field1' => str(__('validation.custom.attribute_alt'))->ucfirst(),
|
||||
'inter1' => __('validation.custom.of_the.vowel'),
|
||||
'field2' => __('validation.attributes.image'),
|
||||
'inter2' => $inter,
|
||||
'model' => $model,
|
||||
]),
|
||||
'hasWordCounter' => true,
|
||||
'name' => 'picture_alt',
|
||||
'required' => true,
|
||||
'model' => $sectionApproachModel ?? null,
|
||||
'helper' => __('crud.minicrud.picture_alt_helper'),
|
||||
'placeholder' => __(':field1 :inter1:field2 :inter2:model', [
|
||||
'field1' => str(__('validation.custom.attribute_alt'))->ucfirst(),
|
||||
'inter1' => __('validation.custom.of_the.vowel'),
|
||||
'field2' => __('validation.attributes.image'),
|
||||
'inter2' => $inter,
|
||||
'model' => $model,
|
||||
]),
|
||||
])
|
||||
</div>
|
||||
{{-- PICTURE_TITLE --}}
|
||||
<div class="col-12 col-lg-6 mb-3">
|
||||
@include('bo.partials.inputs.varchar', [
|
||||
'id' => 'approachPictureTitle',
|
||||
'label' => __(':field1 :inter1:field2 :inter2:model', [
|
||||
'field1' => str(__('validation.custom.attribute_title'))->ucfirst(),
|
||||
'inter1' => __('validation.custom.of_the.vowel'),
|
||||
'field2' => __('validation.attributes.image'),
|
||||
'inter2' => $inter,
|
||||
'model' => $model,
|
||||
]),
|
||||
'hasWordCounter' => true,
|
||||
'name' => 'picture_title',
|
||||
'required' => true,
|
||||
'model' => $sectionApproachModel ?? null,
|
||||
'helper' => __('crud.minicrud.picture_title_helper'),
|
||||
'placeholder' => __(':field1 :inter1:field2 :inter2:model', [
|
||||
'field1' => str(__('validation.custom.attribute_title'))->ucfirst(),
|
||||
'inter1' => __('validation.custom.of_the.vowel'),
|
||||
'field2' => __('validation.attributes.image'),
|
||||
'inter2' => $inter,
|
||||
'model' => $model,
|
||||
]),
|
||||
])
|
||||
</div>
|
||||
{{-- PICTURE --}}
|
||||
<div class="col-12">
|
||||
@include('bo.partials.inputs.varchar-picture', [
|
||||
'id' => 'sectionApproachPicture',
|
||||
'name' => 'picture',
|
||||
'width' => 80,
|
||||
'height' => 75,
|
||||
'model' => $sectionApproachModel ?? null,
|
||||
'required' => true,
|
||||
'preview' => true,
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="col-12 text-center">
|
||||
<p><b>{{ __('* Champs obligatoires') }}</b></p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
<table class="table-hover table-fix-action m-0 table">
|
||||
@if (count($sections) > 0)
|
||||
<thead>
|
||||
@include('bo.modules.table-col-sorter', [
|
||||
'cols' => [
|
||||
'name' => str(__('section'))->ucfirst(),
|
||||
'category_id' => str(__('validation.custom.category'))->ucfirst(),
|
||||
'page_id' => str(__('page'))->ucfirst(),
|
||||
'created_at' => str(__('validation.attributes.updated_at'))->ucfirst(),
|
||||
],
|
||||
])
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($sections as $section)
|
||||
<tr class="border-bottom">
|
||||
<td class="text-center align-middle">{{ $section->title }}</td>
|
||||
<td class="text-center align-middle">
|
||||
@if ($section->category)
|
||||
<a href="{{ route('bo.categories.approaches.show', $section->category) }}"
|
||||
class="badge text-bg-secondary text-decoration-none">
|
||||
{{ $section->category->name }}
|
||||
</a>
|
||||
@endif
|
||||
</td>
|
||||
<td class="text-center align-middle">
|
||||
@if ($section->page)
|
||||
<a href="{{ route('bo.static_pages.edit', $section->page) }}"
|
||||
class="badge text-bg-secondary text-decoration-none">
|
||||
{{ $section->page->title }}
|
||||
</a>
|
||||
@endif
|
||||
</td>
|
||||
<td class="text-center align-middle">
|
||||
<span class="badge text-bg-secondary">{{ $section->updated_at->isoFormat('LLLL') }}</span>
|
||||
</td>
|
||||
<td class="text-end align-middle">
|
||||
@canAny(['view', 'duplicate', 'update', 'delete'], $section)
|
||||
<form class="btn-group confirmDeleteTS"
|
||||
action="{{ route('bo.sections.approaches.destroy', $section) }}" method="POST" novalidate>
|
||||
@can('view', $section)
|
||||
<a class="btn btn-sm btn-warning" data-bs-toggle="tooltip"
|
||||
href="{{ route('bo.sections.approaches.show', $section) }}"
|
||||
title="{{ str(__('crud.actions.show'))->ucfirst() }}">
|
||||
<i class="fa-solid fa-eye"></i>
|
||||
</a>
|
||||
@endcan
|
||||
@can('duplicate', $section)
|
||||
<a class="btn btn-sm btn-secondary" data-bs-toggle="tooltip"
|
||||
href="{{ route('bo.sections.approaches.duplicate', $section) }}"
|
||||
title="{{ str(__('crud.actions.duplicate'))->ucfirst() }}">
|
||||
<i class="fa-solid fa-copy"></i>
|
||||
</a>
|
||||
@endcan
|
||||
@can('update', $section)
|
||||
<a class="btn btn-sm btn-primary" data-bs-toggle="tooltip"
|
||||
href="{{ route('bo.sections.approaches.edit', $section) }}"
|
||||
title="{{ str(__('crud.actions.update'))->ucfirst() }}">
|
||||
<i class="fa-solid fa-pencil"></i>
|
||||
</a>
|
||||
@endcan
|
||||
@can('delete', $section)
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button class="btn btn-sm btn-danger" data-bs-toggle="tooltip" type="submit"
|
||||
title="{{ str(__('crud.actions.delete'))->ucfirst() }}">
|
||||
<i class="fa-solid fa-trash"></i>
|
||||
</button>
|
||||
@endcan
|
||||
</form>
|
||||
@else
|
||||
<span class="text-danger" data-bs-toggle="tooltip" title="{{ __('list.right') }}">
|
||||
<i class="fa-solid fa-ban"></i>
|
||||
</span>
|
||||
@endcan
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
@else
|
||||
<tr>
|
||||
<td class="border-0">
|
||||
{{ trans_choice('crud.other.no_model_found', 2, ['model' => trans_choice('models.classes.sectionApproach', 1)]) }}
|
||||
</td>
|
||||
</tr>
|
||||
@endif
|
||||
</table>
|
||||
27
resources/views/bo/pages/sections_approaches/index.blade.php
Normal file
27
resources/views/bo/pages/sections_approaches/index.blade.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
@extends('bo.layout', ['brParam' => $sections])
|
||||
|
||||
@section('title',str(trans_choice('models.classes.sectionApproach', 1))->plural()->ucfirst())
|
||||
@section('description', __('Liste de tous les :model', ['model' => trans_choice('models.classes.sectionApproach', 2)]))
|
||||
@section('breadcrumb', request()->route()->getName())
|
||||
|
||||
@section('content')
|
||||
<div class="d-flex justify-content-between flex-md-nowrap align-items-center flex-wrap">
|
||||
@include('modules.breadcrumbs.breadcrumb-body', [
|
||||
'brParam' => $sections,
|
||||
])
|
||||
@can('create', \App\Models\SectionApproach::class)
|
||||
<a class="btn btn-primary float-right" data-bs-toggle="tooltip"
|
||||
href="{{ route('bo.sections.approaches.create') }}"
|
||||
title="{{ __('crud.helpers.create_model', ['model' => trans_choice('models.classes.sectionApproach', 1)]) }}">
|
||||
<i class="fa-solid fa-plus"></i>
|
||||
</a>
|
||||
@endcan
|
||||
</div>
|
||||
@include('bo.modules.search-bar')
|
||||
<div class="table-responsive mb-3">
|
||||
@include('bo.pages.sections_approaches.index-list')
|
||||
</div>
|
||||
{{ $sections->links() }}
|
||||
@endsection
|
||||
|
||||
|
||||
107
resources/views/bo/pages/sections_approaches/show.blade.php
Normal file
107
resources/views/bo/pages/sections_approaches/show.blade.php
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
@extends('bo.layout', ['brParam' => $sectionApproachModel])
|
||||
|
||||
@section('title', __('Aperçu d\'un :model', ['model' => trans_choice('models.classes.sectionApproach', 1)]))
|
||||
@section('description', __('Édition d\'un :model déjà existant', ['model' => trans_choice('models.classes.sectionApproach', 1)]))
|
||||
@section('breadcrumb', request()->route()->getName())
|
||||
|
||||
@section('content')
|
||||
<div class="d-flex justify-content-between flex-md-nowrap align-items-center flex-wrap pb-3">
|
||||
<div class="d-flex align-items-start flex-row">
|
||||
<a class="btn btn-primary text-decoration-none m-0 me-2" data-bs-toggle="tooltip"
|
||||
href="{{ route('bo.sections.approaches.index') }}"
|
||||
title="{{ __('crud.helpers.list_all', ['model' => trans_choice('models.classes.sectionApproach',2)]) }}">
|
||||
<i class="fa-solid fa-arrow-left"></i>
|
||||
</a>
|
||||
@include('modules.breadcrumbs.breadcrumb-body', ['brParam' => $sectionApproachModel])
|
||||
</div>
|
||||
<div class="btn-group mb-md-0 mb-2">
|
||||
@canAny(['view', 'duplicate', 'update', 'delete'], $sectionApproachModel)
|
||||
<form class="btn-group confirmDeleteTS" action="{{ route('bo.approaches.destroy', $sectionApproachModel) }}" method="POST" novalidate>
|
||||
@can('duplicate', $sectionApproachModel)
|
||||
<a class="btn btn-secondary" data-bs-toggle="tooltip"
|
||||
href="{{ route('bo.sections.approaches.duplicate', ['section_approach' => $sectionApproachModel]) }}"
|
||||
title="{{ str(__('crud.actions.duplicate'))->ucfirst() }}">
|
||||
<i class="fa-solid fa-copy"></i>
|
||||
</a>
|
||||
@endcan
|
||||
@can('update', $sectionApproachModel)
|
||||
<a class="btn btn-primary" data-bs-toggle="tooltip" href="{{ route('bo.sections.approaches.edit', ['section_approach' => $sectionApproachModel]) }}"
|
||||
title="{{ str(__('crud.actions.update'))->ucfirst() }}">
|
||||
<i class="fa-solid fa-pencil"></i>
|
||||
</a>
|
||||
@endcan
|
||||
@can('delete', $sectionApproachModel)
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button class="btn btn-danger" data-bs-toggle="tooltip" type="submit" title="{{ str(__('crud.actions.delete'))->ucfirst() }}">
|
||||
<i class="fa-solid fa-trash"></i>
|
||||
</button>
|
||||
@endcan
|
||||
</form>
|
||||
@endcan
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="table-responsive mb-3">
|
||||
<table class="table-hover m-0 table">
|
||||
<tbody>
|
||||
<tr class="border-bottom">
|
||||
<td class="w-50 fw-bold text-center align-middle">
|
||||
{{ str(__('validation.attributes.title'))->ucfirst() }}
|
||||
</td>
|
||||
<td class="w-50 text-center align-middle">
|
||||
{{ $sectionApproachModel->title }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="border-bottom">
|
||||
<td class="w-50 fw-bold text-center align-middle">
|
||||
{{ str(__('validation.attributes.content'))->ucfirst() }}
|
||||
</td>
|
||||
<td class="w-50 text-center align-middle">
|
||||
{{ $sectionApproachModel->content }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="border-bottom">
|
||||
<td class="w-50 fw-bold text-center align-middle">
|
||||
{{ str(__('validation.attributes.image'))->ucfirst() }}
|
||||
</td>
|
||||
<td class="w-50 text-center align-middle">
|
||||
<img src="{{ $sectionApproachModel->picture }}" title="{{ $sectionApproachModel->picture_title }}"
|
||||
alt="{{ $sectionApproachModel->picture_alt }}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="border-bottom">
|
||||
<td class="w-50 fw-bold text-center align-middle">
|
||||
{{ str(__('validation.custom.attribute_alt'))->ucfirst() }}
|
||||
</td>
|
||||
<td class="w-50 text-center align-middle">
|
||||
{{ $sectionApproachModel->picture_alt }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="border-bottom">
|
||||
<td class="w-50 fw-bold text-center align-middle">
|
||||
{{ str(__('validation.custom.attribute_title'))->ucfirst() }}
|
||||
</td>
|
||||
<td class="w-50 text-center align-middle">
|
||||
{{ $sectionApproachModel->picture_title }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="border-bottom">
|
||||
<td class="w-50 fw-bold text-center align-middle">{{ str(__('validation.attributes.created_at'))->ucfirst() }}</td>
|
||||
<td class="w-50 text-center align-middle">
|
||||
{{ str($sectionApproachModel->created_at->isoFormat('LLLL'))->ucFirst() }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="border-bottom">
|
||||
<td class="w-50 fw-bold text-center align-middle">{{ str(__('validation.attributes.updated_at'))->ucfirst() }}</td>
|
||||
<td class="w-50 text-center align-middle">
|
||||
{{ str($sectionApproachModel->updated_at->isoFormat('LLLL'))->ucFirst() }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
@ -118,7 +118,9 @@
|
|||
!$staticPageModel->type->equals(StaticPageType::legals) &&
|
||||
!$staticPageModel->type->equals(StaticPageType::confidentiality) &&
|
||||
!$staticPageModel->type->equals(StaticPageType::accessibility) &&
|
||||
!$staticPageModel->type->equals(StaticPageType::selling))
|
||||
!$staticPageModel->type->equals(StaticPageType::selling) &&
|
||||
!$staticPageModel->type->equals(StaticPageType::exitOutside) &&
|
||||
!$staticPageModel->type->equals(StaticPageType::ouiCBon))
|
||||
{{-- SUBTITLE --}}
|
||||
<div class="col-12 col-md-6 mb-3">
|
||||
<fieldset class="h-100 border p-3">
|
||||
|
|
@ -161,7 +163,9 @@
|
|||
!$staticPageModel->type->equals(StaticPageType::recipe) &&
|
||||
!$staticPageModel->type->equals(StaticPageType::product) &&
|
||||
!$staticPageModel->type->equals(StaticPageType::home) &&
|
||||
!$staticPageModel->type->equals(StaticPageType::search))
|
||||
!$staticPageModel->type->equals(StaticPageType::search) &&
|
||||
!$staticPageModel->type->equals(StaticPageType::exitOutside) &&
|
||||
!$staticPageModel->type->equals(StaticPageType::ouiCBon))
|
||||
{{-- CONTENT --}}
|
||||
<div class="col-12 mb-3">
|
||||
<fieldset class="border p-3">
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
@foreach ($associatedModels as $associatedModel)
|
||||
<option
|
||||
value="{{ $associatedModel->value}}"
|
||||
@selected(old($name, $model->{$name}->value ?? $value ?? 1) == $associatedModel->value)>
|
||||
@selected(old($name, $model->{$name} ?? $value ?? 1) == $associatedModel->value)>
|
||||
{{ $associatedModel->label }}
|
||||
</option>
|
||||
@endforeach
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<div @class(['mt-md-0 mt-5', $class ?? ''])>
|
||||
<div class="light-card">
|
||||
<img class="img-fluid light-card-icon" src="{{ Vite::asset($icon['path']) }}" title="{{ $icon['description'] }}"
|
||||
<img class="img-fluid light-card-icon" src="{{ asset($icon['path']) }}" title="{{ $icon['description'] }}"
|
||||
alt="{{ $icon['alt'] }}">
|
||||
|
||||
<span class="text-uppercase bg-secondary text-light fw-semibold right-rotate-sm">{{ $category }}</span>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
@props(['title' => '', 'subtitle' => ''])
|
||||
@props(['title' => '', 'subtitle' => '', 'image' => ''])
|
||||
|
||||
@php
|
||||
$translatedTitle = __($title);
|
||||
|
|
@ -30,15 +30,10 @@
|
|||
</div>
|
||||
<div class="d-none d-xl-block col-6 col-xxl-4">
|
||||
<div class="header-image-wrapper breeding-header-translate-right">
|
||||
<img class="img-fluid" src="{{ Vite::asset('resources/assets/images/breeding/haystack.jpg') }}"
|
||||
title="{{ __('titre de l\'image') }}" alt="{{ __('alt de l\'image') }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-8 position-relative z-1 mx-auto mt-4">
|
||||
<div class="d-xl-none header-image-wrapper">
|
||||
<img class="img-fluid" src="{{ Vite::asset('resources/assets/images/breeding/haystack.jpg') }}"
|
||||
<img class="img-fluid" src="{{ asset($image) }}"
|
||||
title="{{ __('titre de l\'image') }}" alt="{{ __('alt de l\'image') }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -1,124 +1,7 @@
|
|||
@php
|
||||
$items = [
|
||||
'chicken' => [
|
||||
[
|
||||
'category' => 'Accès à l\'extérieur',
|
||||
'icon' => [
|
||||
'path' => 'resources/assets/images/breeding/sortant-a-l-exterieur/chicken-outside-sun.svg',
|
||||
'alt' => "Pictogramme d'un accès à l'eau et l'alimenttaion en continu",
|
||||
'description' => "Pictogramme d'une goutte d'eau et d'un épi de blé entouré de d'un clycle de deux flèches",
|
||||
],
|
||||
'content' => [
|
||||
[
|
||||
'title' => 'Des volailles qui sortent à l’Extérieur',
|
||||
'points' => [
|
||||
nl2br(__('Nos poulets ont accès quotidiennement à un :strongStartparcours extérieur pendant au minimum 8 heures*:strongEnd', [
|
||||
'strongStart' => '<strong>',
|
||||
'strongEnd' => '</strong>',
|
||||
'br' => '<br>',
|
||||
])),
|
||||
nl2br(__('Les trappes sont ouvertes toute la journée : les volailles peuvent donc :strongStartsortir dans les prés:strongEnd ou :strongStartrester dans le poulailler:strongEnd comme elles le souhaitent ! Cela permet de leur assurer des conditions d’élevage les plus proches possible de leur milieu naturel, à la lumière naturelle le jour, et à l’obscurité toute la nuit.', [
|
||||
'strongStart' => '<strong>',
|
||||
'strongEnd' => '</strong>',
|
||||
'br' => '<br>',
|
||||
])),
|
||||
],
|
||||
'asterisc' => '*Durant au moins la moitié de leur élevage',
|
||||
],
|
||||
],
|
||||
'class' => 'card-template-sm',
|
||||
],
|
||||
[
|
||||
'category' => 'Amélioration du bien-être animal',
|
||||
'icon' => [
|
||||
'path' => 'resources/assets/images/breeding/sortant-a-l-exterieur/chicken-heart.svg',
|
||||
'alt' => "Pictogramme d'une volaille en bonne santé",
|
||||
'description' => "Pictogramme d'une volaille avec un coeur pour valoriser le bien-être animal dans les élevages",
|
||||
],
|
||||
'content' => [
|
||||
[
|
||||
'title' => 'Le bien-être animal au cœur des préoccupations',
|
||||
'text' => 'Nos éleveurs partenaires ont des convictions fortes :',
|
||||
],
|
||||
[
|
||||
'points' => [
|
||||
nl2br(__('Elever des :strongStartvolailles 100% françaises:strongEnd', [
|
||||
'strongStart' => '<strong>',
|
||||
'strongEnd' => '</strong>',
|
||||
'br' => '<br>',
|
||||
])),
|
||||
nl2br(__('Privilégiez des poulets à croissance lente élevées pendant :strongStart56 jours minimum.:strongEnd', [
|
||||
'strongStart' => '<strong>',
|
||||
'strongEnd' => '</strong>',
|
||||
'br' => '<br>',
|
||||
])),
|
||||
nl2br(__('Utiliser une :strongStartmédecine douce:strongEnd pour soigner leurs volailles. L’utilisation d’antibiotiques n’est faite qu’en dernier recours et après autorisation d’un vétérinaire indépendant*.', [
|
||||
'strongStart' => '<strong>',
|
||||
'strongEnd' => '</strong>',
|
||||
'br' => '<br>',
|
||||
])),
|
||||
],
|
||||
'asterisc' => '*Conformément aux exigences réglementaires',
|
||||
],
|
||||
],
|
||||
'class' => 'card-template-md',
|
||||
],
|
||||
[
|
||||
'category' => 'Environnement',
|
||||
'icon' => [
|
||||
'path' => 'resources/assets/images/breeding/sortant-a-l-exterieur/chicken-arrow-left-right.svg',
|
||||
'alt' => "Pictogramme de volailles avec un accès à l'extérieur",
|
||||
'description' => 'Pictogramme de volailles dans un champs ensoleillé',
|
||||
],
|
||||
'content' => [
|
||||
[
|
||||
'title' => 'Plus d\'espace à l\'extérieur mais aussi à l\'intérieur !',
|
||||
'points' => [
|
||||
nl2br(__('En moyenne :strongStart30% d’espace supplémentaire dans le poulailler:strongEnd par rapport aux élevages conventionnels pour garantir plus d’espaces aux poulets pour se déplacer et exprimer leur comportement naturel.', [
|
||||
'strongStart' => '<strong>',
|
||||
'strongEnd' => '</strong>',
|
||||
'br' => '<br>',
|
||||
])),
|
||||
nl2br(__('Les volailles ont à disposition des jouets comme des :strongStartballots de paille et des pierres à piquer.:strongEnd', [
|
||||
'strongStart' => '<strong>',
|
||||
'strongEnd' => '</strong>',
|
||||
'br' => '<br>',
|
||||
])),
|
||||
],
|
||||
],
|
||||
],
|
||||
'class' => 'card-template-md',
|
||||
],
|
||||
[
|
||||
'category' => 'Alimentation',
|
||||
'icon' => [
|
||||
'path' => 'resources/assets/images/breeding/sortant-a-l-exterieur/chicken-outside-food.svg',
|
||||
'alt' => "Pictogramme d'une volaille avec plus d'espace",
|
||||
'description' => "Pictogramme d'une volaille avec deux flèches opposées pour indiquer plus d'espace à l'intérieur et à l'extérieur du poulailler",
|
||||
],
|
||||
'content' => [
|
||||
[
|
||||
'title' => 'Un accès constant à l\'eau et à la nourriture',
|
||||
'points' => [
|
||||
nl2br(__('Nos volailles sont nourries avec des :strongStartcéréales entières 100% françaises:strongEnd, sélectionnées par des nutritionnistes et :strongStartgaranties SANS OGM:strongEnd (<0,9%).', [
|
||||
'strongStart' => '<strong>',
|
||||
'strongEnd' => '</strong>',
|
||||
'br' => '<br>',
|
||||
])),
|
||||
nl2br(__('Nos volailles ont :strongStartaccès toute la journée à des abreuvoirs d’eau et à leur nourriture dans les mangeoires.:strongEnd', [
|
||||
'strongStart' => '<strong>',
|
||||
'strongEnd' => '</strong>',
|
||||
'br' => '<br>',
|
||||
])),
|
||||
],
|
||||
],
|
||||
],
|
||||
'class' => 'card-template-sm',
|
||||
],
|
||||
],
|
||||
];
|
||||
$items = $sections;
|
||||
@endphp
|
||||
|
||||
@props(['onglets' => [], 'sections' => [], 'staticPageModel'])
|
||||
<section class="position-relative line-border-large z-1 overflow-hidden">
|
||||
<div class="position-absolute h-100 w-100 top-0 z-0">
|
||||
<div class="bg-green-wood h-100 w-100" id="demarche-bg"></div>
|
||||
|
|
@ -128,33 +11,50 @@
|
|||
<div class="col-12 mb-2">
|
||||
<div class="d-md-flex justify-content-md-center gap-md-3">
|
||||
<h2 class="h1 f-intro-head-h-base align-self-md-center text-center">
|
||||
{{ __('Notre cahier des charges') }}
|
||||
{{ __($staticPageModel->data['title']['value']) }}
|
||||
</h2>
|
||||
{{-- Oui c'est bon Logo --}}
|
||||
<div class="d-flex justify-content-center mb-3">
|
||||
<div>
|
||||
<img class="img-fluid center-block"
|
||||
src="{{ Vite::asset('resources/assets/images/breeding/sortant-a-l-exterieur/logo-sortant-a-l-exterieur.png') }}"
|
||||
alt="{{ __('Logo de la démarche sortant à l\'extérieur') }}">
|
||||
src="{{ asset($staticPageModel->data['picto']['value']) }}"
|
||||
alt="{{ __($staticPageModel->data['picto']['alt']) }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="w-lg-50 mx-auto text-center">
|
||||
{{ __('Notre démarche inédite Le Gaulois ’’Sortant à l’extérieur’’ s’engage à ce que les volailles sortent à l’extérieur, tous les jours, dans les prés. Découvrez la démarche développée avec les éleveurs partenaires mobilisés chaque jour pour élever des volailles, nées et élevées en France.') }}
|
||||
{{ __(strip_tags($staticPageModel->data['description']['value'])) }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{{-- Buttons --}}
|
||||
<div class="d-flex justify-content-center gap-md-4 gap-5">
|
||||
<button class="btn btn-secondary fs-6 d-block" id="chicken-button-outside" type="button">
|
||||
{{ __('Poulet') }}
|
||||
</button>
|
||||
@foreach ($items as $categoryKey => $categoryItems)
|
||||
<button
|
||||
class="btn btn-secondary fs-6 d-block category-btn"
|
||||
type="button"
|
||||
data-category="{{ $categoryKey }}"
|
||||
>
|
||||
{{ $categoryKey }}
|
||||
</button>
|
||||
@endforeach
|
||||
</div>
|
||||
{{-- Cards --}}
|
||||
<div class="row mb-5 mt-5" id="cards-container-outside">
|
||||
<div class="card-grid">
|
||||
@foreach ($items['chicken'] as $item)
|
||||
<x-fo.breeding.light-card :category="$item['category']" :icon="$item['icon']" :content="$item['content']" :class="$item['class'] . ' chicken-card'" />
|
||||
@foreach ($items as $categoryKey => $categoryItems)
|
||||
|
||||
<div style="display: contents" data-category="{{ $categoryKey }}">
|
||||
@foreach ($categoryItems as $item)
|
||||
<x-fo.breeding.light-card
|
||||
:category="$item['category']"
|
||||
:icon="$item['icon']"
|
||||
:content="$item['content']"
|
||||
:class="$item['class']"
|
||||
data-category="{{ $categoryKey }}"
|
||||
/>
|
||||
@endforeach
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,54 +1,4 @@
|
|||
@php
|
||||
$slides = [
|
||||
[
|
||||
'image' => [
|
||||
'path' => Vite::asset(
|
||||
'resources/assets/images/breeding/sortant-a-l-exterieur/Elevage-volailles-poulailler-Sortant-a-l-exterieur-Le-Gaulois.jpg',
|
||||
),
|
||||
'title' => "Elevage Le Gaulois respectant le cahier des charges ’’Sortant à l'extérieur’’",
|
||||
'alt' => 'Volailles à l\'intérieur du poulailler avec des trappes pour accéder à l\'extérieur toute la journée',
|
||||
],
|
||||
],
|
||||
[
|
||||
'image' => [
|
||||
'path' => Vite::asset(
|
||||
'resources/assets/images/breeding/sortant-a-l-exterieur/Eleveur-alimentation-volailles-exterieur-champs-Le-Gaulois.jpg',
|
||||
),
|
||||
'title' => 'Éleveur marchant vers ses volailles pour les nourrir',
|
||||
'alt' => 'Éleveur Le Gaulois marchant avec un sceau, nourrissant les volailles à l\'extérieur, dans son champ',
|
||||
],
|
||||
],
|
||||
[
|
||||
'image' => [
|
||||
'path' => Vite::asset(
|
||||
'resources/assets/images/breeding/sortant-a-l-exterieur/Eleveur-poulets-exterieur-champs-demarche-elevage-Le-Gaulois.jpg',
|
||||
),
|
||||
'title' => 'Éleveur reposant une volaille dans son champs',
|
||||
'alt' =>
|
||||
'Éleveur Le Gaulois souriant reposant une volaille sur l\'herbe de son exploitation et entouré de trois autres poulets',
|
||||
],
|
||||
],
|
||||
[
|
||||
'image' => [
|
||||
'path' => Vite::asset(
|
||||
'resources/assets/images/breeding/sortant-a-l-exterieur/Poulets-herbes-champs-exterieur-Le-Gaulois.jpg',
|
||||
),
|
||||
'title' => 'Volailles à l\'extérieur dans le pré',
|
||||
'alt' => 'Poulets à l\'extérieur dans l\'herbe d\un champ',
|
||||
],
|
||||
],
|
||||
[
|
||||
'image' => [
|
||||
'path' => Vite::asset(
|
||||
'resources/assets/images/breeding/sortant-a-l-exterieur/Poulets-sortent-a-l-exterieur-poulailler-champs-Le-Gaulois.jpg',
|
||||
),
|
||||
'title' => 'Poulets sortant à l\'extérieur du poulailler',
|
||||
'alt' => 'Poulets qui sortent tous les jours dans les prés grâce aux trappes du poulailler d\'élevage',
|
||||
],
|
||||
],
|
||||
];
|
||||
@endphp
|
||||
|
||||
@props(['sliderImages' => []])
|
||||
<section class="position-relative negative-margin-sm overflow-hidden">
|
||||
<div class="position-absolute h-100 w-100 top-0 z-0">
|
||||
<div class="bg-white-wood-reverse h-100 w-100" id="slider-galery-outside-bg"></div>
|
||||
|
|
@ -66,11 +16,11 @@
|
|||
|
||||
<section class="swiper container-fluid position-relative container" id="swiper-breeding-galery-slides">
|
||||
<div class="swiper-wrapper w-fit">
|
||||
@foreach ($slides as $slide)
|
||||
@foreach ($sliderImages as $slide)
|
||||
<div class="swiper-slide">
|
||||
<div class="d-flex justify-content-center w-100 bg-light position-relative line-border-small p-2">
|
||||
<div class="w-100 swiper-breeding-galery-img-container bg-light position-relative line-border-small">
|
||||
<img class="w-100 h-100 block-center object-fit-cover" src="{{ $slide['image']['path'] }}"
|
||||
<img class="w-100 h-100 block-center object-fit-cover" src="{{ asset($slide['image']['path']) }}"
|
||||
title="{{ $slide['image']['title'] }}" alt="{{ $slide['image']['alt'] }}">
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
@extends('fo.layout')
|
||||
|
||||
@section('title', str('La marque 100% volaille française')->upper())
|
||||
@section('description', str('La marque 100% volaille française')->ucFirst())
|
||||
@section('bg-offset', true)
|
||||
|
||||
@section('content')
|
||||
<x-fo.breeding.section.header-section title="{{ __('Démarche sortant à l’extérieur') }}" />
|
||||
<x-fo.breeding.section.header-section title="{{ __($staticPageModel->title) }}" :image="$staticPageModel->picture"/>
|
||||
<section id="sortant-a-l-exterieur">
|
||||
<x-fo.breeding.section.sortant-a-l-exterieur.cahier-des-charges-section />
|
||||
<x-fo.breeding.section.sortant-a-l-exterieur.galery-section />
|
||||
<x-fo.breeding.section.sortant-a-l-exterieur.cahier-des-charges-section :staticPageModel="$staticPageModel" :onglets="$categoryApproachModels" :sections="$sectionApproachModels" />
|
||||
<x-fo.breeding.section.sortant-a-l-exterieur.galery-section :sliderImages="$sliderImages" />
|
||||
</section>
|
||||
{{-- <section class="pb-3 pt-5" id="breeder-map-section">
|
||||
<div class="pt-5">
|
||||
|
|
@ -16,3 +15,4 @@
|
|||
</div>
|
||||
</section> --}}
|
||||
@endsection
|
||||
|
||||
|
|
@ -26,6 +26,9 @@
|
|||
window.__SYSTEM._routes['fo.breeding.index'] = '{{ route('fo.breeding.index') }}';
|
||||
window.__SYSTEM._routes['fo.recruitment.show'] = '{{ route('fo.recruitment.show') }}';
|
||||
window.__SYSTEM._routes['fo.news.index'] = '{{ route('fo.news.index') }}';
|
||||
window.__SYSTEM._routes['bo.sections.approaches.json-paginate'] = '{{ route('bo.sections.approaches.json-paginate') }}';
|
||||
window.__SYSTEM._routes['bo.categories.approaches.json-paginate'] = '{{ route('bo.categories.approaches.json-paginate') }}';
|
||||
|
||||
// FO
|
||||
window.__SYSTEM._routes['fo.home.products'] = '{{ route('fo.home.products', ['legend_slug' => 'LEGENDSLUG']) }}';
|
||||
window.__SYSTEM._routes['fo.contact.show'] = '{{ route('fo.contact.show') }}';
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use App\Models\DemarcheSlide;
|
|||
use App\Models\KeyNumber;
|
||||
use App\Models\Profession;
|
||||
use App\Models\BrandAdvantage;
|
||||
use App\Models\CategoryApproach;
|
||||
use App\Models\Claim;
|
||||
use App\Models\ConsumptionMoment;
|
||||
use App\Models\Discount;
|
||||
|
|
@ -26,6 +27,7 @@ use App\Models\Product;
|
|||
use App\Models\ProductType;
|
||||
use App\Models\Range;
|
||||
use App\Models\Recipe;
|
||||
use App\Models\SectionApproach;
|
||||
use App\Models\SellItem;
|
||||
use App\Models\StaticPage;
|
||||
use App\Models\Submeat;
|
||||
|
|
@ -37,6 +39,7 @@ use App\Models\Video;
|
|||
use Diglactic\Breadcrumbs\Breadcrumbs;
|
||||
use Diglactic\Breadcrumbs\Generator;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
// * DASHBOARD
|
||||
Breadcrumbs::for('bo.dashboard', function (Generator $trail) {
|
||||
|
|
@ -433,6 +436,55 @@ Breadcrumbs::for('bo.approaches.duplicate', function (Generator $trail, int $app
|
|||
$trail->push(Str::ucfirst(trans('crud.actions.duplicate')));
|
||||
});
|
||||
|
||||
// * CATEGORIES APPROACHES
|
||||
Breadcrumbs::for('bo.categories.approaches.index', function (Generator $trail) {
|
||||
$trail->push(Str::ucfirst(trans('categories')), route('bo.categories.approaches.index'));
|
||||
});
|
||||
|
||||
Breadcrumbs::for('bo.categories.approaches.show', function (Generator $trail, CategoryApproach $category) {
|
||||
$trail->parent('bo.categories.approaches.index');
|
||||
$trail->push(Str::ucfirst(trans('crud.actions.view')), route('bo.categories.approaches.show', $category));
|
||||
});
|
||||
|
||||
Breadcrumbs::for('bo.categories.approaches.create', function (Generator $trail) {
|
||||
$trail->parent('bo.categories.approaches.index');
|
||||
$trail->push(Str::ucfirst(trans('crud.actions.create')), route('bo.categories.approaches.create'));
|
||||
});
|
||||
|
||||
Breadcrumbs::for('bo.categories.approaches.edit', function (Generator $trail, CategoryApproach $category) {
|
||||
$trail->parent('bo.categories.approaches.index');
|
||||
$trail->push(Str::ucfirst(trans('crud.actions.edit')), route('bo.categories.approaches.edit', $category));
|
||||
});
|
||||
|
||||
// * SECTIONS APPROACHES
|
||||
Breadcrumbs::for('bo.sections.approaches.index', function (Generator $trail) {
|
||||
$trail->push(Str::ucfirst(trans('sections')), route('bo.sections.approaches.index'));
|
||||
});
|
||||
|
||||
// Optionnel : index filtré par page (si tu veux un breadcrumb différent)
|
||||
Breadcrumbs::for('bo.sections.approaches.indexByPage', function (Generator $trail, ?StaticPage $page) {
|
||||
$trail->parent('bo.sections.approaches.index');
|
||||
$trail->push($page->title, route('bo.sections.approaches.index'));
|
||||
});
|
||||
|
||||
Breadcrumbs::for('bo.sections.approaches.show', function (Generator $trail, SectionApproach $section) {
|
||||
$trail->parent('bo.sections.approaches.index');
|
||||
$trail->push(Str::ucfirst(trans('crud.actions.view')), route('bo.sections.approaches.show', $section));
|
||||
});
|
||||
|
||||
Breadcrumbs::for('bo.sections.approaches.create', function (Generator $trail, ?StaticPage $page = null) {
|
||||
$trail->parent('bo.sections.approaches.index');
|
||||
if ($page) {
|
||||
$trail->push($page->title, route('bo.sections.approaches.index', ['page_id' => $page->id]));
|
||||
}
|
||||
$trail->push(Str::ucfirst(trans('crud.actions.create')), route('bo.sections.approaches.create'));
|
||||
});
|
||||
|
||||
Breadcrumbs::for('bo.sections.approaches.edit', function (Generator $trail, SectionApproach $section) {
|
||||
$trail->parent('bo.sections.approaches.index');
|
||||
$trail->push(Str::ucfirst(trans('crud.actions.edit')), route('bo.sections.approaches.edit', $section));
|
||||
});
|
||||
|
||||
// * CONSUMPTION_MOMENTS
|
||||
Breadcrumbs::for('bo.consumption_moments.index', function (Generator $trail) {
|
||||
$trail->push(
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use App\Http\Controllers\Bo\ActivityLogController;
|
|||
use App\Http\Controllers\Bo\ApproachController;
|
||||
use App\Http\Controllers\Bo\DemarcheSlideController;
|
||||
use App\Http\Controllers\Bo\BrandAdvantageController;
|
||||
use App\Http\Controllers\Bo\CategoryApproachesController;
|
||||
use App\Http\Controllers\Bo\ClaimController;
|
||||
use App\Http\Controllers\Bo\ConsumptionMomentController;
|
||||
use App\Http\Controllers\Bo\DashboardController;
|
||||
|
|
@ -35,6 +36,7 @@ use App\Http\Controllers\Bo\UploadController;
|
|||
use App\Http\Controllers\Bo\UserController;
|
||||
use App\Http\Controllers\Bo\VideoController;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Controllers\Bo\SectionApproachController;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
|
|
@ -323,6 +325,32 @@ Route::middleware(['throttle:web', 'admin-secure'])->prefix('bo')->name('bo.')->
|
|||
Route::get('/approaches/json/paginate', [ApproachController::class, 'jsonPaginateDemarches'])
|
||||
->name('approaches.json-paginate');
|
||||
|
||||
// * CATEGORY APPROACHES
|
||||
Route::resource('categories-approaches', CategoryApproachesController::class)
|
||||
->names('categories.approaches');
|
||||
|
||||
Route::get(
|
||||
'/categories-approaches/{categories_approach}/duplicate',
|
||||
[CategoryApproachesController::class, 'duplicate']
|
||||
)->name('categories.approaches.duplicate');
|
||||
|
||||
// * SECTION APPROACHES
|
||||
Route::resource('sections-approaches', SectionApproachController::class)
|
||||
->names('sections.approaches')
|
||||
->parameters(['sections-approaches' => 'section_approach'])
|
||||
->withoutMiddleware('htmlsanitize')
|
||||
->middleware('htmlsanitize:content');
|
||||
|
||||
Route::get(
|
||||
'/sections-approaches/{section_approach}/duplicate',
|
||||
[SectionApproachController::class, 'duplicate']
|
||||
)->name('sections.approaches.duplicate');
|
||||
Route::get('/sections-approaches/json/paginate', [SectionApproachController::class, 'jsonPaginatePage'])
|
||||
->name('sections.approaches.json-paginate');
|
||||
|
||||
Route::get('/categories-approaches/json/paginate', [CategoryApproachesController::class, 'jsonPaginateCategory'])
|
||||
->name('categories.approaches.json-paginate');
|
||||
|
||||
// * CONSUMPTION MOMENT.
|
||||
Route::resource('consumption_moments', ConsumptionMomentController::class)
|
||||
->withoutMiddleware('htmlsanitize')
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ use App\Http\Controllers\Fo\RatingController;
|
|||
use App\Http\Controllers\Fo\RecipeController;
|
||||
use App\Http\Controllers\Fo\SearchController;
|
||||
use App\Http\Controllers\Fo\StaticPageController;
|
||||
use App\Models\StaticPage;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::middleware(['throttle:web'])->name('fo.')->group(function () {
|
||||
|
|
@ -138,7 +137,7 @@ Route::middleware(['throttle:web'])->name('fo.')->group(function () {
|
|||
->group(function () {
|
||||
Route::view('/', 'fo.pages.breeding.index')->name('index');
|
||||
Route::get('/oui-c-est-bon', [BreedingController::class, 'ocbBreederPage'])->name('oui-c-est-bon');
|
||||
Route::view('/sortant-a-l-exterieur', 'fo.pages.breeding.sortant-a-l-exterieur')
|
||||
Route::get('/sortant-a-l-exterieur', [BreedingController::class, 'exitOutsidePage'])
|
||||
->name('sortant-a-l-exterieur');
|
||||
Route::get('/{breeding_static_page:slug}', [BreedingController::class, 'breedingPage'])
|
||||
->name('show');
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue