notices and tg-bot module created
This commit is contained in:
parent
c2501e8a29
commit
57b1c744b9
18
app/Http/Controllers/NotificationProbeController.php
Normal file
18
app/Http/Controllers/NotificationProbeController.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Deal\Deal;
|
||||
|
||||
use App\Notifications\UniqueContact;
|
||||
|
||||
class NotificationProbeController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
auth()->user()->notify(new UniqueContact(Deal::find(4)));
|
||||
echo auth()->user()->unreadNotifications->count() . '<br>';
|
||||
die(auth()->user()->notifications);
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,11 @@
|
||||
@php($title = 'Жилые комплексы')
|
||||
@php($title = 'Жилой комплекс «' . $complex->name . '»')
|
||||
@php($backUrl = route('admin.complexes'))
|
||||
@extends('layouts.admin')
|
||||
@section('content')
|
||||
<div class="fs-5 bg-light p-0 m-0 border border-1 rounded-4 p-3">
|
||||
<h4 class="fw-bold my-3">{{ $complex->name }}</h4>
|
||||
<h4 class="fw-bold my-3">
|
||||
Редактирование
|
||||
</h4>
|
||||
<form action="{{ route('admin.complexes.update', ['complex' => $complex]) }}" method="post"
|
||||
enctype="multipart/form-data">
|
||||
@csrf
|
||||
@ -28,6 +31,8 @@
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary">Сохранить</button>
|
||||
<a class="btn btn-secondary" href="{{ route('admin.complexes') }}">Отмена</a>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
14
app/Modules/Bot/Config/config.php
Normal file
14
app/Modules/Bot/Config/config.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'telegram_bot_token' => '8108664710:AAG4sNtP02P0a6ElSHpCypsYV77EZCADwSo',
|
||||
'telegram_bot_identifier' => 'testnaviomiro38_bot',
|
||||
'telegram_bot_id' => 1,
|
||||
'telegram_type' => 'Telegram',
|
||||
|
||||
'vk_bot_id' => 2,
|
||||
'vk_type' => 'Vk',
|
||||
'vk_group_token' => 'vk1.a.s1l2J2Nri9FukE8m-eIAjq1fgBMXO_O5WR6T-cCoDjetrY9XrVggY2JyhGDv5pcTeJQuX16OxUrcCaTLagjIyp1w1A6CXKstsCPcnIxDm0GATK15360lhQ5SFjT0ciYh809wf22cQbFssHkkQj6shGzhVvJC7rdpjXNmdMyPs2geiaxktWjEVM7-2oIUrcOrs-zeGxKeucJ7_ofstL4g0A',
|
||||
'vk_group_id' => 227931308,
|
||||
'vk_group_confirmation' => '1bb6fd31'
|
||||
];
|
||||
@ -0,0 +1,38 @@
|
||||
<?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('messenger_bots', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('type');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
// Добавляем запись с type "Telegram"
|
||||
DB::table('messenger_bots')->insertOrIgnore([
|
||||
'type' => 'Telegram',
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('messenger_bots');
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,29 @@
|
||||
<?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
|
||||
{
|
||||
// Добавляем запись с type "Vk"
|
||||
DB::table('messenger_bots')->insertOrIgnore([
|
||||
'type' => 'Vk',
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
DB::table('messenger_bots')->where('type', 'Vk')->delete();
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,36 @@
|
||||
<?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('user_bots', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('bot_id')->constrained(
|
||||
table: 'messenger_bots',
|
||||
indexName: 'messenger_bots_bot_id_foreign_key'
|
||||
)->onDelete('cascade');
|
||||
$table->foreignId('user_id')->constrained(
|
||||
table: 'users',
|
||||
indexName: 'users_user_id_foreign_key'
|
||||
)->onDelete('cascade');
|
||||
$table->string('user_bot_id');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('user_bots');
|
||||
}
|
||||
};
|
||||
28
app/Modules/Bot/Http/Controllers/BotNotificationSender.php
Normal file
28
app/Modules/Bot/Http/Controllers/BotNotificationSender.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Bot\Http\Controllers;
|
||||
|
||||
use App\Modules\Bot\Models\UserBot;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class BotNotificationSender {
|
||||
|
||||
public static function routeMessage(int $userId, string $message): void
|
||||
{
|
||||
$userBots = UserBot::where('user_id', $userId)->with('bot')->get();
|
||||
|
||||
foreach ($userBots as $userBot) {
|
||||
switch ($userBot->bot->type) {
|
||||
case config('bot.telegram_type'):
|
||||
TelegramBot::sendMessage($userBot->user_bot_id, $message);
|
||||
break;
|
||||
case config('bot.vk_type'):
|
||||
VkBot::sendMessage($userBot->user_bot_id, $message);
|
||||
break;
|
||||
default:
|
||||
Log::warning("Unknown bot type: {$userBot->bot->type}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
161
app/Modules/Bot/Http/Controllers/TelegramBot.php
Normal file
161
app/Modules/Bot/Http/Controllers/TelegramBot.php
Normal file
@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Bot\Http\Controllers;
|
||||
|
||||
use App\Modules\Bot\Http\Interfaces\MessengerBotInterface;
|
||||
use App\Models\User;
|
||||
use App\Modules\Bot\Models\UserBot;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class TelegramBot implements MessengerBotInterface
|
||||
{
|
||||
private $botIdentifier;
|
||||
private $botToken;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->botIdentifier = config('bot.telegram_bot_identifier');
|
||||
$this->botToken = config('bot.telegram_bot_token');
|
||||
}
|
||||
|
||||
public function handleWebhook(Request $request)
|
||||
{
|
||||
$update = $request->all();
|
||||
|
||||
if (isset($update['message'])) {
|
||||
$this->handleMessage($update['message']);
|
||||
} elseif (isset($update['my_chat_member'])) {
|
||||
$this->handleChatMemberUpdate($update['my_chat_member']);
|
||||
}
|
||||
}
|
||||
|
||||
private function handleMessage($message)
|
||||
{
|
||||
if (isset($message['text'])) {
|
||||
$text = $message['text'];
|
||||
$chatId = $message['chat']['id'];
|
||||
$command = strtolower(explode(' ', $text)[0]);
|
||||
|
||||
switch ($command) {
|
||||
case '/start':
|
||||
$this->handleStart($text, $chatId);
|
||||
break;
|
||||
case '/stop':
|
||||
$this->handleUnsubscribe($chatId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function handleChatMemberUpdate($chatMember)
|
||||
{
|
||||
$chatId = $chatMember['chat']['id'];
|
||||
$newStatus = $chatMember['new_chat_member']['status'];
|
||||
|
||||
if ($newStatus === 'kicked' || $newStatus === 'left') {
|
||||
$this->stopBot($chatId);
|
||||
}
|
||||
}
|
||||
|
||||
private function handleStart($text, $chatId)
|
||||
{
|
||||
$parts = explode(' ', $text);
|
||||
if (count($parts) > 1) {
|
||||
$encryptedUserId = $parts[1];
|
||||
try {
|
||||
$userId = base64_decode($encryptedUserId);
|
||||
|
||||
$user = User::find($userId);
|
||||
if ($user) {
|
||||
UserBot::updateOrCreate(
|
||||
['user_id' => $userId, 'bot_id' => config('bot.telegram_bot_id')],
|
||||
['user_bot_id' => $chatId]
|
||||
);
|
||||
|
||||
$this->sendMessage($chatId, "Здравствуйте, {$user->name}! Вы успешно подписались на уведомления.");
|
||||
} else {
|
||||
$this->sendMessage($chatId, "Извините, не удалось найти вашу учетную запись.");
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Error decrypting user ID', ['error' => $e->getMessage()]);
|
||||
$this->sendMessage($chatId, "Произошла ошибка при обработке вашего запроса.");
|
||||
}
|
||||
} else {
|
||||
$this->sendMessage($chatId, "Добро пожаловать! Для подписки на уведомления, пожалуйста, используйте ссылку с нашего сайта.");
|
||||
}
|
||||
}
|
||||
|
||||
private function stopBot($chatId)
|
||||
{
|
||||
try {
|
||||
$userBot = UserBot::where('user_bot_id', $chatId)
|
||||
->where('bot_id', config('bot.telegram_bot_id'))
|
||||
->first();
|
||||
|
||||
if ($userBot) {
|
||||
$userBot->delete();
|
||||
Log::info('User unsubscribed', ['chatId' => $chatId]);
|
||||
} else {
|
||||
Log::info('Unsubscribe attempt for non-subscribed user', ['chatId' => $chatId]);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Error during unsubscribe process', ['error' => $e->getMessage(), 'chatId' => $chatId]);
|
||||
}
|
||||
}
|
||||
|
||||
private function handleUnsubscribe($chatId)
|
||||
{
|
||||
try {
|
||||
$userBot = UserBot::where('user_bot_id', $chatId)
|
||||
->where('bot_id', config('bot.telegram_bot_id'))
|
||||
->first();
|
||||
|
||||
if ($userBot) {
|
||||
$userBot->delete();
|
||||
$this->sendMessage($chatId, "Вы успешно отписались от уведомлений. Если захотите подписаться снова, воспользуйтесь ссылкой на нашем сайте.");
|
||||
Log::info('User unsubscribed', ['chatId' => $chatId]);
|
||||
} else {
|
||||
$this->sendMessage($chatId, "Вы не были подписаны на уведомления.");
|
||||
Log::info('Unsubscribe attempt for non-subscribed user', ['chatId' => $chatId]);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Error during unsubscribe process', ['error' => $e->getMessage(), 'chatId' => $chatId]);
|
||||
$this->sendMessage($chatId, "Произошла ошибка при обработке вашего запроса. Пожалуйста, попробуйте позже.");
|
||||
}
|
||||
}
|
||||
|
||||
public function subscribe() :mixed
|
||||
{
|
||||
$userId = Auth::id();
|
||||
$encryptedUserId = base64_encode($userId);
|
||||
|
||||
$telegramUrl = "https://t.me/$this->botIdentifier?start=$encryptedUserId";
|
||||
|
||||
return redirect($telegramUrl);
|
||||
}
|
||||
|
||||
|
||||
public static function sendMessage(string $userBotId, string $message): void
|
||||
{
|
||||
$botToken = config('bot.telegram_bot_token');
|
||||
Http::withoutVerifying()
|
||||
->post("https://api.telegram.org/bot{$botToken}/sendMessage", [
|
||||
'chat_id' => $userBotId,
|
||||
'text' => $message,
|
||||
'parse_mode' => 'HTML'
|
||||
]);
|
||||
}
|
||||
|
||||
public function setHook()
|
||||
{
|
||||
$response = Http::withoutVerifying()
|
||||
->post("https://api.telegram.org/bot{$this->botToken}/setWebhook", [
|
||||
'url' => 'https://naviom.iro38.ru/api/telegramWebhook',
|
||||
'allowed_updates' => ['message', 'my_chat_member']
|
||||
])->json();
|
||||
dd($response);
|
||||
}
|
||||
}
|
||||
75
app/Modules/Bot/Http/Controllers/VkBot.php
Normal file
75
app/Modules/Bot/Http/Controllers/VkBot.php
Normal file
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Bot\Http\Controllers;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Modules\Bot\Http\Interfaces\MessengerBotInterface;
|
||||
use App\Modules\Bot\Models\UserBot;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class VkBot implements MessengerBotInterface
|
||||
{
|
||||
private int $botId;
|
||||
private int $groupId;
|
||||
private string $groupConfirmation;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->botId = config('bot.vk_bot_id');
|
||||
$this->groupId = config('bot.vk_group_id');
|
||||
$this->groupConfirmation = config('bot.vk_group_confirmation');
|
||||
}
|
||||
|
||||
public static function sendMessage(string $userBotId, string $message): void
|
||||
{
|
||||
Log::info('Попытка отправить сообщение');
|
||||
$params['access_token'] = config('bot.vk_group_token');
|
||||
$params['v'] = '5.199';
|
||||
$params['random_id'] = random_int(1, PHP_INT_MAX);
|
||||
$params['user_id'] = $userBotId;
|
||||
$params['message'] = $message;
|
||||
|
||||
$response = Http::withoutVerifying()->withQueryParameters($params)->post("https://api.vk.com/method/messages.send");
|
||||
}
|
||||
|
||||
public function allowMessages(Request $request)
|
||||
{
|
||||
if ($request->vkUserId and $request->naviomUserId and User::find($request->naviomUserId)) {
|
||||
UserBot::updateOrCreate(
|
||||
['user_id' => $request->naviomUserId, 'bot_id' => $this->botId],
|
||||
['user_bot_id' => $request->vkUserId]
|
||||
);
|
||||
$user = User::find($request->naviomUserId);
|
||||
$this->sendMessage($request->vkUserId, "Здравствуйте, {$user->name}! Вы успешно подписались на уведомления.");
|
||||
}
|
||||
return response()->json(['success' => true]);
|
||||
}
|
||||
|
||||
public function handleVkCallback(Request $request)
|
||||
{
|
||||
switch ($request->type) {
|
||||
case 'confirmation':
|
||||
return $this->handleConfirmation($request->group_id);
|
||||
case 'message_deny':
|
||||
return $this->handleDenyMessage($request->object['user_id']);
|
||||
}
|
||||
}
|
||||
|
||||
private function handleConfirmation(int $groupId): string
|
||||
{
|
||||
if ($groupId == $this->groupId) {
|
||||
return $this->groupConfirmation;
|
||||
}
|
||||
}
|
||||
|
||||
private function handleDenyMessage(int $vkUserId): string
|
||||
{
|
||||
$subscription = UserBot::where('user_bot_id', $vkUserId)->where('bot_id', $this->botId)->first();
|
||||
if ($subscription) {
|
||||
$subscription->delete();
|
||||
}
|
||||
return 'ok';
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
namespace App\Modules\Bot\Http\Interfaces;
|
||||
|
||||
interface MessengerBotInterface {
|
||||
|
||||
public static function sendMessage(string $userBotId, string $message): void;
|
||||
|
||||
}
|
||||
|
||||
13
app/Modules/Bot/Models/Bot.php
Normal file
13
app/Modules/Bot/Models/Bot.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Modules\Bot\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Bot extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = ['name'];
|
||||
}
|
||||
11
app/Modules/Bot/Models/MessengerBot.php
Normal file
11
app/Modules/Bot/Models/MessengerBot.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Modules\Bot\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class MessengerBot extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
}
|
||||
22
app/Modules/Bot/Models/UserBot.php
Normal file
22
app/Modules/Bot/Models/UserBot.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Modules\Bot\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class UserBot extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'bot_id',
|
||||
'user_id',
|
||||
'user_bot_id'
|
||||
];
|
||||
|
||||
public function bot()
|
||||
{
|
||||
return $this->belongsTo(MessengerBot::class);
|
||||
}
|
||||
}
|
||||
68
app/Modules/Bot/Providers/ModuleServiceProvider.php
Normal file
68
app/Modules/Bot/Providers/ModuleServiceProvider.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Bot\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Support\Facades\Blade;
|
||||
use Livewire\Livewire;
|
||||
|
||||
class ModuleServiceProvider extends ServiceProvider
|
||||
{
|
||||
protected String $moduleName = 'Bot';
|
||||
|
||||
public function register()
|
||||
{
|
||||
$this->app->register(RouteServiceProvider::class);
|
||||
}
|
||||
|
||||
public function boot()
|
||||
{
|
||||
$this->registerViews();
|
||||
$this->registerLivewireViews();
|
||||
$this->registerMigrations();
|
||||
$this->registerConfig();
|
||||
$this->registerComponent();
|
||||
$this->registerLivewire();
|
||||
}
|
||||
|
||||
protected function registerViews()
|
||||
{
|
||||
$moduleViewsPath = __DIR__.'/../Views';
|
||||
$this->loadViewsFrom(
|
||||
$moduleViewsPath, strtolower($this->moduleName)
|
||||
);
|
||||
}
|
||||
|
||||
protected function registerLivewireViews()
|
||||
{
|
||||
$moduleViewsPath = __DIR__.'/../Views/livewire';
|
||||
$this->loadViewsFrom(
|
||||
$moduleViewsPath, strtolower($this->moduleName)
|
||||
);
|
||||
}
|
||||
|
||||
protected function registerMigrations()
|
||||
{
|
||||
$this->loadMigrationsFrom(
|
||||
app_path('Modules/'.$this->moduleName.'/Database/Migrations')
|
||||
);
|
||||
}
|
||||
|
||||
protected function registerConfig()
|
||||
{
|
||||
$path = app_path('Modules/'.$this->moduleName.'/Config/config.php');
|
||||
$this->mergeConfigFrom(
|
||||
$path, strtolower($this->moduleName)
|
||||
);
|
||||
}
|
||||
|
||||
protected function registerLivewire()
|
||||
{
|
||||
//Livewire::component('<name>', \Modules\<NAME>\Http\Livewire\<NAME>::class);
|
||||
}
|
||||
|
||||
protected function registerComponent()
|
||||
{
|
||||
//Blade::component('<name>', \Modules\<NAME>\Http\Components\<NAME>::class);
|
||||
}
|
||||
}
|
||||
24
app/Modules/Bot/Providers/RouteServiceProvider.php
Normal file
24
app/Modules/Bot/Providers/RouteServiceProvider.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Bot\Providers;
|
||||
|
||||
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
class RouteServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
||||
public function map()
|
||||
{
|
||||
$this->registerWebRoutes();
|
||||
}
|
||||
|
||||
protected function registerWebRoutes()
|
||||
{
|
||||
//Add Web Routes with web Guard
|
||||
Route::middleware('web')
|
||||
//Set Default Controllers Namespace
|
||||
->namespace('Modules\\Bot\\Http\\Controllers')
|
||||
->group(app_path('Modules/Bot/Routes/web.php'));
|
||||
}
|
||||
}
|
||||
20
app/Modules/Bot/Routes/web.php
Normal file
20
app/Modules/Bot/Routes/web.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Modules\Bot\Http\Controllers\TelegramBot;
|
||||
use Modules\Bot\Http\Controllers\VkBot;
|
||||
|
||||
Route::middleware(['auth'])->group(function() {
|
||||
|
||||
Route::get('/telegram/subscribe',[TelegramBot::class, 'subscribe'])->name('telegram.subscribe');
|
||||
Route::get('/telegramHook', [TelegramBot::class, 'setHook'])->name('setHook');
|
||||
|
||||
Route::post('/vk/allowMessages',[VkBot::class, 'allowMessages'])->name('vk.allowMessages');
|
||||
|
||||
|
||||
Route::middleware(['hasAccess'])->group(function() {
|
||||
/** Routes that need to be protected - Маршруты которые нужно защитить */
|
||||
});
|
||||
});
|
||||
|
||||
4
app/Modules/Bot/Views/index.blade.php
Normal file
4
app/Modules/Bot/Views/index.blade.php
Normal file
@ -0,0 +1,4 @@
|
||||
@extends('layouts.app')
|
||||
@section('content')
|
||||
<h1> Example views </h1>
|
||||
@endsection
|
||||
5
app/Modules/Notice/Config/config.php
Normal file
5
app/Modules/Notice/Config/config.php
Normal file
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
];
|
||||
5
app/Modules/Notice/Config/notices.php
Normal file
5
app/Modules/Notice/Config/notices.php
Normal file
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'new Recomendation' => 'NewRecomendationNotice',
|
||||
];
|
||||
@ -0,0 +1,40 @@
|
||||
<?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('notifications', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('user_id')->constrained(
|
||||
table: 'users', indexName: 'notifications_user_id_foreign_key'
|
||||
)->onDelete('cascade');
|
||||
$table->string('action');
|
||||
$table->string('object_name');
|
||||
$table->unsignedInteger('object_id');
|
||||
$table->date('read_at')->nullable();
|
||||
$table->date('sended_to_email_at')->nullable();
|
||||
$table->date('disabled_at')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::table('notifications', function (Blueprint $table) {
|
||||
$table->unique(['user_id', 'action', 'object_name', 'object_id']);
|
||||
});*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
//Schema::dropIfExists('notifications');
|
||||
}
|
||||
};
|
||||
25
app/Modules/Notice/Http/Controllers/NoticeController.php
Normal file
25
app/Modules/Notice/Http/Controllers/NoticeController.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Notice\Http\Controllers;
|
||||
|
||||
use Modules\Notice\Models\Notice;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use Modules\Notice\Models\UnreadMessagesMailer;
|
||||
|
||||
class NoticeController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
return view('notice::index');
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
$mailer = new UnreadMessagesMailer();
|
||||
$mailer->run();
|
||||
}
|
||||
}
|
||||
23
app/Modules/Notice/Http/Livewire/UserNotices.php
Normal file
23
app/Modules/Notice/Http/Livewire/UserNotices.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Notice\Http\Livewire;
|
||||
|
||||
use Livewire\Component;
|
||||
use Illuminate\Notifications\DatabaseNotification;
|
||||
|
||||
class UserNotices extends Component
|
||||
{
|
||||
public function read(DatabaseNotification $notice)
|
||||
{
|
||||
$notice->markAsRead();
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
$currentDate = date("Y-m-d");
|
||||
$startDate = date("Y-m-d", strtotime($currentDate . " -2 months"));
|
||||
return view('notice::user-notifications', [
|
||||
'notifications' => auth()->user()->notifications
|
||||
]);
|
||||
}
|
||||
}
|
||||
23
app/Modules/Notice/Http/Livewire/UserNoticesButton.php
Normal file
23
app/Modules/Notice/Http/Livewire/UserNoticesButton.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Notice\Http\Livewire;
|
||||
|
||||
use Livewire\Component;
|
||||
|
||||
use Modules\Notice\Models\Notice;
|
||||
use Modules\Chat\Models\ChatMessageRead;
|
||||
|
||||
class UserNoticesButton extends Component
|
||||
{
|
||||
public function render()
|
||||
{
|
||||
$currentDate = date("Y-m-d");
|
||||
$startDate = date("Y-m-d", strtotime($currentDate . " -2 months"));
|
||||
|
||||
return view('notice::user-notices-button', [
|
||||
'unreadedCount' =>
|
||||
auth()->user()->unreadNotifications
|
||||
->count()
|
||||
]);
|
||||
}
|
||||
}
|
||||
22
app/Modules/Notice/Models/NewWayMeetingNotice.php
Normal file
22
app/Modules/Notice/Models/NewWayMeetingNotice.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Notice\Models;
|
||||
|
||||
use Modules\Notice\Models\Notice;
|
||||
|
||||
use App\Models\Meeting\WayMeeting;
|
||||
|
||||
class NewWayMeetingNotice
|
||||
{
|
||||
public static function getParameters(Notice $notice)
|
||||
{
|
||||
$wayMeeting = WayMeeting::find($notice->object_id);
|
||||
if (!$wayMeeting)
|
||||
return false;
|
||||
return [
|
||||
'id' => $wayMeeting->id,
|
||||
'name' => $wayMeeting->meeting->name,
|
||||
'action' => route('way.index', ['way' => $wayMeeting->way->id]),
|
||||
];
|
||||
}
|
||||
}
|
||||
39
app/Modules/Notice/Models/Notice.php
Normal file
39
app/Modules/Notice/Models/Notice.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Notice\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Notice extends Model
|
||||
{
|
||||
protected $table = 'notices';
|
||||
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'action',
|
||||
'object_name',
|
||||
'object_id',
|
||||
'read_at'
|
||||
];
|
||||
|
||||
public function toString()
|
||||
{
|
||||
$noticeName = "$this->action $this->object_name";
|
||||
$noticeClass = __DIR__ . '/' . config('notice.types.' . $noticeName);
|
||||
if (file_exists($noticeClass . '.php')) {
|
||||
$noticeClass = 'Modules\\Notice\\Models\\' . config('notice.types.' . $noticeName);
|
||||
if ($parameters = $noticeClass::getParameters($this)) {
|
||||
return __("notification.$this->action $this->object_name", $parameters);
|
||||
};
|
||||
};
|
||||
return FALSE;
|
||||
//
|
||||
}
|
||||
|
||||
public function created_at()
|
||||
{
|
||||
return date_format(date_create($this->created_at), env('DATETIME_FORMAT'));
|
||||
}
|
||||
|
||||
}
|
||||
72
app/Modules/Notice/Models/NoticesMailer.php
Normal file
72
app/Modules/Notice/Models/NoticesMailer.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Notice\Models;
|
||||
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
|
||||
use App\Notifications\NoticesMailerNotification;
|
||||
use Modules\Notice\Models\Notice;
|
||||
use Modules\Bot\Http\Controllers\BotNotificationSender;
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
|
||||
class NoticesMailer
|
||||
{
|
||||
use Notifiable;
|
||||
|
||||
private $user;
|
||||
private $notices;
|
||||
private $messages;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$date = Carbon::now();
|
||||
//$date->subDays(1);
|
||||
$date = $date->toDateTimeString();
|
||||
$latest_notice = Notice::where('created_at', '<=', $date)
|
||||
->whereNull('sended_to_email_at')
|
||||
->whereNull('read_at')
|
||||
->orderBy('created_at', 'desc');
|
||||
if ($latest_notice = $latest_notice->first()) {
|
||||
$this->user = User::findOrFail($latest_notice->user_id);
|
||||
$this->notices = Notice::where('user_id', $this->user->id)
|
||||
->whereNull('sended_to_email_at')
|
||||
->whereNull('read_at')
|
||||
->orderBy('object_name')
|
||||
->orderBy('created_at')->get();
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
if (!$this->user) {
|
||||
Log::error('Has no notices for mailing');
|
||||
return;
|
||||
};
|
||||
|
||||
if ($this->notices->count() == 0) {
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
$notification = new NoticesMailerNotification($this->notices);
|
||||
|
||||
Notification::route('mail', $this->user->email)
|
||||
->notify($notification);
|
||||
|
||||
$botMessage = $notification->buildBotMessage();
|
||||
BotNotificationSender::routeMessage($this->user->id, $botMessage);
|
||||
|
||||
foreach ($this->notices as $notice) {
|
||||
$notice->sended_to_email_at = now();
|
||||
$notice->save();
|
||||
};
|
||||
}
|
||||
}
|
||||
69
app/Modules/Notice/Models/UnreadMessagesMailer.php
Normal file
69
app/Modules/Notice/Models/UnreadMessagesMailer.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Notice\Models;
|
||||
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
|
||||
use App\Notifications\NewChatMessageNoticesMailerNotification;
|
||||
use Modules\Notice\Models\Notice;
|
||||
use Modules\Chat\Models\Chat;
|
||||
use Modules\Chat\Models\ChatMessage;
|
||||
use Modules\Chat\Models\ChatMessageRead;
|
||||
use App\Models\User;
|
||||
use Modules\Bot\Http\Controllers\BotNotificationSender;
|
||||
|
||||
class UnreadMessagesMailer
|
||||
{
|
||||
use Notifiable;
|
||||
|
||||
private $user;
|
||||
private $notices;
|
||||
private $senders;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$newChatNotice = Notice::whereNull('sended_to_email_at')
|
||||
->whereNull('read_at')
|
||||
->where('object_name', 'Chat')
|
||||
->orderBy('created_at');
|
||||
if ($newChatNotice = $newChatNotice->first()) {
|
||||
$this->user = User::findOrFail($newChatNotice->user_id);
|
||||
$this->notices = Notice::where('user_id', $this->user->id)
|
||||
->whereNull('sended_to_email_at')
|
||||
->whereNull('read_at')
|
||||
->where('object_name', 'Chat')
|
||||
->orderBy('created_at')->get();
|
||||
//$this->senders = ChatMessageRead::where('receiver_id', $this->user->id)->where('message.sender_id');
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
public function run()
|
||||
{
|
||||
if (!$this->user) {
|
||||
//Log::error('Has no notices for mailing');
|
||||
return;
|
||||
};
|
||||
|
||||
if ($this->notices->count() == 0) {
|
||||
return false;
|
||||
};
|
||||
|
||||
$notification = new NewChatMessageNoticesMailerNotification();
|
||||
|
||||
Notification::route('mail', $this->user->email)
|
||||
->notify($notification);
|
||||
|
||||
$botMessage = $notification->buildBotMessage();
|
||||
BotNotificationSender::routeMessage($this->user->id, $botMessage);
|
||||
|
||||
foreach ($this->notices as $notice) {
|
||||
$notice->sended_to_email_at = now();
|
||||
$notice->save();
|
||||
};
|
||||
}
|
||||
}
|
||||
78
app/Modules/Notice/Providers/ModuleServiceProvider.php
Normal file
78
app/Modules/Notice/Providers/ModuleServiceProvider.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Notice\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Support\Facades\Blade;
|
||||
use Livewire\Livewire;
|
||||
|
||||
class ModuleServiceProvider extends ServiceProvider
|
||||
{
|
||||
protected string $moduleName = 'Notice';
|
||||
|
||||
public function register()
|
||||
{
|
||||
$this->app->register(RouteServiceProvider::class);
|
||||
}
|
||||
|
||||
public function boot()
|
||||
{
|
||||
$this->registerViews();
|
||||
$this->registerLivewireViews();
|
||||
$this->registerMigrations();
|
||||
$this->registerConfig();
|
||||
$this->registerComponent();
|
||||
$this->registerLivewire();
|
||||
}
|
||||
|
||||
protected function registerViews()
|
||||
{
|
||||
$moduleViewsPath = __DIR__ . '/../Views';
|
||||
$this->loadViewsFrom(
|
||||
$moduleViewsPath,
|
||||
strtolower($this->moduleName)
|
||||
);
|
||||
}
|
||||
|
||||
protected function registerLivewireViews()
|
||||
{
|
||||
$moduleViewsPath = __DIR__ . '/../Views/livewire';
|
||||
$this->loadViewsFrom(
|
||||
$moduleViewsPath,
|
||||
strtolower($this->moduleName)
|
||||
);
|
||||
}
|
||||
|
||||
protected function registerMigrations()
|
||||
{
|
||||
$this->loadMigrationsFrom(
|
||||
app_path('Modules/' . $this->moduleName . '/Database/Migrations')
|
||||
);
|
||||
}
|
||||
|
||||
protected function registerConfig()
|
||||
{
|
||||
$path = app_path('Modules/' . $this->moduleName . '/Config/config.php');
|
||||
$this->mergeConfigFrom(
|
||||
$path,
|
||||
strtolower($this->moduleName)
|
||||
);
|
||||
|
||||
$path = app_path('Modules/' . $this->moduleName . '/Config/notices.php');
|
||||
$this->mergeConfigFrom(
|
||||
$path,
|
||||
'notice.types'
|
||||
);
|
||||
}
|
||||
|
||||
protected function registerLivewire()
|
||||
{
|
||||
Livewire::component('notices.user-notices', \Modules\Notice\Http\Livewire\UserNotices::class);
|
||||
Livewire::component('notices.user-notices-button', \Modules\Notice\Http\Livewire\UserNoticesButton::class);
|
||||
}
|
||||
|
||||
protected function registerComponent()
|
||||
{
|
||||
//Blade::component('<name>', \Modules\<NAME>\Http\Components\<NAME>::class);
|
||||
}
|
||||
}
|
||||
24
app/Modules/Notice/Providers/RouteServiceProvider.php
Normal file
24
app/Modules/Notice/Providers/RouteServiceProvider.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Notice\Providers;
|
||||
|
||||
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
class RouteServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
||||
public function map()
|
||||
{
|
||||
$this->registerWebRoutes();
|
||||
}
|
||||
|
||||
protected function registerWebRoutes()
|
||||
{
|
||||
//Add Web Routes with web Guard
|
||||
Route::middleware('web')
|
||||
//Set Default Controllers Namespace
|
||||
->namespace('Modules\\Notice\\Http\\Controllers')
|
||||
->group(app_path('Modules/Notice/Routes/web.php'));
|
||||
}
|
||||
}
|
||||
14
app/Modules/Notice/Routes/web.php
Normal file
14
app/Modules/Notice/Routes/web.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Modules\Notice\Http\Controllers\NoticeController;
|
||||
|
||||
Route::middleware(['auth'])->group(function() {
|
||||
|
||||
Route::get('/notice', [NoticeController::class, 'index']);
|
||||
Route::get('/notice/run', [NoticeController::class, 'run']);
|
||||
|
||||
Route::middleware(['hasAccess'])->group(function() {
|
||||
/** Routes that need to be protected - Маршруты которые нужно защитить */
|
||||
});
|
||||
});
|
||||
16
app/Modules/Notice/Views/index.blade.php
Normal file
16
app/Modules/Notice/Views/index.blade.php
Normal file
@ -0,0 +1,16 @@
|
||||
<div>
|
||||
<div class="offcanvas offcanvas-end rounded-start offcanvas-animated-xl" tabindex="-1" id="notificationsOffcanvas"
|
||||
aria-labelledby="offcanvasExampleLabel">
|
||||
<div class="offcanvas-header">
|
||||
<h5 class="offcanvas-title" id="offcanvasExampleLabel">Уведомления</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body">
|
||||
<div class="list-group list-group-flush scrollarea">
|
||||
@livewireStyles
|
||||
<livewire:notices.user-notices />
|
||||
@livewireScripts
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
29
app/Modules/Notice/Views/user-notices-button.blade.php
Normal file
29
app/Modules/Notice/Views/user-notices-button.blade.php
Normal file
@ -0,0 +1,29 @@
|
||||
<div wire:poll.10000ms>
|
||||
<div class="d-block">
|
||||
<a type="button" class="rounded-circle p-2 lh-1 link-secondary bg-primary-soft-hover text-decoration-none p-1"
|
||||
data-bs-toggle="offcanvas" href="#notificationsOffcanvas">
|
||||
<div class="position-relative">
|
||||
<i class="bi bi-bell fs-4"></i>
|
||||
@if ($unreadedCount > 0)
|
||||
<span class="notices-badge animation-blink"></span>
|
||||
@endif
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
{{-- <div class="d-lg-none d-block">
|
||||
<a class="nav-link text-center" data-bs-toggle="offcanvas" href="#notificationsOffcanvas">
|
||||
<div class="position-relative">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1.5em" height="1.5em" fill="currentColor" class="bi bi-bell" viewBox="0 0 16 16">
|
||||
<path
|
||||
d="M8 16a2 2 0 0 0 2-2H6a2 2 0 0 0 2 2M8 1.918l-.797.161A4 4 0 0 0 4 6c0 .628-.134 2.197-.459 3.742-.16.767-.376 1.566-.663 2.258h10.244c-.287-.692-.502-1.49-.663-2.258C12.134 8.197 12 6.628 12 6a4 4 0 0 0-3.203-3.92zM14.22 12c.223.447.481.801.78 1H1c.299-.199.557-.553.78-1C2.68 10.2 3 6.88 3 6c0-2.42 1.72-4.44 4.005-4.901a1 1 0 1 1 1.99 0A5 5 0 0 1 13 6c0 .88.32 4.2 1.22 6"/>
|
||||
</svg>
|
||||
<div class="position-absolute start-45 bottom-100">
|
||||
@if ($unreadedCount > 0 || $unreadedMessages > 0)
|
||||
<span class="notices-badge animation-blink"></span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<span class="small d-block text-small-mobile">Уведомления</span>
|
||||
</a>
|
||||
</div> --}}
|
||||
</div>
|
||||
38
app/Modules/Notice/Views/user-notifications.blade.php
Normal file
38
app/Modules/Notice/Views/user-notifications.blade.php
Normal file
@ -0,0 +1,38 @@
|
||||
<div wire:poll.10000ms>
|
||||
@if ($notifications->count() == 0)
|
||||
<div class="d-flex justify-content-center align-items-center">
|
||||
<div class="d-grid gap-1 p-3">
|
||||
<i class="bi bi-inbox display-5 text-center"></i>
|
||||
<span class="fs-6 fw-semibold">{{ __('notification.has no notifications') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<ul class="list-group gap-1">
|
||||
@foreach ($notifications as $notification)
|
||||
@if (array_key_exists('text', $notification->data))
|
||||
<li href="#"
|
||||
class="list-group-item list-group-item-action rounded {{ !$notification->read_at ? 'list-group-item-warning' : 'list-group-item-light' }}"
|
||||
aria-current="true" wire:click="read({{ $notification }})">
|
||||
<div class="small">
|
||||
<p class="m-0">
|
||||
{{ $notification->data['text'] }}
|
||||
</p>
|
||||
<p class="m-0 d-flex flex-wrap justify-content-end align-items-center">
|
||||
<span class="badge fw-light text-secondary">{{ $notification->created_at }}</span>
|
||||
@if ($notification->read_at)
|
||||
<span class=" fs-5 text-success">
|
||||
<i class="bi bi-check-all"></i>
|
||||
</span>
|
||||
@else
|
||||
<span class=" fs-5 text-secondary">
|
||||
<i class="bi bi-check"></i>
|
||||
</span>
|
||||
@endif
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
@endif
|
||||
@endforeach
|
||||
</ul>
|
||||
@endif
|
||||
</div>
|
||||
62
app/Notifications/UniqueContact.php
Normal file
62
app/Notifications/UniqueContact.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
use App\Models\Deal\Deal;
|
||||
use App\Models\Deal\DealStatus;
|
||||
|
||||
class UniqueContact extends Notification
|
||||
{
|
||||
use Queueable;
|
||||
private $deal;
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*/
|
||||
public function __construct(Deal $deal)
|
||||
{
|
||||
if ($deal->status != DealStatus::UNIQUE)
|
||||
{
|
||||
//throw new \Exception('Notification sending: deal is not unique');
|
||||
}
|
||||
$this->deal = $deal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public function via(object $notifiable): array
|
||||
{
|
||||
return ['database'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*/
|
||||
public function toMail(object $notifiable): MailMessage
|
||||
{
|
||||
return (new MailMessage)
|
||||
->line('The introduction to the notification.')
|
||||
->action('Notification Action', url('/'))
|
||||
->line('Thank you for using our application!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(object $notifiable): array
|
||||
{
|
||||
return [
|
||||
'deal' => $this->deal->id,
|
||||
'text' => __('notifications.' . get_class($this), ['contact' => $this->deal->user->name])
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
<?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('notifications', function (Blueprint $table) {
|
||||
$table->uuid('id')->primary();
|
||||
$table->string('type');
|
||||
$table->morphs('notifiable');
|
||||
$table->text('data');
|
||||
$table->timestamp('read_at')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('notifications');
|
||||
}
|
||||
};
|
||||
18
lang/ru/notifications.php
Normal file
18
lang/ru/notifications.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Password Reset Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are the default lines which match reasons
|
||||
| that are given by the password broker for a password update attempt
|
||||
| has failed, such as for an invalid token or invalid new password.
|
||||
|
|
||||
*/
|
||||
|
||||
'App\Notifications\UniqueContact' => 'Контакт :contact был проверен, уникальность подтверждена',
|
||||
|
||||
];
|
||||
@ -66,4 +66,45 @@ .active>.page-link {
|
||||
.page-item:not(.active)>.page-link:hover {
|
||||
color: #e6662a !important;
|
||||
border-color: #ccc
|
||||
}
|
||||
|
||||
|
||||
/*NOTOFICATIONS*/
|
||||
.notices-badge {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 15px;
|
||||
transform: translate(50%, -50%);
|
||||
background-color: #d63939 !important
|
||||
}
|
||||
|
||||
.notices-badge:empty {
|
||||
display: inline-block;
|
||||
width: .5rem;
|
||||
height: .5rem;
|
||||
min-width: 0;
|
||||
min-height: auto;
|
||||
padding: 0;
|
||||
border-radius: 100rem;
|
||||
vertical-align: baseline
|
||||
}
|
||||
|
||||
.animation-blink {
|
||||
-webkit-animation: blink 2s infinite;
|
||||
animation: blink 2s infinite
|
||||
}
|
||||
|
||||
@keyframes blink {
|
||||
0% {
|
||||
opacity: 0
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 0
|
||||
}
|
||||
}
|
||||
@ -27,11 +27,21 @@
|
||||
<img src={{ url('/images/logo.png') }} alt="Logo" width="70">
|
||||
</a>
|
||||
</div>
|
||||
<div class="col px-0 px-md-4 text-start text-truncate fw-light fs-4 text-secondary text-uppercase"
|
||||
id="pageTitle">
|
||||
@isset($title)
|
||||
{{ $title }}
|
||||
@endisset
|
||||
<div class="col px-0 px-md-4 text-start" id="pageTitle">
|
||||
<a class="icon-link icon-link-hover text-truncate fw-lighter fs-4 text-secondary text-uppercase text-decoration-none align-middle"
|
||||
href="@isset($backUrl) {{ $backUrl }} @endisset"
|
||||
style="--bs-icon-link-transform: translate3d(-.125rem, 0, 0);">
|
||||
@isset($backUrl)
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
|
||||
class="bi bi-caret-left" viewBox="0 0 16 16">
|
||||
<path
|
||||
d="M10 12.796V3.204L4.519 8zm-.659.753-5.48-4.796a1 1 0 0 1 0-1.506l5.48-4.796A1 1 0 0 1 11 3.204v9.592a1 1 0 0 1-1.659.753" />
|
||||
</svg>
|
||||
@endisset
|
||||
@isset($title)
|
||||
{{ $title }}
|
||||
@endisset
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-auto col-sm-2">
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
<link href="https://fonts.bunny.net/css?family=Nunito" rel="stylesheet">
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
||||
@vite(['resources/sass/app.scss', 'resources/js/app.js', 'resources/css/app.css', 'resources/css/docs.css'])
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@ -47,7 +47,10 @@
|
||||
</ul>
|
||||
|
||||
<!-- Right Side Of Navbar -->
|
||||
<ul class="navbar-nav ms-auto">
|
||||
<ul class="navbar-nav align-items-center ms-auto">
|
||||
<div class="nav-item ">
|
||||
@livewire('notices.user-notices-button')
|
||||
</div>
|
||||
<li class="nav-item dropdown">
|
||||
<a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button"
|
||||
data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
|
||||
@ -118,6 +121,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@include('notice::index')
|
||||
@vite(['resources/sass/app.scss', 'resources/js/app.js', 'resources/css/app.css', 'resources/css/docs.css'])
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
@ -59,4 +59,6 @@
|
||||
Route::get('profile', function ()
|
||||
{
|
||||
return view(view: 'user.profile');
|
||||
});
|
||||
});
|
||||
|
||||
Route::get('/notices', [App\Http\Controllers\NotificationProbeController::class, 'index']);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user