feat: ✨ add claim mail templates crud
This commit is contained in:
parent
7df0fe4634
commit
ed7ed6f55e
14 changed files with 813 additions and 94 deletions
174
app/Http/Controllers/Bo/ClaimMailTemplateController.php
Normal file
174
app/Http/Controllers/Bo/ClaimMailTemplateController.php
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Bo\ClaimMailTemplates\ClaimMailTemplateRequest;
|
||||
use App\Models\Brand;
|
||||
use App\Models\ClaimMailTemplate;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class ClaimMailTemplateController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create the controller instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->authorizeResource(ClaimMailTemplate::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
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $query */
|
||||
$query = ClaimMailTemplate::query()->when(
|
||||
$request->filled('brand'),
|
||||
fn($q) => $q->whereHas('brand', fn($q) => $q->where('id', $request->brand))
|
||||
);
|
||||
|
||||
if ($request->search) {
|
||||
$this->searchQuery(
|
||||
$query,
|
||||
$request->search,
|
||||
null,
|
||||
'label',
|
||||
);
|
||||
}
|
||||
|
||||
$this->sortQuery($query);
|
||||
$searchFields = trans('validation.custom.label');
|
||||
|
||||
$claimMailTemplateModels = $this->paginate($query);
|
||||
|
||||
return view('bo.pages.claim_mail_templates.index', compact('claimMailTemplateModels', 'searchFields'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the specified resource.
|
||||
*
|
||||
* @param \App\Models\ClaimMailTemplate $claim_mail_template
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function show(ClaimMailTemplate $claim_mail_template): \Illuminate\Contracts\View\View
|
||||
{
|
||||
return view('bo.pages.claim_mail_templates.show', [
|
||||
'claimMailTemplateModel' => $claim_mail_template,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @param \App\Models\ClaimMailTemplate $claim_mail_template
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function create(ClaimMailTemplate $claim_mail_template): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$brandModels = Brand::query()->orderBy('name', 'ASC')->paginate($this->jsonItemPerPagination);
|
||||
return view('bo.pages.claim_mail_templates.create', [
|
||||
'claimMailTemplateModel' => $claim_mail_template,
|
||||
'brandModels' => $brandModels,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\ClaimMailTemplates\ClaimMailTemplateRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(ClaimMailTemplateRequest $request): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$claimMailTemplateModel = new ClaimMailTemplate();
|
||||
$claimMailTemplateModel->fill($request->validated());
|
||||
if ($claimMailTemplateModel->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.claim_mail_templates.edit', $claimMailTemplateModel)
|
||||
->with('success', trans(
|
||||
':model a été créé.',
|
||||
['model' => Str::singular(trans('models.classes.claimmailtemplates'))]
|
||||
));
|
||||
}
|
||||
return redirect()
|
||||
->back()
|
||||
->with('error', trans(
|
||||
':model n\'a pas été créé.',
|
||||
['model' => Str::singular(trans('models.classes.claimmailtemplates'))]
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\ClaimMailTemplate $claim_mail_template
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit(ClaimMailTemplate $claim_mail_template): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$brandModels = Brand::query()->orderBy('name', 'ASC')->paginate($this->jsonItemPerPagination);
|
||||
return view('bo.pages.claim_mail_templates.edit', [
|
||||
'claimMailTemplateModel' => $claim_mail_template,
|
||||
'brandModels' => $brandModels,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a spacific resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\ClaimSubjects\ClaimMailTemplateRequest $request
|
||||
* @param \App\Models\ClaimMailTemplate $claim_mail_template
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(
|
||||
ClaimMailTemplateRequest $request,
|
||||
ClaimMailTemplate $claim_mail_template
|
||||
): \Illuminate\Http\RedirectResponse {
|
||||
return DB::transaction(function () use ($request, $claim_mail_template) {
|
||||
$claim_mail_template->fill($request->validated());
|
||||
if ($claim_mail_template->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.claim_mail_templates.edit', $claim_mail_template)
|
||||
->with('success', trans(
|
||||
':model a été mis à jour.',
|
||||
['model' => Str::singular(trans('models.classes.claimmailtemplates'))]
|
||||
));
|
||||
}
|
||||
return redirect()
|
||||
->back()
|
||||
->with('error', trans(
|
||||
':model n\'a pas été mis à jour.',
|
||||
['model' => Str::singular(trans('models.classes.claimmailtemplates'))]
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\ClaimMailTemplate $claim_mail_template
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function destroy(ClaimMailTemplate $claim_mail_template): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
if ($claim_mail_template->deleteOrFail()) {
|
||||
return redirect()->route('bo.claim_mail_templates.index')
|
||||
->with('success', __('crud.messages.has_been_deleted', [
|
||||
'model' => Str::of(__('models.classes.claimmailtemplates'))->singular()
|
||||
]));
|
||||
}
|
||||
return redirect()->back()
|
||||
->with('error', __('crud.messages.cannot_be_deleted', [
|
||||
'model' => Str::of(__('models.classes.claimmailtemplates'))->singular()
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Bo\ClaimMailTemplates;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class ClaimMailTemplateRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return auth('backend')->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'brand_id' => 'required|exists:brands,id',
|
||||
'label' => 'required|string|min:3|max:255',
|
||||
'content' => 'required|string|min:3|max:500',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get custom attributes for validator errors.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function attributes(): array
|
||||
{
|
||||
return [
|
||||
'brand_id' => trans('models.classes.brands'),
|
||||
'label' => trans('validation.custom.label'),
|
||||
'content' => trans('validation.attributes.content'),
|
||||
];
|
||||
}
|
||||
}
|
||||
109
app/Policies/ClaimMailTemplatePolicy.php
Normal file
109
app/Policies/ClaimMailTemplatePolicy.php
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Enums\Users\RoleEnum;
|
||||
use App\Models\ClaimMailTemplate;
|
||||
use App\Models\User;
|
||||
use App\Policies\Rules\UserStaticRules;
|
||||
|
||||
class ClaimMailTemplatePolicy
|
||||
{
|
||||
/**
|
||||
* ViewAny a claim subject.
|
||||
*
|
||||
* @param \App\Models\User $authUser
|
||||
* @return boolean
|
||||
*/
|
||||
public function viewAny(User $authUser): bool
|
||||
{
|
||||
return UserStaticRules::atLeastRole($authUser, RoleEnum::marketing);
|
||||
}
|
||||
|
||||
/**
|
||||
* View a claim subject.
|
||||
*
|
||||
* @param \App\Models\User $authUser
|
||||
* @param \App\Models\ClaimMailTemplate $claim_mail_template
|
||||
* @return boolean
|
||||
*/
|
||||
public function view(User $authUser, ClaimMailTemplate $claim_mail_template): bool
|
||||
{
|
||||
return $this->checkOnlyMinAdminOrInUserBrands($authUser, $claim_mail_template);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a claim subject.
|
||||
*
|
||||
* @param \App\Models\User $authUser
|
||||
* @return boolean
|
||||
*/
|
||||
public function create(User $authUser): bool
|
||||
{
|
||||
return UserStaticRules::atLeastRole($authUser, RoleEnum::marketing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a claim subject.
|
||||
*
|
||||
* @param \App\Models\User $authUser
|
||||
* @return boolean
|
||||
*/
|
||||
public function store(User $authUser): bool
|
||||
{
|
||||
return UserStaticRules::atLeastRole($authUser, RoleEnum::marketing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit a claim subject.
|
||||
*
|
||||
* @param \App\Models\User $authUser
|
||||
* @param \App\Models\ClaimMailTemplate $claim_mail_template
|
||||
* @return boolean
|
||||
*/
|
||||
public function edit(User $authUser, ClaimMailTemplate $claim_mail_template): bool
|
||||
{
|
||||
return $this->checkOnlyMinAdminOrInUserBrands($authUser, $claim_mail_template);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a claim subject.
|
||||
*
|
||||
* @param \App\Models\User $authUser
|
||||
* @param \App\Models\ClaimMailTemplate $claim_mail_template
|
||||
* @return boolean
|
||||
*/
|
||||
public function update(User $authUser, ClaimMailTemplate $claim_mail_template): bool
|
||||
{
|
||||
return $this->checkOnlyMinAdminOrInUserBrands($authUser, $claim_mail_template);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a claim subject.
|
||||
*
|
||||
* @param \App\Models\User $authUser
|
||||
* @param \App\Models\ClaimMailTemplate $claim_mail_template
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete(User $authUser, ClaimMailTemplate $claim_mail_template): bool
|
||||
{
|
||||
return $this->checkOnlyMinAdminOrInUserBrands($authUser, $claim_mail_template);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the user an access a specific resource.
|
||||
*
|
||||
* @param \App\Models\User $authUser
|
||||
* @param \App\Models\ClaimMailTemplate $claim_mail_template
|
||||
* @return boolean
|
||||
*/
|
||||
private function checkOnlyMinAdminOrInUserBrands(User $authUser, ClaimMailTemplate $claim_mail_template): bool
|
||||
{
|
||||
$userBrandModelKeys = $authUser->brands->pluck('id')->toArray();
|
||||
$claimMailTemplateModelKey = $claim_mail_template->brand->getKey();
|
||||
return UserStaticRules::atLeastRole($authUser, RoleEnum::admin) || (
|
||||
UserStaticRules::atLeastRole($authUser, RoleEnum::marketing)
|
||||
&& \in_array($claimMailTemplateModelKey, $userBrandModelKeys)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,109 +1,102 @@
|
|||
<template>
|
||||
<WordCounter
|
||||
:id="intId"
|
||||
:id="id"
|
||||
class="ck-word-count"
|
||||
/>
|
||||
<textarea
|
||||
ref="textarea"
|
||||
:id="intId"
|
||||
:class="`input-text-auto-component ${intClass}`"
|
||||
:name="intName"
|
||||
:aria-describedby="intAriaDescribedby"
|
||||
:placeholder="intPlaceholder"
|
||||
:required="intRequired"
|
||||
@input="onInput"
|
||||
:id="id"
|
||||
:class="{'form-control': true, [classPath]: !!classPath, 'is-invalid': errors.methods.parseValidationInput('content', allErrors)}"
|
||||
:name="name"
|
||||
:aria-describedby="ariaDescribedby"
|
||||
:placeholder="placeholder"
|
||||
:required="required"
|
||||
@input="styleElement(checkInput())"
|
||||
@blur="onBlur"
|
||||
v-model="intValue"
|
||||
v-model="value"
|
||||
rows="5"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref } from "vue";
|
||||
import trans from "../../modules/trans";
|
||||
<script lang="ts" setup>
|
||||
import { computed, nextTick, onBeforeMount, onMounted, ref, useAttrs } from "vue";
|
||||
import WordCounter from "./WordCounterComponent.vue";
|
||||
import errors from "./../../modules/errors";
|
||||
|
||||
const textarea = ref<HTMLTextAreaElement | null>(null);
|
||||
|
||||
export default defineComponent({
|
||||
name: "InputTextAutoComponent",
|
||||
inheritAttrs: false,
|
||||
mixins: [trans],
|
||||
components: {
|
||||
WordCounter,
|
||||
},
|
||||
setup() {
|
||||
return { textarea };
|
||||
},
|
||||
beforeMount() {
|
||||
if (!this.$attrs.json) {
|
||||
throw new Error("this component requires json");
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const json = String(this.$attrs.json ?? "{}"),
|
||||
data = JSON.parse(json);
|
||||
this.intId = String(data.id);
|
||||
this.intClass = String(data.class);
|
||||
this.intName = String(data.name);
|
||||
this.intPlaceholder = String(data.placeholder);
|
||||
this.intAriaDescribedby = String(data.ariaDescribedby);
|
||||
this.intValue = String(data.value);
|
||||
if (data.required) {
|
||||
this.intRequired = true;
|
||||
}
|
||||
if (this.textarea) {
|
||||
// Default input init
|
||||
this.textarea.setAttribute("style", "height: 1rem;overflow-y: hidden;");
|
||||
}
|
||||
// * Init input
|
||||
this.$nextTick(this.onInput);
|
||||
},
|
||||
data(): {
|
||||
intId: string;
|
||||
intClass: string;
|
||||
intName: string;
|
||||
intPlaceholder: string;
|
||||
intAriaDescribedby: string;
|
||||
intRequired: boolean;
|
||||
intValue: string;
|
||||
} {
|
||||
return {
|
||||
intId: "",
|
||||
intClass: "",
|
||||
intName: "",
|
||||
intPlaceholder: "",
|
||||
intAriaDescribedby: "",
|
||||
intRequired: false,
|
||||
intValue: "",
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onBlur() {
|
||||
const el = textarea.value;
|
||||
if (!el) {
|
||||
throw new Error("undefined textarea element");
|
||||
}
|
||||
// * Remove every new line char
|
||||
el.value = el.value.replace(/[\n\r]/g, "");
|
||||
this.$nextTick(() => {
|
||||
el.style.height = "auto";
|
||||
el.style.height = `${el.scrollHeight}px`;
|
||||
});
|
||||
},
|
||||
onInput() {
|
||||
const el = textarea.value;
|
||||
if (!el) {
|
||||
throw new Error("undefined textarea element");
|
||||
}
|
||||
el.style.height = "auto";
|
||||
el.style.height = `${el.scrollHeight}px`;
|
||||
},
|
||||
},
|
||||
defineOptions({
|
||||
name: "InputTextAutoComponent"
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.input-text-auto-component {
|
||||
resize: none;
|
||||
// * ATTRIBUTES
|
||||
const attrs = useAttrs();
|
||||
|
||||
// * REFS
|
||||
const textarea = ref<HTMLTextAreaElement|null>(null);
|
||||
|
||||
// * DATA
|
||||
/** Hack to set the id for wordCounterComponent. */
|
||||
const id = ref<string>(JSON.parse(String(attrs.json ?? "{}")).id);
|
||||
const classPath = ref<string>("");
|
||||
const name = ref<string>("");
|
||||
const placeholder = ref<string>("");
|
||||
const ariaDescribedby = ref<string>("");
|
||||
const value = ref<string>("");
|
||||
const required = ref<boolean>(true);
|
||||
const allErrors = ref<LaravelValidationErrors>({});
|
||||
|
||||
// * COMPUTED
|
||||
const isUsedWithProps = computed<boolean>(() => attrs.json === undefined);
|
||||
|
||||
onBeforeMount(() => {
|
||||
if (isUsedWithProps.value) {
|
||||
throw new Error("this component requires json");
|
||||
}
|
||||
});
|
||||
|
||||
// * LIFECYCLE
|
||||
onMounted(() => {
|
||||
const json = String(attrs.json ?? "{}"),
|
||||
data = JSON.parse(json);
|
||||
if (!isUsedWithProps.value) {
|
||||
id.value = String(data.id);
|
||||
classPath.value = String(data.class);
|
||||
name.value = String(data.name);
|
||||
placeholder.value = String(data.placeholder);
|
||||
ariaDescribedby.value = String(data.ariaDescribedby);
|
||||
value.value = String(data.value);
|
||||
required.value = data.required;
|
||||
textarea.value?.setAttribute("style", "height:1rem;overflow-y:hidden;");
|
||||
allErrors.value = data.errors;
|
||||
}
|
||||
nextTick(() => {
|
||||
styleElement(checkInput());
|
||||
});
|
||||
});
|
||||
|
||||
// * METHODS
|
||||
|
||||
/** When the textarea get the focus. */
|
||||
function onBlur() {
|
||||
const el = checkInput();
|
||||
/** Remove every new line char */
|
||||
// el.value = el.value.replace(/[\n\r]/g, "");
|
||||
nextTick(() => {
|
||||
styleElement(el);
|
||||
});
|
||||
}
|
||||
</style>
|
||||
|
||||
/** Check if the element is an HTMLTextAreaElement. */
|
||||
function checkInput(): HTMLTextAreaElement {
|
||||
const el = textarea.value;
|
||||
if (!el) {
|
||||
throw new Error("undefined textarea element");
|
||||
}
|
||||
return el;
|
||||
}
|
||||
|
||||
/** Style the textarea element. */
|
||||
function styleElement(el: HTMLTextAreaElement): void {
|
||||
el.style.height = "auto";
|
||||
el.style.height = `${el.scrollHeight}px`;
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
\App\Models\SingleOptin::class,
|
||||
\App\Models\Claim::class,
|
||||
\App\Models\ClaimSubject::class,
|
||||
\App\Models\ClaimMailTemplate::class,
|
||||
];
|
||||
@endphp
|
||||
@foreach ($modelsClasses as $crudModel)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
@extends('bo.layout')
|
||||
|
||||
@section('title', sprintf('%s - %s', __('models.classes.claimmailtemplates'), str(__('création'))->ucfirst()))
|
||||
@section('description', __('Création d\'une :model', ['model' => __('models.classes.claimmailtemplates')]))
|
||||
@section('metaIndex', 'noindex,nofollow')
|
||||
|
||||
@section('content')
|
||||
<div class="card border-0">
|
||||
<div class="card-header">
|
||||
<div class="d-flex justify-content-between flex-md-nowrap align-items-center flex-wrap">
|
||||
<div class="d-flex align-items-start flex-row">
|
||||
@can('viewAny', \App\Models\ClaimMailTemplate::class)
|
||||
<a class="btn btn-primary text-decoration-none me-2" data-bs-tooltip="tooltip" data-bs-placement="top"
|
||||
data-bs-tooltip="tooltip" href="{{ route('bo.claim_mail_templates.index') }}"
|
||||
title="{{ __('Retourner sur la liste des :model', ['model' => __('models.classes.claimmailtemplates')]) }}">
|
||||
<i class="fa-solid fa-arrow-left"></i>
|
||||
</a>
|
||||
@endcan
|
||||
@include('modules.breadcrumbs.breadcrumb-body')
|
||||
</div>
|
||||
@can('create', $claimMailTemplateModel)
|
||||
<div class="col-12 col-md-4 d-flex justify-content-center justify-content-md-end align-items-center">
|
||||
<button class="btn btn-primary" id="formSubmitClone" data-bs-tooltip="tooltip" type="button"
|
||||
title="{{ __('Sauvegarder cette :model', ['model' => Str::singular(__('models.classes.claimmailtemplates'))]) }}">
|
||||
{{ __('Sauvegarder') }}
|
||||
</button>
|
||||
</div>
|
||||
@endcan
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form action="{{ route('bo.claim_mail_templates.store') }}" method="POST">
|
||||
@csrf
|
||||
@include('bo.pages.claim_mail_templates.form')
|
||||
<div class="row">
|
||||
<div class="col text-center">
|
||||
@can('create', $claimMailTemplateModel)
|
||||
<button class="btn btn-primary" id="formSubmit" data-bs-tooltip="tooltip" type="submit"
|
||||
title="{{ __('Sauvegarder cette :model', ['model' => Str::singular(__('models.classes.claimmailtemplates'))]) }}">{{ __('Sauvegarder') }}</button>
|
||||
@endcan
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
65
resources/views/bo/pages/claim_mail_templates/edit.blade.php
Normal file
65
resources/views/bo/pages/claim_mail_templates/edit.blade.php
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
@extends('bo.layout')
|
||||
|
||||
@section('title', sprintf('%s - %s', __('models.classes.claimmailtemplates'), str(__('édition'))->ucfirst()))
|
||||
@section('description', __('Édition d\'une :model', ['model' => __('models.classes.claimmailtemplates')]))
|
||||
@section('metaIndex', 'noindex,nofollow')
|
||||
|
||||
@section('content')
|
||||
<div class="card border-0">
|
||||
<div class="card-header">
|
||||
<div class="d-flex justify-content-between flex-md-nowrap align-items-center flex-wrap">
|
||||
<div class="d-flex align-items-start flex-row">
|
||||
@can('viewAny', \App\Models\ClaimMailTemplate::class)
|
||||
<a class="btn btn-primary text-decoration-none me-2" data-bs-tooltip="tooltip" data-bs-placement="top"
|
||||
data-bs-tooltip="tooltip" href="{{ route('bo.claim_mail_templates.index') }}"
|
||||
title="{{ __('Retourner sur la liste des :model', ['model' => __('models.classes.claimmailtemplates')]) }}">
|
||||
<i class="fa-solid fa-arrow-left"></i>
|
||||
</a>
|
||||
@endcan
|
||||
@include('modules.breadcrumbs.breadcrumb-body')
|
||||
</div>
|
||||
<form class="btn-group" id="dataDelete"
|
||||
action="{{ route('bo.claim_mail_templates.destroy', $claimMailTemplateModel) }}" method="POST">
|
||||
@can('view', $claimMailTemplateModel)
|
||||
<a class="btn btn-warning" data-bs-tooltip="tooltip"
|
||||
href="{{ route('bo.claim_mail_templates.show', $claimMailTemplateModel->getKey()) }}"
|
||||
title="{{ __('Voir ce :model', ['model' => str(__('models.classes.claimmailtemplates'))->singular()]) }}">
|
||||
<i class="fa-solid fa-eye"></i>
|
||||
</a>
|
||||
@endcan
|
||||
@can('update', $claimMailTemplateModel)
|
||||
<button class="btn btn-primary" id="formSubmitClone" data-bs-tooltip="tooltip" type="button"
|
||||
title="{{ __('Sauvegarder ce :model', ['model' => str(__('models.classes.claimmailtemplates'))->singular()]) }}">
|
||||
{{ __('Sauvegarder') }}
|
||||
</button>
|
||||
@endcan
|
||||
@can('delete', $claimMailTemplateModel)
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button class="btn btn-danger" data-bs-tooltip="tooltip"
|
||||
title="{{ __('Supprimer ce :model', ['model' => str(__('models.classes.claimmailtemplates'))->singular()]) }}">
|
||||
<i class="fa-solid fa-trash"></i>
|
||||
</button>
|
||||
@endcan
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form action="{{ route('bo.claim_mail_templates.update', $claimMailTemplateModel->getKey()) }}" method="POST">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
@include('bo.pages.claim_mail_templates.form')
|
||||
<div class="row">
|
||||
<div class="col text-center">
|
||||
@can('update', $claimMailTemplateModel)
|
||||
<button class="btn btn-primary" id="formSubmit" data-bs-tooltip="tooltip" type="submit"
|
||||
title="{{ __('Sauvegarder ce :model', ['model' => str(__('models.classes.claimmailtemplates'))->singular()]) }}">
|
||||
{{ __('Sauvegarder') }}
|
||||
</button>
|
||||
@endcan
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
93
resources/views/bo/pages/claim_mail_templates/form.blade.php
Normal file
93
resources/views/bo/pages/claim_mail_templates/form.blade.php
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
<div class="row">
|
||||
{{-- BRAND --}}
|
||||
<div class="col-12 col-md-6 pb-3">
|
||||
<fieldset class="h-100 border p-3">
|
||||
<legend>{{ __('Marque') }}</legend>
|
||||
<div class="row">
|
||||
@include('bo.partials.inputs.search-belongs-to-dropdown', [
|
||||
'id' => 'claimMailTemplateBrand',
|
||||
'label' => __('Modifier la :model associée', [
|
||||
'model' => str(__('models.classes.brands'))->singular(),
|
||||
]),
|
||||
'name' => 'brand_id',
|
||||
'relation' => 'brand',
|
||||
'model' => $claimMailTemplateModel,
|
||||
'targetClass' => 'App\Models\Brand',
|
||||
'modelListPaginate' => $brandModels ?? [],
|
||||
'constructedRoute' => route('bo.brands.json-paginate'),
|
||||
'fieldName' => 'name',
|
||||
'multiple' => false,
|
||||
'required' => true,
|
||||
'disabled' => false,
|
||||
'placeholder' => __('Rechercher une :model', [
|
||||
'model' => str(__('models.classes.brands'))->singular(),
|
||||
]),
|
||||
'helper' => __('Sélectionner une :model qui sera associée parmis la liste.', [
|
||||
'model' => str(__('models.classes.brands'))->singular(),
|
||||
]),
|
||||
])
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
{{-- LABEL --}}
|
||||
<div class="col-12 col-md-6 mb-3">
|
||||
<fieldset class="h-100 border p-3">
|
||||
<legend>{{ str(__('validation.custom.label'))->ucfirst() }}</legend>
|
||||
<div class="row">
|
||||
<div class="col-12 mb-3">
|
||||
@include('bo.partials.inputs.varchar', [
|
||||
'id' => 'claimMailTemplateLabel',
|
||||
'label' => __('Nom du :model', [
|
||||
'model' => str(__('models.classes.claimsubjects'))->singular(),
|
||||
]),
|
||||
'hasWordCounter' => true,
|
||||
'name' => 'label',
|
||||
'required' => true,
|
||||
'model' => $claimMailTemplateModel ?? null,
|
||||
'helper' => __('Doit décrire précisément le produit (3 caractères minimum, 255 maximum).'),
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="col-12 mb-3">
|
||||
<fieldset class="h-100 border p-3">
|
||||
<legend>{{ str(__('validation.attributes.content'))->ucfirst() }}</legend>
|
||||
<div class="row">
|
||||
<div class="col-12 mb-3">
|
||||
@include('bo.partials.inputs.varchar-multiline', [
|
||||
'id' => 'claimMailTemplateContent',
|
||||
'label' => __('Texte du :model', [
|
||||
'model' => str(__('models.classes.claimsubjects'))->singular(),
|
||||
]),
|
||||
'name' => 'content',
|
||||
'model' => $claimMailTemplateModel ?? null,
|
||||
'required' => true,
|
||||
'helper' => __('validation.between.string', [
|
||||
'attribute' => __(':model', [
|
||||
'model' => str(__('models.classes.claimsubjects'))->singular(),
|
||||
]),
|
||||
'min' => 5,
|
||||
'max' => 160,
|
||||
]),
|
||||
'placeholder' => __('Votre texte ici.'),
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script @if (isset($nonce)) nonce="{{ $nonce }}" @endif>
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
// Submit button clone.
|
||||
const submit = document.getElementById('formSubmit')
|
||||
submitClone = document.getElementById('formSubmitClone');
|
||||
submitClone.addEventListener('click', (event) => {
|
||||
event.preventDefault();
|
||||
submit.click();
|
||||
})
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
<table class="table table-hover table-fix-action m-0">
|
||||
<thead class="border-top-0 border-start-0 border-end-0 border border-2">
|
||||
@include('bo.modules.table-col-sorter', [
|
||||
'cols' => [
|
||||
'label' => str(__('validation.custom.label'))->ucfirst(),
|
||||
'content' => str(__('validation.attributes.content'))->ucfirst(),
|
||||
'brand_id' => str(__('models.classes.brands'))->singular()->ucfirst(),
|
||||
'updated_at' => str(__('validation.attributes.updated_at'))->ucfirst(),
|
||||
],
|
||||
])
|
||||
</thead>
|
||||
<tbody>
|
||||
@if ($claimMailTemplateModels->count())
|
||||
@foreach ($claimMailTemplateModels as $claimMailTemplateModel)
|
||||
<tr>
|
||||
<td class="text-center align-middle">{{ $claimMailTemplateModel->label }}</td>
|
||||
<td class="text-center align-middle">{{ str($claimMailTemplateModel->content)->limit(50) }}</td>
|
||||
<td class="text-center align-middle">{{ $claimMailTemplateModel->brand->name }}</td>
|
||||
<td class="text-center align-middle">
|
||||
<span class="badge bg-warning text-bg-warning text-wrap">
|
||||
{{ $claimMailTemplateModel->updated_at }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="text-end align-middle">
|
||||
<form class="btn-group" id="dataDelete"
|
||||
action="{{ route('bo.claim_mail_templates.destroy', $claimMailTemplateModel) }}"
|
||||
method="POST">
|
||||
@can('view', $claimMailTemplateModel)
|
||||
<a class="btn btn-sm btn-warning" data-bs-tooltip="tooltip"
|
||||
href="{{ route('bo.claim_mail_templates.show', $claimMailTemplateModel->getKey()) }}"
|
||||
title="{{ __('Voir ce :model', ['model' => Str::singular(__('models.classes.claimmailtemplates'))]) }}">
|
||||
<i class="fa-solid fa-eye"></i>
|
||||
</a>
|
||||
@endcan
|
||||
@can('update', $claimMailTemplateModel)
|
||||
<a class="btn btn-sm btn-primary" data-bs-tooltip="tooltip"
|
||||
href="{{ route('bo.claim_mail_templates.edit', $claimMailTemplateModel->getKey()) }}"
|
||||
title="{{ __('Modifier ce :model', ['model' => Str::singular(__('models.classes.claimmailtemplates'))]) }}">
|
||||
<i class="fa-solid fa-pencil"></i>
|
||||
</a>
|
||||
@endcan
|
||||
@can('delete', $claimMailTemplateModel)
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button class="btn btn-sm btn-danger" data-bs-tooltip="tooltip"
|
||||
title="{{ __('Supprimer ce :model', ['model' => Str::singular(__('models.classes.claimmailtemplates'))]) }}">
|
||||
<i class="fa-solid fa-trash"></i>
|
||||
</button>
|
||||
@endcan
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
@else
|
||||
<tr>
|
||||
<td class="text-center" colspan="5">
|
||||
<span class="h3">
|
||||
{{ __('Aucun résultat pour les :models', ['models' => __('models.classes.claimmailtemplates')]) }}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
@endif
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
@extends('bo.layout')
|
||||
|
||||
@section('title', sprintf('%s - %s', __('models.classes.claimmailtemplates'), str(__('liste'))->ucfirst()))
|
||||
@section('description', __('Listage de toutes les :model', ['model' => __('models.classes.claimmailtemplates')]))
|
||||
@section('metaIndex', 'noindex,nofollow')
|
||||
|
||||
@section('content')
|
||||
<div class="row w-100 mx-auto">
|
||||
<div class="col p-0">
|
||||
<div class="card rounded-0 border-0">
|
||||
<div class="card-header">
|
||||
<div class="row w-100 mx-auto">
|
||||
<div class="col p-0">
|
||||
@include('modules.breadcrumbs.breadcrumb-body')
|
||||
</div>
|
||||
@can('create', \App\Models\ClaimMailTemplate::class)
|
||||
<div class="col-md-3 d-flex align-items-center p-0">
|
||||
<div class="input-group justify-content-end">
|
||||
<a class="btn btn-primary" data-bs-tooltip="tooltip"
|
||||
href="{{ route('bo.claim_mail_templates.create') }}"
|
||||
title="{{ __('Ajouter une :model', ['model' => str(__('models.classes.claimmailtemplates'))->singular()]) }}">
|
||||
<i class="fa-solid fa-plus"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@endcan
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@include('bo.modules.search-bar')
|
||||
<div class="row w-100 mx-auto mb-2">
|
||||
<div class="col table-responsive p-0">
|
||||
@include('bo.pages.claim_mail_templates.index-list')
|
||||
</div>
|
||||
</div>
|
||||
{!! $claimMailTemplateModels->links() !!}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
65
resources/views/bo/pages/claim_mail_templates/show.blade.php
Normal file
65
resources/views/bo/pages/claim_mail_templates/show.blade.php
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
@extends('bo.layout', ['brParam' => $claimMailTemplateModel])
|
||||
|
||||
@section('title', sprintf('%s - %s', __('models.classes.claimmailtemplates'), str(__('aperçu'))->ucfirst()))
|
||||
@section('description', __('Aperçu d\'un :model', ['model' => __('models.classes.claimmailtemplates')]))
|
||||
@section('metaIndex', 'noindex,nofollow')
|
||||
@section('breadcrumb', request()->route()->getName())
|
||||
|
||||
@section('content')
|
||||
<div class="card border-0">
|
||||
<div class="card-header">
|
||||
<div class="d-flex justify-content-between flex-md-nowrap align-items-center flex-wrap">
|
||||
<div class="d-flex align-items-start flex-row">
|
||||
@can('viewAny', \App\Models\ClaimMailTemplate::class)
|
||||
<a class="btn btn-primary text-decoration-none me-2" data-bs-tooltip="tooltip" data-bs-placement="top"
|
||||
data-bs-tooltip="tooltip" href="{{ route('bo.claim_mail_templates.index') }}"
|
||||
title="{{ __('Retourner sur la liste des :model', ['model' => __('models.classes.claimmailtemplates')]) }}">
|
||||
<i class="fa-solid fa-arrow-left"></i>
|
||||
</a>
|
||||
@endcan
|
||||
@include('modules.breadcrumbs.breadcrumb-body', ['brParam' => $claimMailTemplateModel])
|
||||
</div>
|
||||
<form class="btn-group" id="dataDelete"
|
||||
action="{{ route('bo.claim_mail_templates.destroy', $claimMailTemplateModel) }}" method="POST">
|
||||
@can('update', $claimMailTemplateModel)
|
||||
<a class="btn btn-primary" data-bs-tooltip="tooltip"
|
||||
href="{{ route('bo.claim_mail_templates.edit', $claimMailTemplateModel->getKey()) }}"
|
||||
title="{{ __('Modifier ce :model', ['model' => Str::singular(__('models.classes.claimmailtemplates'))]) }}">
|
||||
<i class="fa-solid fa-pencil"></i>
|
||||
</a>
|
||||
@endcan
|
||||
@can('delete', $claimMailTemplateModel)
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button class="btn btn-danger" data-bs-tooltip="tooltip"
|
||||
title="{{ __('Supprimer ce :model', ['model' => Str::singular(__('models.classes.claimmailtemplates'))]) }}">
|
||||
<i class="fa-solid fa-trash"></i>
|
||||
</button>
|
||||
@endcan
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table-sm table-bordered table-striped table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="w-50"><b>{{ str(__('validation.custom.label'))->ucfirst() }}</b></td>
|
||||
<td class="w-50">{{ $claimMailTemplateModel->label }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="w-50"><b>{{ str(__('validation.attributes.content'))->ucfirst() }}</b></td>
|
||||
<td class="w-50">
|
||||
<p class="m-0">
|
||||
{!! clean(nl2br($claimMailTemplateModel->content)) !!}
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="w-50"><b>{{ __('Marque') }}</b></td>
|
||||
<td class="w-50">{{ $claimMailTemplateModel->brand->name }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
@ -23,6 +23,7 @@
|
|||
'required' => $required,
|
||||
'value' => old($name, $model->{$name} ?? ''),
|
||||
'class' => 'w-100',
|
||||
'errors' => $errors->getBag('default')->getMessages() ?? [],
|
||||
];
|
||||
@endphp
|
||||
<div class="input-text-auto" data-json='@json($data)'></div>
|
||||
|
|
|
|||
|
|
@ -160,3 +160,20 @@ Breadcrumbs::for('bo.claim_subjects.show', function (Generator $trail) {
|
|||
$trail->parent('bo.claim_subjects.index');
|
||||
$trail->push(trans('Aperçu'));
|
||||
});
|
||||
|
||||
// * CLAIM MAIL TEMPLATES
|
||||
Breadcrumbs::for('bo.claim_mail_templates.index', function (Generator $trail) {
|
||||
$trail->push(trans('models.classes.claimsubjects'), route('bo.claim_mail_templates.index'));
|
||||
});
|
||||
Breadcrumbs::for('bo.claim_mail_templates.create', function (Generator $trail) {
|
||||
$trail->parent('bo.claim_mail_templates.index');
|
||||
$trail->push(trans('Création'), route('bo.claim_mail_templates.create'));
|
||||
});
|
||||
Breadcrumbs::for('bo.claim_mail_templates.edit', function (Generator $trail) {
|
||||
$trail->parent('bo.claim_mail_templates.index');
|
||||
$trail->push(trans('Édition'));
|
||||
});
|
||||
Breadcrumbs::for('bo.claim_mail_templates.show', function (Generator $trail) {
|
||||
$trail->parent('bo.claim_mail_templates.index');
|
||||
$trail->push(trans('Aperçu'));
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use App\Http\Controllers\Bo\ActivityLogsController;
|
|||
use App\Http\Controllers\Bo\AnswerController;
|
||||
use App\Http\Controllers\Bo\BrandController;
|
||||
use App\Http\Controllers\Bo\ClaimController;
|
||||
use App\Http\Controllers\Bo\ClaimMailTemplateController;
|
||||
use App\Http\Controllers\Bo\ClaimMessageController;
|
||||
use App\Http\Controllers\Bo\ClaimSubjectController;
|
||||
use App\Http\Controllers\Bo\CustomerController;
|
||||
|
|
@ -107,6 +108,9 @@ Route::middleware(['throttle:web', 'admin-secure'])->prefix('bo')->name('bo.')->
|
|||
// * CLAIM SUBJECTS.
|
||||
Route::resource('claim_subjects', ClaimSubjectController::class);
|
||||
|
||||
// * CLAIM MAIL TEMPLATES.
|
||||
Route::resource('claim_mail_templates', ClaimMailTemplateController::class);
|
||||
|
||||
// * OTHERS.
|
||||
Route::post('theme/set', [Controller::class, 'setTheme'])->name('theme.set');
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue