добавлена функция приглашений в агентство
This commit is contained in:
parent
54207dcf50
commit
197129008e
@ -10,17 +10,20 @@
|
|||||||
<div class="text-danger">{{ $message }}</div>
|
<div class="text-danger">{{ $message }}</div>
|
||||||
@enderror
|
@enderror
|
||||||
</div>
|
</div>
|
||||||
<div class="">
|
<div class="row text-dark">
|
||||||
|
<label class="form-label mb-1">Города для публикации</label>
|
||||||
|
<div class="hstack gap-2 mb-2">
|
||||||
@if($availableCities = GetAvailableCities())
|
@if($availableCities = GetAvailableCities())
|
||||||
@foreach($availableCities as $key=>$city)
|
@foreach($availableCities as $key=>$city)
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input name="cities[{{ $key }}]" class="form-check-input" type="checkbox" value="{{ $city->id }}" id="city_ {{ $city->id }}">
|
<input name="cities[{{ $key }}]" class="btn-check" type="checkbox" value="{{ $city->id }}" id="city_{{ $city->id }}">
|
||||||
<label class="form-check-label" for="city_{{ $city->id }}">
|
<label class="btn bg-light" for="city_{{ $city->id }}">
|
||||||
{{ $city->name }}
|
{{ $city->name }}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
@endforeach
|
||||||
@endif
|
@endif
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-6 mb-3">
|
<div class="col-6 mb-3">
|
||||||
|
|||||||
@ -5,8 +5,6 @@
|
|||||||
|
|
||||||
Route::middleware(['auth'])->group(function ()
|
Route::middleware(['auth'])->group(function ()
|
||||||
{
|
{
|
||||||
|
|
||||||
Route::get('/docs', [DocsController::class, 'index'])->name('docs.index');
|
Route::get('/docs', [DocsController::class, 'index'])->name('docs.index');
|
||||||
Route::get('/docs/{document}/download', [DocsController::class, 'download'])->name('docs.download');
|
Route::get('/docs/{document}/download', [DocsController::class, 'download'])->name('docs.download');
|
||||||
|
|
||||||
});
|
});
|
||||||
5
app/Modules/Invite/Config/config.php
Normal file
5
app/Modules/Invite/Config/config.php
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
];
|
||||||
@ -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('invites', function (Blueprint $table)
|
||||||
|
{
|
||||||
|
$table->id();
|
||||||
|
$table->uuid('hash');
|
||||||
|
$table->foreignId('company_id')->references('id')->on('companies')->onDelete('cascade');
|
||||||
|
$table->timestamps();
|
||||||
|
$table->softDeletes();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('invites');
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
<?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('invite_agents', function (Blueprint $table)
|
||||||
|
{
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('invite_id')->references('id')->on('invites');
|
||||||
|
$table->foreignId('agent_id')->references('id')->on('agents');
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('invite_agents');
|
||||||
|
}
|
||||||
|
};
|
||||||
125
app/Modules/Invite/Http/Controllers/InviteController.php
Normal file
125
app/Modules/Invite/Http/Controllers/InviteController.php
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Invite\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
||||||
|
use Modules\Invite\Models\InviteAgent;
|
||||||
|
use Ramsey\Uuid\Uuid;
|
||||||
|
|
||||||
|
use Modules\Invite\Models\Invite;
|
||||||
|
use Modules\User\Models\User;
|
||||||
|
use Modules\User\Models\Role;
|
||||||
|
use Modules\User\Models\UserRole;
|
||||||
|
use Modules\Main\Models\Company\Company;
|
||||||
|
use Modules\Main\Models\Company\CompanyAdmin;
|
||||||
|
use Modules\Main\Models\Agent\Agent;
|
||||||
|
use Modules\CityManager\Models\CityManager;
|
||||||
|
|
||||||
|
class InviteController extends Controller
|
||||||
|
{
|
||||||
|
public function index(Company $company = null)
|
||||||
|
{
|
||||||
|
$companies = [];
|
||||||
|
//$companiesIds = UserRole::where('user_id', auth()->user()->id)->pluck('company_id')->toArray();
|
||||||
|
if (!$company) {
|
||||||
|
if (auth()->user()->hasRole(Role::CITY_MANAGER)) {
|
||||||
|
$citiesIds = CityManager::where('user_id', auth()->user()->id)->pluck('city_id')->toArray();
|
||||||
|
foreach (Company::whereIn('city_id', $citiesIds)->get() as $company) {
|
||||||
|
$companies[] = $company;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (auth()->user()->hasRole(Role::COMPANY_ADMIN)) {
|
||||||
|
$companyAdmin = CompanyAdmin::where('user_id', auth()->user()->id)->first();
|
||||||
|
$companies[] = $companyAdmin->company;
|
||||||
|
}
|
||||||
|
if (count($companies) > 1) {
|
||||||
|
return view('invite::companies', [
|
||||||
|
'companies' => $companies
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
return to_route('company.invites', [
|
||||||
|
'company' => $companies[0]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return view('invite::index', [
|
||||||
|
'company' => $company,
|
||||||
|
'invites' => Invite::where('company_id', $company->id)->get()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
public function create(Request $request, Company $company) {
|
||||||
|
Invite::create([
|
||||||
|
'hash' => Uuid::uuid4(),
|
||||||
|
'company_id' => $company->id
|
||||||
|
]);
|
||||||
|
return back();
|
||||||
|
}
|
||||||
|
public function open(Request $request, $hash) {
|
||||||
|
if (!$invite = Invite::where('hash', $hash)->first()) {
|
||||||
|
return back();
|
||||||
|
}
|
||||||
|
return view('invite::form', [
|
||||||
|
'invite' => $invite
|
||||||
|
]);
|
||||||
|
return back();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function process(Request $request, $hash) {
|
||||||
|
if (!$invite = Invite::where('hash', $hash)->first()) {
|
||||||
|
return back();
|
||||||
|
}
|
||||||
|
$user = User::where('email', $request->email)->orWhere('phone', $request->phone)->first();
|
||||||
|
|
||||||
|
if ($user) {
|
||||||
|
if (UserRole::where('user_id', Role::AGENT)->get()) {
|
||||||
|
return back()->withInput()->withErrors('Агент с данным телефоном или электронной почтой уже зарегистрирован');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$user = User::create([
|
||||||
|
'name' => $request->name,
|
||||||
|
'email' => $request->email,
|
||||||
|
'phone' => $request->phone
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
$agent = Agent::create([
|
||||||
|
'company_id' => $invite->company_id,
|
||||||
|
'user_id' => $user->id
|
||||||
|
]);
|
||||||
|
if (!$agent && $user->wasRecentlyCreated) {
|
||||||
|
$user->delete();
|
||||||
|
return back()->withInput()->withErrors('При создании учетной записи возникла ошибка. Попробуйте сделать это немного позже');
|
||||||
|
}
|
||||||
|
$registration = InviteAgent::create([
|
||||||
|
'invite_id' => $invite->id,
|
||||||
|
'agent_id' => $agent->id
|
||||||
|
]);
|
||||||
|
if (!$registration) {
|
||||||
|
$agent->forceDelete();
|
||||||
|
return back()->withInput()->withErrors('При создании учетной записи возникла ошибка. Попробуйте сделать это немного позже');
|
||||||
|
}
|
||||||
|
$user->setForcedPassword();
|
||||||
|
return to_route('company.invite.success', [
|
||||||
|
'hash' => $invite->hash
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function success(Request $request, $hash) {
|
||||||
|
if (!$invite = Invite::where('hash', $hash)->first()) {
|
||||||
|
return back();
|
||||||
|
}
|
||||||
|
return view('invite::success', [
|
||||||
|
'invite' => $invite
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
public function delete (Invite $invite) {
|
||||||
|
$invite->delete();
|
||||||
|
return back()->withSuccess('Ссылка-приглашение была успешно удалена');
|
||||||
|
}
|
||||||
|
public function agents(Invite $invite) {
|
||||||
|
return view('invite::agents', [
|
||||||
|
'invite' => $invite
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
26
app/Modules/Invite/Models/Invite.php
Normal file
26
app/Modules/Invite/Models/Invite.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Invite\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Modules\Main\Models\Company\Company;
|
||||||
|
class Invite extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'hash',
|
||||||
|
'company_id'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function company()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Company::class, 'company_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function registrations()
|
||||||
|
{
|
||||||
|
return $this->HasMany(InviteAgent::class, 'invite_id');
|
||||||
|
}
|
||||||
|
}
|
||||||
27
app/Modules/Invite/Models/InviteAgent.php
Normal file
27
app/Modules/Invite/Models/InviteAgent.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Invite\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Modules\Main\Models\Agent\Agent;
|
||||||
|
class InviteAgent extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
protected $touches = ['invite'];
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'invite_id',
|
||||||
|
'agent_id'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function agent()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Agent::class, 'agent_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function invite()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Invite::class, 'invite_id');
|
||||||
|
}
|
||||||
|
}
|
||||||
71
app/Modules/Invite/Providers/ModuleServiceProvider.php
Normal file
71
app/Modules/Invite/Providers/ModuleServiceProvider.php
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Invite\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
use Illuminate\Support\Facades\Blade;
|
||||||
|
use Livewire\Livewire;
|
||||||
|
|
||||||
|
class ModuleServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
protected string $moduleName = 'Invite';
|
||||||
|
|
||||||
|
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('document', \Modules\Docs\Http\Components\DocumentComponent::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
24
app/Modules/Invite/Providers/RouteServiceProvider.php
Normal file
24
app/Modules/Invite/Providers/RouteServiceProvider.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Invite\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\\Invite\\Http\\Controllers')
|
||||||
|
->group(app_path('Modules/Invite/Routes/web.php'));
|
||||||
|
}
|
||||||
|
}
|
||||||
17
app/Modules/Invite/Routes/web.php
Normal file
17
app/Modules/Invite/Routes/web.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
use Modules\Invite\Http\Controllers\InviteController;
|
||||||
|
|
||||||
|
Route::middleware(['auth'])->group(function ()
|
||||||
|
{
|
||||||
|
Route::get('company/{company}/invites', [InviteController::class, 'index'])->name('company.invites');
|
||||||
|
Route::get('company/invites', [InviteController::class, 'index'])->name('company.invites.select');
|
||||||
|
|
||||||
|
Route::post('company/{company}/create', [InviteController::class, 'create'])->name('company.invites.create');
|
||||||
|
Route::get('company/invite/{hash}', [InviteController::class, 'open'])->name('company.invite.open');
|
||||||
|
Route::post('company/invite/{hash}', [InviteController::class, 'process'])->name('company.invite.process');
|
||||||
|
Route::get('company/invite/{hash}/success', [InviteController::class, 'success'])->name('company.invite.success');
|
||||||
|
Route::get('company/invite/{invite}/agents', [InviteController::class, 'agents'])->name('company.invite.agents');
|
||||||
|
Route::post('company/invite/{invite}/delete', [InviteController::class, 'delete'])->name('company.invite.delete');
|
||||||
|
});
|
||||||
40
app/Modules/Invite/Views/agents.blade.php
Normal file
40
app/Modules/Invite/Views/agents.blade.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
@php($title = 'Зарегистрированные по приглашению агенты')
|
||||||
|
@extends('layouts.app')
|
||||||
|
@section('content')
|
||||||
|
<h4>{{ $invite->company->name }}</h4>
|
||||||
|
<div class="d-none mb-3 sticky-top bg-light rounded-3">
|
||||||
|
<div class="p-2 w-100"></div>
|
||||||
|
<div class="p-2 flex-shrink-1">
|
||||||
|
<form class="d-none" method="post" action="{{ route('company.invites.create', ['company' => 1]) }}">
|
||||||
|
@csrf
|
||||||
|
<input class="btn btn-primary" type="submit" value="Создать приглашение" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h5>Зарегистрированные по приглашению агенты</h5>
|
||||||
|
<div class="row g-2 w-100">
|
||||||
|
@foreach ($invite->registrations()->orderBy('created_at', 'desc')->get() as $inviteRegistration)
|
||||||
|
<div class="d-flex flex-row w-100 gap-3 bg-light rounded-3 p-2">
|
||||||
|
<div class="col flex-fill">
|
||||||
|
{{ $inviteRegistration->agent->user?->name }}
|
||||||
|
</div>
|
||||||
|
<div class="col-2">
|
||||||
|
{{ $inviteRegistration->created_at->diffForHumans() }}
|
||||||
|
</div>
|
||||||
|
<div class="col-1 d-none">
|
||||||
|
<div class="dropdown d-none d-md-block" style="">
|
||||||
|
<button class="btn btn-light" type="button" id="dropdownMenuButton" data-bs-toggle="dropdown"
|
||||||
|
aria-haspopup="true" aria-expanded="false">
|
||||||
|
<i class="bi bi-three-dots-vertical"></i>
|
||||||
|
</button>
|
||||||
|
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton" data-popper-placement="bottom-start">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
45
app/Modules/Invite/Views/companies.blade.php
Normal file
45
app/Modules/Invite/Views/companies.blade.php
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
@php($title = 'Приглашения агентов')
|
||||||
|
@extends('layouts.app')
|
||||||
|
@section('content')
|
||||||
|
<div class="d-flex mb-3 sticky-top bg-light rounded-3">
|
||||||
|
<div class="p-2 w-100"></div>
|
||||||
|
<div class="p-2 flex-shrink-1">
|
||||||
|
<form class="" method="post" action="{{ route('company.invites.create', ['company' => 1]) }}">
|
||||||
|
@csrf
|
||||||
|
<input class="btn btn-primary" type="submit" value="Создать приглашение" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h5>Доступные агентства</h5>
|
||||||
|
<div class="row g-2 w-100">
|
||||||
|
@foreach ($companies as $company)
|
||||||
|
<a href="{{ route('company.invites', ['company' => $company]) }}"
|
||||||
|
class="p-2 bg-light rounded icon-link icon-link-hover w-100 hstack gap-2 text-decoration-none">
|
||||||
|
<span class="col-8 text-dark">{{ $company->name }}</span>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
|
||||||
|
class="bi bi-chevron-right ms-auto" viewBox="0 0 16 16">
|
||||||
|
<path fill-rule="evenodd"
|
||||||
|
d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708" />
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
const copyBtns = document.querySelectorAll('.copy-invite-btn');
|
||||||
|
Array.from(copyBtns).forEach(btn => {
|
||||||
|
btn.addEventListener('click', function (event) {
|
||||||
|
targetId = '#' + event.target.dataset.target;
|
||||||
|
navigator.clipboard.writeText(document.querySelector(targetId).value)
|
||||||
|
.then(() => {
|
||||||
|
alert('Ссылка скопирована в буфер обмена');
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error(`Ошибка копирования: ${error}`)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
18
app/Modules/Invite/Views/components/invite.blade.php
Normal file
18
app/Modules/Invite/Views/components/invite.blade.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<div class="document-card d-flex border border-1 rounded-3 overflow-hidden">
|
||||||
|
<div class="p-2 w-100 p-2 bg-light">
|
||||||
|
<h4>{{ $document->name }}</h4>
|
||||||
|
<div class="fw-semibold">
|
||||||
|
{{ $document->description }}
|
||||||
|
</div>
|
||||||
|
<div class="fw-lighter text-secondary">Загружен: {{ $document->created_at->diffForHumans() }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="download d-flex align-items-center">
|
||||||
|
<a href="{{ route('docs.download', ['document' => $document]) }}" class="m-auto text-white">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" fill="currentColor"
|
||||||
|
class="bi bi-arrow-down-circle" viewBox="0 0 16 16">
|
||||||
|
<path fill-rule="evenodd"
|
||||||
|
d="M1 8a7 7 0 1 0 14 0A7 7 0 0 0 1 8m15 0A8 8 0 1 1 0 8a8 8 0 0 1 16 0M8.5 4.5a.5.5 0 0 0-1 0v5.793L5.354 8.146a.5.5 0 1 0-.708.708l3 3a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293z" />
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
32
app/Modules/Invite/Views/form.blade.php
Normal file
32
app/Modules/Invite/Views/form.blade.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
@php($title = 'Приглашения агентов')
|
||||||
|
@extends('layouts.guest')
|
||||||
|
@section('content')
|
||||||
|
<form class="modal-content" action="{{ route('company.invite.process', ['hash' => $invite->hash]) }}" method="post">
|
||||||
|
<h1 class="mb-3 fs-5" id="exampleModalLabel">Форма регистрации агента</h1>
|
||||||
|
|
||||||
|
<div class="modal-body">
|
||||||
|
@csrf
|
||||||
|
в агентство<br><div class="badge bg-primary">{{ $invite->company->name }}</div>
|
||||||
|
<input type="hidden" class="form-control" id="company_id" name="company_id" value="{{ $invite->company->id }}">
|
||||||
|
|
||||||
|
<div class="mb-3 mt-3">
|
||||||
|
<label for="agentName" class="form-label">Полное имя (ФИО)</label>
|
||||||
|
<input type="text" class="form-control" id="agentName" name="name" value="{{ old('name') }}">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="agentEmail" class="form-label">Электронная почта</label>
|
||||||
|
<input type="text" class="form-control" id="agentEmail" name="email" value="{{ old('email') }}">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="agentPhone" class="form-label">Телефон</label>
|
||||||
|
<input type="tel" class="form-control" id="agentPhone" name="phone" value="{{ old('phone') }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer gap-3">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Отмена</button>
|
||||||
|
<input type="submit" class="btn btn-primary" value="Зарегистрироваться">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
@endsection
|
||||||
75
app/Modules/Invite/Views/index.blade.php
Normal file
75
app/Modules/Invite/Views/index.blade.php
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
@php($title = 'Приглашения агентов')
|
||||||
|
@extends('layouts.app')
|
||||||
|
@section('content')
|
||||||
|
<div class="d-flex mb-3 sticky-top bg-light rounded-3">
|
||||||
|
<div class="p-2 w-100"></div>
|
||||||
|
<div class="p-2 flex-shrink-1">
|
||||||
|
<form class="" method="post" action="{{ route('company.invites.create', ['company' => 1]) }}">
|
||||||
|
@csrf
|
||||||
|
<input class="btn btn-primary" type="submit" value="Создать приглашение" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h5>Действующие приглашения для<br><b>{{ $company->name }}</b></h5>
|
||||||
|
<div class="row g-2 w-100">
|
||||||
|
@foreach ($invites as $invite)
|
||||||
|
<div class="d-flex flex-row w-100 gap-3 bg-light rounded-3 p-2 align-items-center">
|
||||||
|
<div class="col flex-fill">
|
||||||
|
<div class="input-group">
|
||||||
|
<input disabled id="invite_{{ $invite->hash }}" value="{{ route('company.invite.open', ['hash' => $invite->hash]) }}" type="text"
|
||||||
|
class="form-control" placeholder="Recipient’s username" aria-label="Recipient’s username"
|
||||||
|
aria-describedby="basic-addon2">
|
||||||
|
<button data-target="invite_{{ $invite->hash }}" class="copy-invite-btn btn btn-secondary border-secondry" type="button" id="button-addon2"><i
|
||||||
|
class="bi bi-clipboard"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-3 d-flex">
|
||||||
|
Зарегистрировалось:
|
||||||
|
<div class="d-block rounded rounded-circle bg-secondary text-light text-center"
|
||||||
|
style="width:1.4rem;height:1.4rem;">
|
||||||
|
{{ $invite->registrations()->count() }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-2">
|
||||||
|
Создано:<br>{{ $invite->created_at->diffForHumans() }}
|
||||||
|
</div>
|
||||||
|
<div class="col-2">
|
||||||
|
Обновлено:<br>{{ $invite->updated_at->diffForHumans() }}
|
||||||
|
</div>
|
||||||
|
<div class="col text-end">
|
||||||
|
<div class="dropdown d-none d-md-block" style="">
|
||||||
|
<button class="btn btn-light" type="button" id="dropdownMenuButton" data-bs-toggle="dropdown"
|
||||||
|
aria-haspopup="true" aria-expanded="false">
|
||||||
|
<i class="bi bi-three-dots-vertical"></i>
|
||||||
|
</button>
|
||||||
|
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton" data-popper-placement="bottom-start">
|
||||||
|
<a class="dropdown-item"
|
||||||
|
href="{{ route('company.invite.agents', ['invite' => $invite]) }}">Агенты</a>
|
||||||
|
<form method="post" action="{{ route('company.invite.delete', ['invite' => $invite]) }}">
|
||||||
|
@csrf
|
||||||
|
<button class="dropdown-item" type="submit">Удалить</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
const copyBtns = document.querySelectorAll('.copy-invite-btn');
|
||||||
|
Array.from(copyBtns).forEach(btn => {
|
||||||
|
btn.addEventListener('click', function (event) {
|
||||||
|
targetId = '#' + event.target.dataset.target;
|
||||||
|
navigator.clipboard.writeText(document.querySelector(targetId).value)
|
||||||
|
.then(() => {
|
||||||
|
alert('Ссылка скопирована в буфер обмена');
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error(`Ошибка копирования: ${error}`)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
14
app/Modules/Invite/Views/success.blade.php
Normal file
14
app/Modules/Invite/Views/success.blade.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
@php($title = 'Приглашения агентов')
|
||||||
|
@extends('layouts.guest')
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
<div class="p-5 rounded-3 bg-success text-center text-light d-flex flex-column justify-content-center gap-3">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" fill="currentColor" class="bi bi-hand-thumbs-up-fill" viewBox="0 0 16 16">
|
||||||
|
<path d="M6.956 1.745C7.021.81 7.908.087 8.864.325l.261.066c.463.116.874.456 1.012.965.22.816.533 2.511.062 4.51a10 10 0 0 1 .443-.051c.713-.065 1.669-.072 2.516.21.518.173.994.681 1.2 1.273.184.532.16 1.162-.234 1.733q.086.18.138.363c.077.27.113.567.113.856s-.036.586-.113.856c-.039.135-.09.273-.16.404.169.387.107.819-.003 1.148a3.2 3.2 0 0 1-.488.901c.054.152.076.312.076.465 0 .305-.089.625-.253.912C13.1 15.522 12.437 16 11.5 16H8c-.605 0-1.07-.081-1.466-.218a4.8 4.8 0 0 1-.97-.484l-.048-.03c-.504-.307-.999-.609-2.068-.722C2.682 14.464 2 13.846 2 13V9c0-.85.685-1.432 1.357-1.615.849-.232 1.574-.787 2.132-1.41.56-.627.914-1.28 1.039-1.639.199-.575.356-1.539.428-2.59z"/>
|
||||||
|
</svg>
|
||||||
|
<div>
|
||||||
|
Регистрация прошла успешно. На указанную электронную почту направлено сообщение с логином и паролем для доступа к агентсткому кабинету {{ $invite->company->name }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@endsection
|
||||||
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
class CreateAgentController extends Controller
|
class CreateAgentController extends Controller
|
||||||
{
|
{
|
||||||
public function __invoke(Request $request)
|
public function __invoke(Request $request, )
|
||||||
{
|
{
|
||||||
$company = Company::findOrFail($request->company_id);
|
$company = Company::findOrFail($request->company_id);
|
||||||
if ($request->user()->cannot('update', $company))
|
if ($request->user()->cannot('update', $company))
|
||||||
|
|||||||
@ -29,12 +29,16 @@ public function boot()
|
|||||||
$this->registerLivewire();
|
$this->registerLivewire();
|
||||||
$this->registerHelpers();
|
$this->registerHelpers();
|
||||||
try {
|
try {
|
||||||
define('DESIGN_PARAMETERS', Design::getParameters());
|
if (!defined('DESIGN_PARAMETERS')) {
|
||||||
|
define('DESIGN_PARAMETERS', Design::getParameters());
|
||||||
|
}
|
||||||
if (array_key_exists('title', DESIGN_PARAMETERS)) {
|
if (array_key_exists('title', DESIGN_PARAMETERS)) {
|
||||||
\Config::set('app.name', DESIGN_PARAMETERS['title']);
|
\Config::set('app.name', DESIGN_PARAMETERS['title']);
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
define('DESIGN_PARAMETERS', []);
|
if (!defined('DESIGN_PARAMETERS')) {
|
||||||
|
define('DESIGN_PARAMETERS', []);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,11 +17,18 @@
|
|||||||
<label class="btn p-2 fs-5" for="option7">Уволенные</label>
|
<label class="btn p-2 fs-5" for="option7">Уволенные</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ms-auto p-2">
|
<div class="ms-auto p-2 d-flex gap-2">
|
||||||
<button type="button" class="btn btn-primary py-2 px-3 fs-5" data-bs-toggle="modal"
|
<div class="dropdown">
|
||||||
data-bs-target="#createAgentModal">
|
<button class="btn btn-primary fs-5 py-2 px-3 dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown"
|
||||||
<i class="bi bi-person-plus"></i>
|
aria-expanded="false">
|
||||||
</button>
|
<i class="bi bi-person-plus"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a class="dropdown-item" href="#" data-bs-toggle="modal" data-bs-target="#createAgentModal">Добавить вручную</a></li>
|
||||||
|
<li><a class="dropdown-item" href="{{ route('company.invites.select') }}">Приглашения</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@if (!$status || $status == 'all' || $status == $statuses::ACTIVE)
|
@if (!$status || $status == 'all' || $status == $statuses::ACTIVE)
|
||||||
|
|||||||
@ -1,12 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use Modules\Docs\Http\Controllers\DocsController;
|
|
||||||
|
|
||||||
Route::middleware(['auth'])->group(function ()
|
Route::middleware(['auth'])->group(function ()
|
||||||
{
|
{
|
||||||
|
|
||||||
Route::get('/doc', [DocsController::class, 'index'])->name('docs.index');
|
|
||||||
Route::get('/docs/{document}/download', [DocsController::class, 'download'])->name('docs.download');
|
|
||||||
|
|
||||||
});
|
});
|
||||||
@ -1,5 +1,4 @@
|
|||||||
@extends('layouts.guest')
|
@extends('layouts.guest')
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
<div class="">
|
<div class="">
|
||||||
<div class="">
|
<div class="">
|
||||||
|
|||||||
@ -15,33 +15,28 @@
|
|||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Route::get('/', function ()
|
Route::get('/', function () {
|
||||||
{
|
|
||||||
return view(view: 'welcome');
|
return view(view: 'welcome');
|
||||||
})->name('welcome');
|
})->name('welcome');
|
||||||
|
|
||||||
Auth::routes();
|
Auth::routes();
|
||||||
|
|
||||||
Route::get('/email/verify/{id}/{hash}', function (EmailVerificationRequest $request)
|
Route::get('/email/verify/{id}/{hash}', function (EmailVerificationRequest $request) {
|
||||||
{
|
|
||||||
$request->fulfill();
|
$request->fulfill();
|
||||||
return redirect('/home');
|
return redirect('/home');
|
||||||
})->middleware(['auth', 'signed'])->name('verification.verify');
|
})->middleware(['auth', 'signed'])->name('verification.verify');
|
||||||
|
|
||||||
Route::middleware(['auth'])->group(function ()
|
Route::middleware(['auth'])->group(function () {
|
||||||
{
|
|
||||||
Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
|
Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
|
||||||
Route::get('/clients/table', [App\Http\Controllers\ClientsTableController::class, 'index'])->name('clients.table');
|
Route::get('/clients/table', [App\Http\Controllers\ClientsTableController::class, 'index'])->name('clients.table');
|
||||||
});
|
});
|
||||||
|
|
||||||
//МАКЕТЫ
|
//МАКЕТЫ
|
||||||
Route::get('projects', function ()
|
Route::get('projects', function () {
|
||||||
{
|
|
||||||
return view(view: 'makets.projects');
|
return view(view: 'makets.projects');
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::get('profile', function ()
|
Route::get('profile', function () {
|
||||||
{
|
|
||||||
return view(view: 'user.profile');
|
return view(view: 'user.profile');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user