Refactor Code Notifications
This commit is contained in:
Jérémy Munsch 2021-03-10 17:16:31 +01:00
parent ae5b2d4105
commit a861e75538
22 changed files with 927 additions and 77 deletions

21
app/Casts/NiceDate.php Normal file
View file

@ -0,0 +1,21 @@
<?php
namespace App\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Support\Carbon;
class NiceDate implements CastsAttributes
{
public function get($model, $key, $value, $attributes)
{
$value = Carbon::parse($value);
return $value->isToday() ?
$value->format('H:i') : $value->format('Y/m/d H:i');
}
public function set($model, $key, $value, $attributes)
{
return Carbon::parse($value)->format('Y-m-d H:i:s');
}
}

View file

@ -2,6 +2,8 @@
namespace App\Enums;
use Kwaadpepper\Enum\BaseEnum;
/**
* @method static self exchange()
* @method static self reduction()

View file

@ -2,22 +2,30 @@
namespace App\Http\Controllers;
use App\Casts\NiceDate;
use App\Enums\NotificationType;
use App\Http\Requests\DeleteMessagesRequest;
use App\Http\Requests\SendMessageRequest;
use App\Http\Requests\SurveyAnswersRequest;
use App\Http\Requests\UpdateInfosRequest;
use App\Models\Articles;
use App\Models\ArticlesCategories;
use App\Models\Customers;
use App\Models\Message;
use App\Models\Notifications;
use App\Models\Reductions;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\View;
use RuntimeException;
use Snipe\BanBuilder\CensorWords;
class ClubController extends Controller
{
public function index(ArticlesCategories $category)
{
$this->getNotifications();
$reductions = Reductions::where([
['end_date_broadcast', '>', now()],
['status', 1]
@ -35,19 +43,15 @@ class ClubController extends Controller
$nbCustomers = Customers::count();
$notifications = 0;
if (Auth::guard('customer')->check()) {
$notifications = $this->getNotifications(Auth::guard('customer')->user());
}
// Cas de catégorie d'article
$category = $category->id ?? null;
return view('front.club.index', compact('montantReductions', 'nbCustomers', 'articles', 'categories', 'notifications', 'category'));
return view('front.club.index', compact('montantReductions', 'nbCustomers', 'articles', 'categories', 'category'));
}
public function infos()
{
$this->getNotifications();
$customer = Auth::guard('customer')->user();
if (!$customer)
abort(404);
@ -60,8 +64,7 @@ class ClubController extends Controller
$crmInfos = $crmCustomer->user;
$birthDate = explode('-', $crmInfos->birth_date);
$notifications = $this->getNotifications($customer);
return view('front.club.informations', compact('customer', 'notifications', 'crmInfos', 'birthDate'));
return view('front.club.informations', compact('customer', 'crmInfos', 'birthDate'));
}
/**
@ -93,25 +96,17 @@ class ClubController extends Controller
return redirect()->route('account.infos')->with('success', __("Vos informations ont bien été enregistrées."));
}
/**
* Retrieve the number of notifications the current authenticated user has
* @param Customer $customer The user whose number of notifications we want to retrieve
*/
private function getNotifications()
{
return Auth::guard('customer')->check() ? Notifications::count() - Auth::guard('customer')->user()->notifications_read()->count() : 0;
}
/**
* Call the notifications page
*/
public function notifications()
{
$notificationsList = Notifications::orderBy('created_at', 'DESC')->with('notifiable')->get();
$this->getNotifications();
$notificationsIds = Notifications::pluck('id')->toArray();
Auth::guard('customer')->user()->notifications_read()->sync($notificationsIds);
$notifications = $this->getNotifications();
return view('front.club.notifications', compact('notifications', 'notificationsList'));
/** @var \App\Models\Customers */
$customer = Auth::guard('customer')->user();
$customer->readNotifications()->sync($notificationsIds);
return view('front.club.notifications');
}
/**
@ -119,10 +114,9 @@ class ClubController extends Controller
*/
public function cart()
{
$this->getNotifications();
$products = Auth::guard('customer')->user()->products;
$notifications = $this->getNotifications();
return view('front.club.cart', compact('products', 'notifications'));
return view('front.club.cart', compact('products'));
}
/**
@ -130,10 +124,9 @@ class ClubController extends Controller
*/
public function favoritesRecipes()
{
$this->getNotifications();
$recipes = Auth::guard('customer')->user()->recipes;
$notifications = $this->getNotifications();
return view('front.club.favorites-recipes', compact('recipes', 'notifications'));
return view('front.club.favorites-recipes', compact('recipes'));
}
/**
@ -141,12 +134,12 @@ class ClubController extends Controller
*/
public function reductions()
{
$notifications = $this->getNotifications();
$this->getNotifications();
// TODO: get url from MesBr class
/** @var \App\Lib\MesBR */
$mesBR = app('mesBr');
$urlReductions = "https://www.mesbr.eu/?refsite=" . config('app.REF_SITE') . "&refcamp=" . config('app.REF_CAMP') . "&hash=" . Auth::guard('customer')->user()->hashcode . "&now=" . time();
return view('front.club.reductions', compact('urlReductions', 'notifications'));
return view('front.club.reductions', compact('urlReductions'));
}
/**
@ -156,8 +149,7 @@ class ClubController extends Controller
*/
public function article(Articles $publishedArticle)
{
$notifications = $this->getNotifications();
$this->getNotifications();
// Check si le customer connecté a déjà répondu
$alreadyAnswered = false;
if (Auth::guard('customer')->check()) {
@ -179,7 +171,6 @@ class ClubController extends Controller
return view('front.club.article', compact(
'publishedArticle',
'categories',
'notifications',
'linkedArticles',
'alreadyAnswered'
));
@ -207,4 +198,75 @@ class ClubController extends Controller
return back();
}
public function messages()
{
$this->getNotifications();
/** @var \App\Models\Customers */
$customer = Auth::guard('customer')->user();
$conversations = $customer->conversations();
return view('front.club.messages', compact('conversations'));
}
public function sendMessage(SendMessageRequest $request)
{
$customer = Customers::where('username', $request->to)->firstOrFail();
$message = new Message($request->all());
$message->to = $customer->id;
$message->from = Auth::guard('customer')->user()->id;
$censor = new CensorWords();
try {
$censor->setDictionary(['en-us', 'en-uk', config('app.locale')]);
} catch (RuntimeException $e) {
$censor->setDictionary(['en-us', 'en-uk', 'fr']);
}
$message->message = $censor->censorString($message->message)['clean'];
$message->saveOrFail();
return response()->json($message->load(['toCustomer' => function ($q) {
$q->select(['id', 'username', 'created_at']);
}, 'fromCustomer' => function ($q) {
$q->select(['id', 'username', 'created_at']);
}]));
}
public function deleteMessage(DeleteMessagesRequest $request)
{
/** @var \App\Models\Customers */
$customer = Auth::guard('customer')->user();
$message = Message::findOrFail($request->message);
$conversations = (object)$customer->conversations();
foreach ($conversations as $conversation) {
$conversation = (object)$conversation;
if ($conversation->id != $message->id) {
continue;
}
/** @var \App\Models\Message $message */
foreach ($conversation->messages as $message) {
if ($message->from == $customer->id) {
$message->hide_from = true;
}
if ($message->to == $customer->id) {
$message->hide_to = true;
}
if ($message->hide_to && $message->hide_from) {
$message->delete();
} else {
$message->saveOrFail();
}
}
}
return response()->json();
}
private function getNotifications()
{
if (!Auth::guard('customer')->check()) {
return;
}
/** @var \App\Models\Customers */
$customer = Auth::guard('customer')->user();
$notifications = $customer->getAllNotifications();
View::share('notifications', count($notifications));
View::share('notificationsList', $notifications);
}
}

View file

@ -19,7 +19,8 @@ class ContactController extends Controller
$user = null;
$status = $request->session()->get('status');
$type = $type ?? ContactFormType::none();
return view('front.contact.contact', compact('type', 'user', 'status'));
$username = $request->username ?? '';
return view('front.contact.contact', compact('type', 'user', 'status', 'username'));
}
public function contactSubmit(ContactFormRequest $request)
@ -53,6 +54,11 @@ class ContactController extends Controller
return back()->withInput()->with('status', false);
}
public function reportCustomer(Request $request)
{
return $this->contact($request, ContactFormType::abuse());
}
public function proposeRecipe(Request $request)
{
return $this->contact($request, ContactFormType::recipe());

View file

@ -0,0 +1,31 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
class DeleteMessagesRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return Auth::guard('customer')->check();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'message' => 'required|exists:messages,id'
];
}
}

View file

@ -0,0 +1,32 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
class SendMessageRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return Auth::guard('customer')->check();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'message' => 'required|string|max:255|min:10',
'to' => 'required|exists:customers,username'
];
}
}

View file

@ -4,8 +4,10 @@ namespace App\Models;
use App\Exceptions\CrmException;
use App\Http\Resources\CustomerCrmResource;
use Illuminate\Support\Str;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Support\Carbon;
class Customers extends Authenticatable
{
@ -28,7 +30,70 @@ class Customers extends Authenticatable
return $this->belongsToMany(Products::class, 'cart', 'customer_id', 'product_id');
}
public function notifications_read() {
public function messages()
{
return $this->hasMany(Message::class, 'to');
}
public function sentMessages()
{
return $this->hasMany(Message::class, 'from');
}
/**
* Get conversations with messages sorted by time
*
* @return array
*/
public function conversations(): array
{
$dateSort = function ($a, $b) {
return Carbon::parse($a->created_at)->timestamp < Carbon::parse($b->created_at)->timestamp;
};
$messageFilter = function ($item) {
return $item->all();
};
$messageWith = [
'fromCustomer' => function ($q) {
$q->select(['id', 'username', 'created_at']);
},
'toCustomer' => function ($q) {
$q->select(['id', 'username', 'created_at']);
}
];
/**
* Hack workaround https://github.com/livewire/livewire/issues/1054
*/
$sentM = $this->sentMessages()->with($messageWith)->get()
->groupBy('toCustomer.username')->map($messageFilter);
$receivedM = $this->messages()->where('hide_to', false)->with($messageWith)->get()
->groupBy('fromCustomer.username')->map($messageFilter);
return $receivedM->mapWithKeys(function ($messagesArray, $fromUsername) use ($sentM, $dateSort) {
$responses = collect(\array_merge($sentM->get($fromUsername) ?? [], $messagesArray))->sort($dateSort);
$last = $responses->first();
return [$fromUsername => [
'to' => $fromUsername,
'id' => $last->id,
'date' => $last->created_at,
'preview' => Str::limit($last->message, 15),
'messages' => $responses->values()->all()
]];
})->toArray();
}
public function notifications()
{
return $this->belongsToMany(Notifications::class);
}
public function getAllNotifications()
{
return Notifications::where('customer_id', $this->id)
->orWhere('customer_id', null)->with('notifiable')->get();
}
public function readNotifications()
{
return $this->belongsToMany(Notifications::class, 'notifications_read', 'customer_id', 'notification_id');
}
@ -131,21 +196,25 @@ class Customers extends Authenticatable
*/
public function toArray()
{
return collect(array_merge(
parent::toArray(),
(array)$this->apiData
))->intersectByKeys([
'email' => '',
'firstname' => '',
'lastname' => '',
'address' => '',
'address2' => '',
'postcode' => '',
'birth_date' => '',
'city' => '',
'country' => '',
'opt_in' => '',
'phone' => ''
])->toArray();
if ($this->crm_id) {
return collect(array_merge(
parent::toArray(),
(array)$this->apiData
))->intersectByKeys([
'email' => '',
'firstname' => '',
'lastname' => '',
'address' => '',
'address2' => '',
'postcode' => '',
'birth_date' => '',
'city' => '',
'country' => '',
'opt_in' => '',
'phone' => ''
])->toArray();
} else {
return parent::toArray();
}
}
}

27
app/Models/Message.php Normal file
View file

@ -0,0 +1,27 @@
<?php
namespace App\Models;
use App\Casts\NiceDate;
use Illuminate\Database\Eloquent\Model;
class Message extends Model
{
protected $casts = [
'created_at' => NiceDate::class,
];
protected $fillable = [
'message',
'to'
];
public function toCustomer()
{
return $this->belongsTo(Customers::class, 'to');
}
public function fromCustomer()
{
return $this->belongsTo(Customers::class, 'from');
}
}

View file

@ -22,8 +22,4 @@ class Notifications extends Model
public function notifiable() {
return $this->morphTo();
}
public function notifications_read() {
return $this->belongsToMany(Customers::class, 'notifications_read', 'notification_id', 'customer_id');
}
}

View file

@ -21,7 +21,8 @@
"laravel/ui": "^2.1",
"mews/purifier": "^3.3",
"league/csv": "^9.6",
"riverskies/laravel-mobile-detect": "^1.3"
"riverskies/laravel-mobile-detect": "^1.3",
"snipe/banbuilder": "^2.3"
},
"require-dev": {
"facade/ignition": "^2.0",

View file

@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
class AddCustomerIdToNotificationsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('notifications', function (Blueprint $table) {
$table->foreignId('customer_id')->nullable()->after('content');
$table->foreign('customer_id')->references('id')->on('customers')->cascadeOnDelete();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('notifications', function (Blueprint $table) {
$table->dropForeign(['customer_id']);
$table->dropColumn(['customer_id']);
});
}
}

View file

@ -0,0 +1,42 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
class CreateMessagesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('messages', function (Blueprint $table) {
$table->id();
$table->string('message', 255);
$table->boolean('hide_from')->default(false);
$table->boolean('hide_to')->default(false);
$table->foreignId('from')->nullable();
$table->foreign('from')->references('id')->on('customers')->cascadeOnDelete();
$table->foreignId('to')->nullable();
$table->foreign('to')->references('id')->on('customers')->cascadeOnDelete();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('messages');
}
}

View file

@ -0,0 +1,187 @@
<template>
<div class="message-bloc clearfix">
<aside class="aside-bloc">
<div class="input-recherche input-group" data-children-count="1">
<input ref="filterInput" @keyup="filterConversations($event)" type="text" class="field-text" :placeholder="__('Rechercher...')">
<span @click="clearFilter($event)" class="addon-btn"><i class="icon-croix"></i></span>
<button class="btn-submit"><i class="icon-loupe"></i></button>
</div>
<div class="scroll-bloc">
<div class="inner-wrap">
<ul class="list-contact">
<li class="msg-non-lu" v-for="(conversation, name) of conversations" v-bind:key="name" @click="showConversation(conversation, $event)">
<a href="#" class="popup-trigger clearfix">
<i class="icon-faq-contact"></i>
<div class="wrap-text">
<h3>
<span class="auteur">{{ conversation.to }}</span>
<span class="date-publication">{{ conversation.date }}</span>
</h3>
<p class="msg-preview">{{ conversation.preview }}</p>
</div>
</a>
</li>
<li v-if="!Object.keys(conversations).length">
<a href="#" class="popup-trigger clearfix" v-on:click.prevent>
<i class="icon-faq-contact"></i>
<div class="wrap-text">
<h3>
<span class="auteur">{{ __('Pas de message') }}</span>
</h3>
<p class="msg-preview"></p>
</div>
</a>
</li>
</ul>
</div>
</div>
</aside>
<div class="main-message hidden-xs">
<div class="scroll-bloc">
<div class="inner-wrap">
<ul class="list-message" data-simplebar>
<li class="msg-item" v-for="message of activeConversation.messages" v-bind:key="message.id">
<h3>
<span class="auteur">{{ message.from_customer.username }}</span>
<span class="date-publication">{{ message.created_at }}</span>
</h3>
<div class="msg-txt">
<p>{{ message.message }}</p>
</div>
</li>
</ul>
</div>
</div>
<div ref="form" class="reponse-bloc display-none">
<div ref="formErrors" class="error-msg display-none"><p></p></div>
<fieldset data-children-count="1">
<textarea v-model="message" cols="20" rows="10" :placeholder="__('Votre message...')"></textarea>
</fieldset>
<div class="bottom-bloc">
<p class="link">
<a @click="reportAbuse($event)" href="#" :title="__('Signaler un abus')">{{ __('Signaler un abus') }}</a>
&nbsp;|&nbsp;
<a @click="deleteConversation($event)" class="message-delete-btn" href="#" :title="__('Supprimer cette conversation')">{{ __('Supprimer cette conversation') }}</a>
</p>
<i ref="loading" class="fas fa-spinner fa-pulse display-none"></i>
<button ref="submit" class="btn btn-red btn-arronded-20 reply-btn" :title="__('Répondre')" @click="sendMessage">{{ __('Répondre') }}</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
mounted() {
this.conversations = JSON.parse(this.dbconversations);
this.orig_conversations = this.conversations;
},
props: [
'dbconversations'
],
data() {
return {
conversations: {},
orig_conversations: {},
activeConversation: {},
message: null
}
},
methods: {
filterConversations(e) {
if(!e.currentTarget.value.length) {
this.$set(this, 'conversations', this.orig_conversations);
return;
}
let out = {};
for(let key in this.conversations) {
let conversation = this.conversations[key];
if(conversation.to.toLowerCase().indexOf(e.currentTarget.value) !== -1) {
out[key] = conversation;
continue;
}
if(conversation.preview.toLowerCase().indexOf(e.currentTarget.value) !== -1) {
out[key] = conversation;
continue;
}
}
this.$set(this, 'conversations', out);
},
clearFilter(e) {
e.preventDefault();
this.$set(this, 'conversations', this.orig_conversations);
this.$refs.filterInput.value ="";
},
reportAbuse(e) {
e.preventDefault();
if(!this.activeConversation.id) {
return;
}
window.location.href = this.route('reportCustomer') + '?username='+this.activeConversation.to;
},
showConversation(conversation, e) {
e.preventDefault();
this.$refs.form.classList.remove('display-none');
for(let li of document.querySelectorAll('.list-contact > li')) {
li.classList.remove('active');
}
e.currentTarget.classList.add('active');
this.activeConversation = conversation;
},
setMessage(message) {
this.activeConversation.messages.unshift(message);
this.$set(this, 'message', '');
},
deleteConversation(e) {
e.preventDefault();
axios.post(this.route('deleteMessage'), { message: this.activeConversation.id })
.catch((error) => {
console.error('Error', error.message);
})
.then(() => {
delete this.conversations[this.activeConversation.to];
delete this.orig_conversations[this.activeConversation.to];
this.$set(this, 'activeConversation', {});
});
},
sendMessage(e) {
e.preventDefault();
this.$refs.submit.disabled = true;
this.$refs.loading.classList.remove('display-none');
axios.post(this.route('sendMessage'), { message: this.message, to: this.activeConversation.to })
.then((response) => {
this.$refs.submit.disabled = false;
this.$refs.formErrors.classList.add('display-none');
this.setMessage(response.data);
})
.catch((error) => {
if (error.response) {
switch (error.response.status) {
case 422:
this.$refs.formErrors.classList.remove('display-none');
this.$refs.formErrors.childNodes[0].innerText = _.flatten(_.map(error.response.data.errors, (val, key) => {
return '\n' + val.join('\n');
}));
break;
default:
this.$refs.formErrors.classList.remove('display-none');
this.$refs.formErrors.childNodes[0].innerText = this.__('Une erreur est survenue');
console.error(this.__('Une erreur est survenue'));
alert(this.__('Une erreur est survenue'));
document.location.reload();
}
} else if (error.request) {
console.error(error.request);
} else {
console.error('Error', error.message);
}
})
.then(() => {
this.$refs.submit.disabled = false;
this.$refs.loading.classList.add('display-none');
});
}
}
}
</script>

View file

@ -33,5 +33,7 @@
"send": "Envoyer",
"civilty": "Civilité",
"message_contact_send": "Votre message a été envoyé avec succès.",
"message_contact_failed": "Une erreur est survenue durant l'envoi de votre message. Veuillez réessayer ultèrieurement."
"message_contact_failed": "Une erreur est survenue durant l'envoi de votre message. Veuillez réessayer ultèrieurement.",
"report_abuse": "Signaler un abus",
"report_abuse_message" : "Je souhaite signaler le message de :username car cet utilisateur ne respecte pas les conditions d'utilisation du Club des Gaulois.\n\nCordialement"
}

View file

@ -1,5 +1,5 @@
.content.contact {
max-width: inherit;
max-width: inherit !important;
aside {
float: left;

View file

@ -1,5 +1,5 @@
.content.error {
max-width: inherit;
max-width: inherit !important;
background-image: url('~@/images/commun/404.jpg');
background-size: cover;
background-position: center center;

View file

@ -0,0 +1,283 @@
.content.messages {
.message-bloc {
border: 1px solid #dfd2c7;
border-radius: 3px;
display: flex;
width: 100%;
@include min-width($tablet) {
margin-bottom: 70px;
}
.aside-bloc {
background-color: #fbf8f5;
border-right: 1px solid #dfd2c7;
width: 100%;
@include min-width($tablet) {
height: inherit;
//-webkit-flex-basis: 295px;
//flex-basis: 295px;
width: 295px;
}
.scroll-bloc {
height: 450px;
@include min-width($tablet) {
width: 295px !important;
}
}
.list-contact {
li {
border-top: 1px solid #dfd2c7;
&.msg-non-lu {
.icon-faq-contact {
opacity: 1;
visibility: visible;
}
}
&.active, &:hover {
background-color: #1e5ba1;
color: #fff;
h3 {
color: #fff;
.date-publication { color: #fff; }
}
p { color: #fff; }
}
a {
display: inline-block;
padding: 20px 18px;
width: 100%;
@include min-width($tablet) {
padding: 20px 13px;
}
&.active, &:hover {
background-color: #1e5ba1;
color: #fff;
h3 {
color: #fff;
.date-publication { color: #fff; }
}
p { color: #fff; }
}
}
.icon-faq-contact {
color: #fab818;
float: left;
font-size: 19px;
margin-right: 15px;
opacity: 0;
visibility: hidden;
}
.wrap-text {
overflow: hidden;
}
}
h3 {
display: flex;
color: #1e5ba1;
font-family: 'Catamaran-Bold';
font-size: 18px;
line-height: 100%;
.date-publication {
color: #ab9d8e;
font-size: 13px;
margin-left: auto;
}
span {
display: inline-block;
}
.auteur {
overflow: hidden;
text-overflow: ellipsis;
}
}
p {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
.input-recherche {
background: #fff;
border: 1px solid #dfd2c7;
display: flex;
height: 50px;
line-height: 48px;
margin: 24px;
padding: 10px 14px;
width: auto;
input {
background: inherit;
border: none;
color: #999595;
height: 26px;
line-height: 26px;
vertical-align: middle;
}
.field-text {
display: table-cell;
position: relative;
width: 100%;
}
.btn-submit {
cursor:pointer;
background: inherit;
border: none;
color: #bcafa1;
display: table-cell;
height: 26px;
vertical-align: middle;
padding: 0 8px;
width: 26px;
flex-basis: 26px;
i {
font-size: 26px;
}
}
.addon-btn {
cursor: pointer;
line-height: 1.2;
padding: 8px;
vertical-align: middle;
i {
color: #e0d2c5;
font-size: 12px;
}
}
}
}
.main-message {
background-color: #f8f2ed;
height: inherit;
overflow: hidden;
position: relative;
width: 100%;
.scroll-bloc {
height: 340px;
overflow: auto;
}
.inner-wrap {
padding: 25px 8px 25px 18px;
@include min-width($tablet) {
padding: 25px 20px 25px 30px;
}
}
.list-message {
.msg-item {
margin-bottom: 25px;
&:last-child { margin-bottom: 0; }
@include min-width($tablet) {
margin-bottom: 20px;
}
}
h3 {
color: #1e5ba1;
display: flex;
font-family: 'Catamaran-Bold';
font-size: 18px;
line-height: 100%;
margin-bottom: 14px;
@include min-width($tablet) {
margin-bottom: 10px;
}
span {
display: inline-block;
}
.date-publication {
color: #ab9d8e;
font-size: 15px;
margin-left: auto;
@include min-width($tablet) {
margin-left: 15px;
}
}
}
.msg-txt {
background-color: #fff;
border-radius: 3px;
padding: 20px;
@include min-width($tablet) {
padding: 20px 25px;
}
}
p {
color: #000;
}
}
.reponse-bloc {
background-color: #1e5ba1;
border-radius: 0 0 3px 0;
//bottom: 0;
//left: 0;
margin-top: 20px;
padding: 30px;
//position: absolute;
width: 100%;
height:100%;
fieldset {
display: block;
}
textarea {
color: #999595;
font-family: 'Catamaran-Regular';
font-size: 1.5em;
height: 100px;
padding: 15px;
width: 100%;
resize:none;
&::-webkit-input-placeholder { color: #999595; }
&::-moz-placeholder { color: #999595; }
&:-ms-input-placeholder { color: #999595; }
&:-moz-placeholder { color: #999595; }
@include min-width($tablet) {
height: 78px;
}
}
p {
color: #fff;
}
a {
color: #fff;
}
.bottom-bloc {
margin-top: 15px;
text-align: center;
@include min-width($tablet) {
text-align: left;
display: flex;
align-items: flex-end;
}
svg {
font-size: 2em;
margin-right: 1em;
margin-bottom: 0.4em;
}
.link {
color: #f9b719;
text-align: center;
margin-bottom: 15px;
@include min-width($tablet) {
margin-bottom: 0;
text-align: left;
}
a {
color: #fff;
display: inline-block;
text-decoration: underline;
vertical-align: middle;
}
}
.btn {
text-transform: uppercase;
&:disabled {
background-color: #200000;
}
@include min-width($tablet) {
margin-left: auto;
text-transform: none;
}
}
}
}
}
}

View file

@ -62,5 +62,6 @@
@import "front/pages/club/index";
@import "front/pages/club/content";
@import "front/pages/club/article";
@import "front/pages/club/messages";
@import "front/pages/club/boutique/index";
@import "front/pages/club/boutique/validated";

View file

@ -0,0 +1,48 @@
@extends('layouts.app')
@section('title', 'Club des Gaulois mes notifications')
@section('description', "Soyez averti de nouvelles activités sur le Club des Gaulois via des alertes : forum, message, nouveautés, sondage")
@section('sub_header')
<div class="sub_header sub_header_club">
<div class="content">
@include('front.club.modules.customerToolbar')
<div class="title-club-account">
<p>
<img src="{{ asset('assets/images/club/logo-leclub.png') }}" alt="{{ __('Le Club des Gaulois - Le Gaulois') }}">
{{ __('Mes messages') }}
</p>
</div>
<!-- TODO : GESTION IMG SI MOBILE -->
<img src="{{ asset('assets/images/club/bandeau-club-dsktp.png') }}" alt="{{ __('Le club des Gaulois - Le Gaulois') }}" class="img-club">
</div>
</div>
@endsection
@section('content')
@include('front.club.modules.quicklink', ['top' => true])
<section class="content-page-club">
<div class="messages content">
<div class="inner-size">
<h1>
<i class="icon-messages"></i>
<span>{{ __('Mes messages') }}</span>
</h1>
<h2 class="notif-sub-title">{{ __('Vos messages facilement accessibles grâce à la barre de recherche.') }}</h2>
<messages dbconversations='@json($conversations)'></messages>
</div>
</div>
</section>
@endsection
@push('scriptsConstants')
<script>
window._locale = '{{ app()->getLocale() }}';
window._translations = @json(cache(sprintf('translations.%s', app()->getLocale())));
window._asset = '{{ asset('') }}';
window._routes = {
'reportCustomer': '{{ route('account.reportCustomer') }}',
'sendMessage': '{{ route('account.sendMessage') }}',
'deleteMessage': '{{ route('account.deleteMessage') }}'
};
</script>
@endpush

View file

@ -46,7 +46,7 @@
@else
<h4>{{ __('question_concern')}}&nbsp;:</h4>
@endif
@if($type->equals(ContactFormType::complain()) or $type->equals(ContactFormType::recipe()))
@if($type->equals(ContactFormType::complain()) or $type->equals(ContactFormType::recipe()) or $type->equals(ContactFormType::abuse()))
<input type="text" class="display-none" name="type" value="{{ $type->value }}" readonly />
@else
<div class="styled-select">
@ -123,7 +123,9 @@
__('Temps de préparation'),
__('Temps de cuisson'),
__('Difficulté')
) !!}@endif</textarea>
) !!}@endif @if($type->equals(ContactFormType::abuse())){{
__('report_abuse_message', ['username' => $username ?? ''])
}}@endif</textarea>
@if($errors->default->has('message'))<small class="text-danger">{{ implode('<br>', $errors->default->get('message')) }}</small>@endif
</p>

View file

@ -31,7 +31,7 @@
<a href="{{ route('home') }}" class="btn btn-red btn-arronded-20 text-uppercase">{{ __('Retour à l\'accueil') }}</a>
</div>
@else
@if(!$type->equals(ContactFormType::complain()) and !$type->equals(ContactFormType::recipe()))
@if(!$type->equals(ContactFormType::complain()) and !$type->equals(ContactFormType::recipe()) and !$type->equals(ContactFormType::abuse()))
<p class="text-white">{{ __('Si vous désirez plutôt envoyer une réclamation utilisez ce lien') }}<br>
<a href="{{ route('product-request') }}" class="btn btn-red btn-arronded-20 text-uppercase">{{ __('Envoyer une réclamation') }}</a></p>
<br>

View file

@ -234,19 +234,22 @@ Route::prefix('/le-club-des-gaulois')
});
Route::prefix('/mon-compte')
->name('account.')
->middleware('auth:customer')
->group(function () {
Route::get('/mes-informations', 'ClubController@infos')->name('infos');
Route::post('/mes-informations', 'ClubController@updateInfos')->name('update-infos');
Route::post('/mes-informations/change-password', 'CustomerController@changePasswordWhenAuthenticated')->name('change-password');
Route::get('/notifications', 'ClubController@notifications')->name('notifications');
Route::get('/messages', function () {
die('Mes messages');
})->name('messages');
Route::get('/recettes-favorites', 'ClubController@favoritesRecipes')->name('favs-recipes');
Route::post('/recettes-favorites/{recipe}/set-status/{status}', 'CustomerController@setFavoriteRecipe')
->name('set-favs-recipes');
Route::get('/liste-de-courses', 'ClubController@cart')->name('cart');
Route::post('/liste-de-courses/{product}/{status}', 'CustomerController@setItemInCart')->name('set-cart');
});
->name('account.')
->middleware('auth:customer')
->group(function () {
Route::redirect('/', '/mon-compte/mes-informations');
Route::get('/mes-informations', 'ClubController@infos')->name('infos');
Route::post('/mes-informations', 'ClubController@updateInfos')->name('update-infos');
Route::post('/mes-informations/change-password', 'CustomerController@changePasswordWhenAuthenticated')
->name('change-password');
Route::get('/notifications', 'ClubController@notifications')->name('notifications');
Route::get('/messages', 'ClubController@messages')->name('messages');
Route::post('/messages/send', 'ClubController@sendMessage')->name('sendMessage');
Route::post('/messages/delete', 'ClubController@deleteMessage')->name('deleteMessage');
Route::get('/messages/report', 'ContactController@reportCustomer')->name('reportCustomer');
Route::get('/recettes-favorites', 'ClubController@favoritesRecipes')->name('favs-recipes');
Route::post('/recettes-favorites/{recipe}/set-status/{status}', 'CustomerController@setFavoriteRecipe')
->name('set-favs-recipes');
Route::get('/liste-de-courses', 'ClubController@cart')->name('cart');
Route::post('/liste-de-courses/{product}/{status}', 'CustomerController@setItemInCart')->name('set-cart');
});