client form updated & modules removed

This commit is contained in:
Thekindbull 2025-09-15 23:37:40 +08:00
parent 08d682ddf2
commit b3e7d17d31
48 changed files with 1153 additions and 156 deletions

View File

@ -5,8 +5,8 @@
use Illuminate\Http\Request;
use App\Models\Deal\Deal;
use App\Models\Company\CompanyAdmin;
use App\Models\City;
use Modules\Main\Models\Company\CompanyAdmin;
use Modules\Main\Models\City;
class ClientsTableController extends Controller
{

View File

@ -7,8 +7,8 @@
use Livewire\WithoutUrlPagination;
use App\Models\User;
use App\Models\Agent\Agent;
use App\Models\Company\CompanyAdmin;
use Modules\Main\Models\Agent\Agent;
use Modules\Main\Models\Company\CompanyAdmin;
use App\Models\Deal\Deal;
use App\Models\Deal\DealStatus;
use App\Models\Deal\Client;

View File

@ -6,14 +6,14 @@
use Livewire\WithPagination;
use Livewire\WithoutUrlPagination;
use App\Models\Agent\Agent;
use App\Models\Company\CompanyAdmin;
use Modules\Main\Models\Agent\Agent;
use Modules\Main\Models\Company\CompanyAdmin;
use App\Models\Deal\Deal;
use App\Models\Deal\DealStatus;
class ContractsTable extends Component
{
{
use WithPagination, WithoutUrlPagination;
public $status;
@ -21,58 +21,58 @@ class ContractsTable extends Component
public $mode;//short || full
public function mount($status = null, $count = 10, $mode = 'full')
{
{
$this->status = $status;
$this->count = $count;
$this->mode = $mode;
}
}
public function getContracts()
{
{
$deals = false;
$user = auth()->user();
if ($agent = Agent::where('user_id', $user->id)->first())
{
{
$deals = Deal::where('agent_id', $agent->id);
}
}
elseif ($admin = CompanyAdmin::where('user_id', $user->id)->first())
{
{
$deals = Deal::whereIn('agent_id', function ($query) use ($admin)
{
{
$query->select('id');
$query->from('agents');
$query->where('company_id', $admin->company_id);
});
}
return $deals;
});
}
return $deals;
}
public function render()
{
{
$deals = $this->getDeals();
if ($this->status && $this->status == DealStatus::UNIQUE)
{
{
$deals = $deals
->whereIn('status', [DealStatus::UNIQUE])
->orderBy('id', 'desc')->paginate($this->count, ['*'], 'unique_clients');
}
}
elseif ($this->status && $this->status == DealStatus::NOT_UNIQUE)
{
{
$deals = $deals
->whereIn('status', [DealStatus::MODERATION, DealStatus::NEW , DealStatus::NOT_UNIQUE])
->orderBy('id', 'desc')->paginate($this->count, ['*'], 'not_unique_clients');
}
}
else
{
{
$deals = $deals->orderBy('id', 'desc')->paginate($this->count, ['*'], 'all_clients');
}
}
;
return view(
'livewire.clients-table',
[
'deals' => $deals,
'deals' => $deals,
'statuses' => DealStatus::class
]
);
}
}
}

View File

@ -1,7 +0,0 @@
<?php
namespace App\Models\Agent;
final class AgentStatus
{
public const ACTIVE = 'Active';
public const DISMISSED = 'Dismissed';
}

View File

@ -8,9 +8,12 @@
use App\Models\User\UserRole;
use App\Models\User\Role;
use Modules\Contracts\Models\Contract;
use Modules\Main\Models\Complex;
use Modules\Main\Models\Agent\Agent;
use Illuminate\Notifications\Notifiable;
use Modules\Bitrix\Traits\Bitrixable;
class Deal extends Model
{
use HasFactory, Notifiable, Bitrixable;
@ -24,7 +27,7 @@ class Deal extends Model
];
public function complex()
{
return $this->belongsTo(\App\Models\Complex::class);
return $this->belongsTo(Complex::class);
}
public function user()
{
@ -32,7 +35,7 @@ public function user()
}
public function agent()
{
return $this->belongsTo(\App\Models\Agent\Agent::class, 'agent_id');
return $this->belongsTo(Agent::class, 'agent_id');
}
public function contract()

View File

@ -7,7 +7,7 @@
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use App\Models\Agent\Agent;
use Modules\Main\Models\Agent\Agent;
use App\Models\Deal\Contract;
use App\Models\Deal\Deal;
use App\Models\Deal\DealStatus;

View File

@ -0,0 +1,5 @@
<?php
return [
];

View File

@ -0,0 +1,27 @@
<?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('client_create_forms', function (Blueprint $table) {
$table->id();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('client_create_forms');
}
};

View File

@ -0,0 +1,65 @@
<?php
use Modules\Contracts\Models\ContractStatus;
use Modules\Main\Models\Company\CompanyAdmin;
use Modules\Main\Models\Agent\Agent;
use Modules\Main\Models\Complex;
if (!function_exists('UserIsCompanyAdmin'))
{
function AdminCompanyOfUser()
{
if ($adminAccount = CompanyAdmin::where('user_id', auth()->user()->id)->first())
{
return $adminAccount->company;
}
else
{
return false;
}
}
}
if (!function_exists('GetAvailableAgents'))
{
function GetAvailableAgents()
{
$agents = [];
if ($adminCompany = AdminCompanyOfUser())
{
$agents = Agent::where('company_id', $adminCompany->id);
}
else
{
$agents = Agent::where('user_id', auth()->user()->id);
}
$agents->with('company:id,name');
$agents->with('user:id,name');
return $agents->get()->toArray();
}
}
if (!function_exists('GetAvailableComplexes'))
{
function GetAvailableComplexes()
{
$complexes = false;
if ($adminCompany = AdminCompanyOfUser())
{
$complexes = Complex::where('city_id', $adminCompany->city_id);
}
else
{
if ($agent = Agent::where('user_id', auth()->user()->id)->first())
{
$complexes = Complex::where('city_id', $agent->company->city_id);
}
}
if ($complexes)
{
return $complexes->get()->toArray();
}
return [];
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace Modules\ClientCreateForm\Http\Controllers;
use Modules\ClientCreateForm\Models\ClientCreateForm;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class ClientCreateFormController extends Controller
{
public function index()
{
return view('clientCreateForm::index');
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace Modules\ClientCreateForm\Http\Livewire;
use Livewire\Attributes\Validate;
use Livewire\Form;
class ClientCreateForm extends Form
{
public $currentClient;
protected $messages = [
'clients.*.firstName.required' => 'Необходимо указать имя клиента',
'clients.*.secondName.required' => 'Необходимо указать фамилию клиента',
'clients.*.phones.*.required' => 'Необходимо указать телефон',
'clients.*.phones.*.regex' => 'Телефон должен быть в международном формате',
'clients.*.phones.*.unique' => 'Клиент с таким телефоном уже существует',
'agent.integer' => 'Необходимо указать агента, от которого добавляется контакт'
];
protected function rules()
{
return [
//'agent' => ['required', 'integer'],
//'currentClient' => ['required', 'string', 'max:255'],
'currentClient.firstName' => ['required', 'string', 'max:255'],
'currentClient.secondName' => ['required', 'string', 'max:255'],
'currentClient.phones.*' => ['required', 'string', 'regex:/^(\+7)([0-9]{3})([-]{1})([0-9]{3})([-]{1})([0-9]{4})/i']
//'client.phone' => ['required', 'string', 'regex:/^\+7 \d{3} \d{3}-\d{2}-\d{2}$/'],
//'client.phone' => ['required', 'string']
];
}
}

View File

@ -0,0 +1,181 @@
<?php
namespace Modules\ClientCreateForm\Http\Livewire;
use Livewire\Component;
class ClientCreateLivewire extends Component
{
//public ClientCreateForm $form;
public $status;
public $availableAgents;
public $complexes;
public $maxClientsCount;
/////////////////////
public $agent;
public $clients;
public $currentClientIndex;
public $currentClient;
public $addSecondaryClient;
public $secondaryClient;
public $clientLabels;
public $bitrixId;
public function mount()
{
$this->complexes = GetAvailableComplexes();
$this->availableAgents = GetAvailableAgents();
$this->maxClientsCount = 2;
$this->clientLabels = ['Основной контакт', 'Супруг/супруга'];
$this->status = FormStatus::NEW;
$this->secondaryClient = false;
$this->addSecondaryClient = true;
if (count($this->availableAgents) == 1) //чтобы не выводить в форму
{ //и не заставлять пользователя указывать вручную
$this->agent = $this->availableAgents[0]['id'];
}
$this->addClient();
$this->addClient();//по-умолчанию сразу выводить супруга
$this->setCurrentClient(0);
}
public function updated($propertyName)
{
$this->status = FormStatus::NEW;
}
public function addClient()
{
if (!isset($this->clients))
{
$this->clients = [];
}
if ($this->maxClientsCount > count($this->clients))
{
$this->clients[] = [
'firstName' => '',
'secondName' => '',
'phones' => [''],
'complexId' => ''
];
}
$this->setCurrentClient(count($this->clients) - 1);
}
public function deleteCurrentContact()
{
if ($this->currentClientIndex > 0)
{
unset($this->clients[$this->currentClientIndex]);
$this->clients = array_values($this->clients);
$this->updateCurrentClientIndex($this->currentClientIndex - 1);
}
}
public function setCurrentClient($index)
{
$this->saveClient();
$this->updateCurrentClientIndex($index);
}
private function updateCurrentClientIndex($index)
{
$this->currentClient = $this->clients[$index];
$this->currentClientIndex = $index;
}
public function saveClient()
{
if (isset($this->currentClientIndex))
{
//$this->form->validate();
$this->clients[$this->currentClientIndex] = $this->currentClient;
}
}
public function addPhoneForClient()
{
$this->currentClient['phones'][] = '';
}
public function render()
{
return view(
'clientcreateform::livewire.form'
);
}
public function rendered()
{
$this->dispatch('phoneInputAdded');
}
public function resetData()
{
$this->mount();
}
public function back()
{
$this->status = FormStatus::NEW;
}
//далее - сохранение клиента в базу и отправка в битрикс.
//надо разделить на invoke классы!
/*public function save()
{
$validated = $this->form->validate();
$newUser = User::updateOrCreate(
['phone' => $this->client['phone']],
[
'name' => trim($this->client['firstName'] . ' ' . $this->client['secondName']),
'phone' => $this->client['phone']
]
);
$data = [
'agent_id' => $this->agent
,
'client_id' => $newUser->id
,
'complex_id' => $this->client['complexId']
];
if ($newDeal = Deal::create($data))
{
if ($bitrixId = $this->sendToBitrix($newDeal))
{
$newDeal->bitrix_id = $bitrixId;
$newDeal->status = DealStatus::MODERATION;
$newDeal->save();
$this->bitrixId = $bitrixId;
return $this->status = FormStatus::SUCCESS;
}
else
{
$newDeal->delete();
}
}
return $this->status = FormStatus::ERROR;
}
public function sendToBitrix(Deal $deal)
{
$agent = $deal->agent;
$agentName = $agent->user->getPartialsName();
$data = [
'CLIENT_FIRST_NAME' => $this->client['firstName'],
'CLIENT_SECOND_NAME' => $this->client['secondName'],
'CLIENT_PHONE' => '+7' . $this->client['phone'],
'BROKER_FIRST_NAME' => $agentName['firstName'],
'BROKER_SECOND_NAME' => $agentName['secondName'],
'BROKER_PHONE' => $agent->user->phone,
'BROKER_INN' => $agent->company->inn,
//'BROKER_CONTACT' => $agent->bitrixId(),
'OBJECT_NAME' => Complex::find($this->client['complexId'])->name,
'CALLBACK_URL' => route('api.client', ['hash' => $deal->confirmToken]),
];
$sender = new SendClient($deal->id, $data);
if ($bitrixId = $agent->bitrixId())
{
$sender->setAgentId($bitrixId);
}
$response = $sender->send();
if ($response)
{
return $response;
}
else
{
return false;
}
}*/
}

View File

@ -0,0 +1,11 @@
<?php
namespace Modules\ClientCreateForm\Http\Livewire;
class FormStatus
{
const NEW = 1;
const IN_PROCESS = 2;
const ERROR = 3;
const SUCCESS = 4;
const READY = 5;
}

View File

@ -0,0 +1,11 @@
<?php
namespace App\Modules\ClientCreateForm\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ClientCreateForm extends Model
{
use HasFactory;
}

View File

@ -0,0 +1,81 @@
<?php
namespace Modules\ClientCreateForm\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Blade;
use Livewire\Livewire;
class ModuleServiceProvider extends ServiceProvider
{
protected string $moduleName = 'ClientCreateForm';
public function register()
{
$this->app->register(RouteServiceProvider::class);
}
public function boot()
{
$this->registerViews();
$this->registerLivewireViews();
$this->registerMigrations();
$this->registerConfig();
$this->registerComponent();
$this->registerLivewire();
$this->registerHelpers();
}
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('ClientCreator', \Modules\ClientCreateForm\Http\Livewire\ClientCreateLivewire::class);
}
protected function registerComponent()
{
//Blade::component('<name>', \Modules\<NAME>\Http\Components\<NAME>::class);
}
protected function registerHelpers()
{
$files = glob(__DIR__ . '/../Helpers/' . "*.php");
foreach ($files as $key => $file)
{
require_once $file;
}
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace Modules\ClientCreateForm\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\\ClientCreateForm\\Http\\Controllers')
->group(app_path('Modules/ClientCreateForm/Routes/web.php'));
}
}

View File

@ -0,0 +1,13 @@
<?php
use Illuminate\Support\Facades\Route;
use Modules\ClientCreateForm\Http\Controllers\ClientCreateFormController;
Route::middleware(['auth'])->group(function() {
Route::get('/clientCreateForm', [ClientCreateFormController::class, 'index']);
Route::middleware(['hasAccess'])->group(function() {
/** Routes that need to be protected - Маршруты которые нужно защитить */
});
});

View File

@ -0,0 +1,4 @@
@extends('layouts.app')
@section('content')
<h1> Example views </h1>
@endsection

View File

@ -0,0 +1,253 @@
<?php
use Modules\ClientCreateForm\Http\Livewire\FormStatus;
?>
<div>
<div class="w-100 text-center" wire:loading wire:target="save, resetData, back">
<div class="spinner-border " style="width: 4rem; height: 4rem;" role="status">
<span class="visually-hidden">Загрузка формы...</span>
</div>
</div>
<div class="w-100" wire:loading.remove wire:target="save, resetData, back">
@if ($status == FormStatus::NEW || $status == FormStatus::READY)
<div class="h4 pb-2 mb-4 fw-bold ">
<small>Добавить клиента</small>
</div>
<ul class="nav nav-tabs">
@foreach ($clients as $clientIndex => $clientItem)
<li class="nav-item">
<a class="nav-link @if ($clientIndex == $currentClientIndex) active @else bg-secondary-subtle @endif"
aria-current="page" href="#" wire:click="setCurrentClient({{ $clientIndex }})">
@if (array_key_exists($clientIndex, $clientLabels))
{{ $clientLabels[$clientIndex] }}
@else
Контакт {{ $clientIndex + 1 }}
@endif
</a>
</li>
@endforeach
@if ($maxClientsCount > count($clients))
<li class="align-middle p-2">
<a class="text-light " href="#" wire:click="addClient">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor"
class="bi bi-plus-circle" viewBox="0 0 16 16">
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16" />
<path
d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4" />
</svg>
</a>
</li>
@endif
</ul>
<div class="bg-light border border-1 rounded-bottom-4 mb-2">
<div class="p-2">
<div class="row mb-2">
<div class="col-12 col-xl-6">
<div class="form-floating mb-3">
<input wire:model.live="currentClient.firstName" id="currentClient.firstName"
type="text"
class="form-control rounded-4 @error('currentClient.firstName') is-invalid @enderror"
name="currentClient.firstName" required autocomplete="currentClient.firstName"
placeholder="Имя">
<label for="currentClient.firstName">Имя</label>
@error('currentClient.firstName')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="col-12 col-xl-6">
<div class="form-floating mb-3">
<input wire:model.live="currentClient.secondName" id="currentClient.secondName"
type="text"
class="form-control rounded-4 @error('currentClient.secondName') is-invalid @enderror"
name="currentClient.secondName" required autocomplete="currentClient.secondName"
placeholder="Фамилия">
<label for="currentClient.secondName">Фамилия</label>
@error('currentClient.secondName')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
</div>
@foreach ($currentClient['phones'] as $phoneKey => $phone)
<div class="row my-1">
<div class="col-12 hstack gap-2">
<div class="form-floating me-auto w-100">
<input wire:model="currentClient.phone.{{ $phoneKey }}"
id="currentClient.phone.{{ $phoneKey }}" type="tel" data-phone-pattern
class="form-control rounded-4 @error('currentClient.phone.{{ $phoneKey }}') is-invalid @enderror"
name="currentClient.phone.{{ $phoneKey }}" required autocomplete="phone"
placeholder="Телефон клиента">
<label for="currentClient.phone.{{ $phoneKey }}">Телефон</label>
@error('currentClient.phone.{{ $phoneKey }}')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
@if (count($currentClient['phones']) == $phoneKey + 1)
<a class="" href="#" wire:click="addPhoneForClient"
title="Добавить еще один телефон для клиента">
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30"
fill="currentColor" class="bi bi-plus-circle" viewBox="0 0 16 16">
<path
d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16" />
<path
d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4" />
</svg>
</a>
@endif
</div>
</div>
@endforeach
</div>
@if ($currentClientIndex > 0)
<div class="mx-3 pb-2 text-end">
<a wire:click="deleteCurrentContact" class="text-primary"
style="text-decoration: underline dotted;" href="#">
Удалить контакт</a>
</div>
@endif
</div>
<div class="form-floating mb-3">
<select wire:model.live="client.complexId"
class="form-select rounded-4 @error('client.complexId') is-invalid @enderror" id="client.complexId"
name="client.complexId" aria-label="Жилой комплекс">
<option selected></option>
@foreach ($complexes as $complex)
<option value="{{ $complex['id'] }}">
{{ $complex['name'] }}
</option>
@endforeach
</select>
<label for="client.complexId">Жилой комплекс</label>
@error('client.complexId')
<span class="invalid-feedback " role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
@if (count($availableAgents) > 1)
<div class="form-floating mb-3">
<select wire:model.live="agent" class="form-select rounded-4 @error('agent') is-invalid @enderror"
id="agent" name="agent" aria-label="Агент">
<option selected></option>
@foreach ($agents as $agent)
<option value="{{ $agent->id }}">
{{ $agent->user->name }}
</option>
@endforeach
</select>
<label for="client.complexId">Агент</label>
@error('agent')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
@endif
@if ($status == FormStatus::READY && !$errors->any())
<div class="">
<button wire:click="save" class="btn btn-secondary rounded-4 fw-bold fs-5 w-100 py-3"
style="background-color: #20184d;">
Создать нового клиента
</button>
</div>
@else
<div class="">
<button disabled class="btn btn-secondary disabled rounded-4 fw-bold fs-5 w-100 py-3"
style="background-color: #20184d;">
Создать нового клиента
</button>
</div>
@endif
@endif
@if ($status == FormStatus::SUCCESS)
<div class="text-center fs-1">
<svg xmlns="http://www.w3.org/2000/svg" width="60" height="60" fill="currentColor"
class="bi bi-check-circle-fill" viewBox="0 0 16 16">
<path
d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0m-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z">
</path>
</svg>
</div>
<div class="text-center fs-3">Клиент добавлен</div>
<div class="text-center fs-5 ">Мы проверим его уникальность и направим Вам информацию в личном
кабинете</div>
<div class="text-center mt-3">
<button wire:click="$refresh" class="btn active border-white border-3 rounded">Продолжить</button>
</div>
@endif
@if ($status == FormStatus::ERROR)
<div class="text-center fs-1 mt-3">
<svg xmlns="http://www.w3.org/2000/svg" width="60" height="60" fill="currentColor"
class="bi bi-emoji-astonished" viewBox="0 0 16 16">
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16" />
<path
d="M7 6.5C7 7.328 6.552 8 6 8s-1-.672-1-1.5S5.448 5 6 5s1 .672 1 1.5m4 0c0 .828-.448 1.5-1 1.5s-1-.672-1-1.5S9.448 5 10 5s1 .672 1 1.5M4.884 4.022a2 2 0 0 1 1.458-.048.5.5 0 0 0 .316-.948 3 3 0 0 0-2.167.077 3.1 3.1 0 0 0-.773.478q-.036.03-.07.064l-.002.001a.5.5 0 0 0 .707.708l-.001.002.001-.002a2 2 0 0 1 .122-.1 2 2 0 0 1 .41-.232Zm6.232 0a2 2 0 0 0-1.458-.048.5.5 0 1 1-.316-.948 3 3 0 0 1 2.168.077 3 3 0 0 1 .773.478l.07.064v.001a.5.5 0 0 1-.706.708l.002.002-.002-.002a2 2 0 0 0-.122-.1 2 2 0 0 0-.41-.232ZM8 10c-.998 0-1.747.623-2.247 1.246-.383.478.08 1.06.687.98q1.56-.202 3.12 0c.606.08 1.07-.502.687-.98C9.747 10.623 8.998 10 8 10" />
</svg>
</div>
<div class="text-center fs-3">Ой!</div>
<div class="text-center fs-5 ">Кажется, возникла проблема на нашей стороне, мы уже ее решаем.
Попробуйте зайти сюда позже.</div>
<div class="text-center my-3">
<button wire:click="back" class="btn btn-lg active border-2 rounded">Повторить</button>
</div>
@endif
</div>
@script
<script>
eventCalllback = function(e) {
var el = e.target,
clearVal = el.dataset.phoneClear,
pattern = el.dataset.phonePattern,
matrix_def = "+7(___) ___-__-__",
matrix = pattern ? pattern : matrix_def,
i = 0,
def = matrix.replace(/\D/g, ""),
val = e.target.value.replace(/\D/g, "");
if (clearVal !== 'false' && e.type === 'blur') {
if (val.length < matrix.match(/([\_\d])/g).length) {
e.target.value = '';
return;
}
}
if (def.length >= val.length) val = def;
e.target.value = matrix.replace(/./g, function(a) {
return /[_\d]/.test(a) && i < val.length ? val.charAt(i++) : i >= val.length ? "" :
a
});
}
document.addEventListener('livewire:initialized', () => {
setPhonePatternToInput();
})
$wire.on('phoneInputAdded', () => {
setInterval(() => {
setPhonePatternToInput()
}, 2000)
});
function setPhonePatternToInput() {
var phone_inputs = document.querySelectorAll('[data-phone-pattern]');
for (let elem of phone_inputs) {
for (let ev of ['input', 'blur', 'focus']) {
elem.addEventListener(ev, eventCalllback);
}
}
}
</script>
@endscript
</div>

View File

@ -1,5 +1,6 @@
<?php
use Modules\Contracts\Models\ContractStatus;
use Modules\Contracts\Models\Contract;
if (!function_exists('GetContractStatuses'))
{
@ -13,4 +14,20 @@ function GetContractStatuses()
ContractStatus::TREATY => ContractStatus::getName(ContractStatus::TREATY),
];
}
}
if (!function_exists('GetAgentPaymentForContract'))
{
function GetAgentPaymentForContract(Contract $contract)
{
$agent = $contract->deal->agent;
$agentPaymentable = $agent->getPaymentable($contract->deal->complex);
$rewardPercent = $agentPaymentable->getPaymentablePercent();
if (!$rewardPercent)
{
$rewardPercent = 0;
}
$price = $contract->price;
return ($price * $rewardPercent) / 100;
}
}

View File

@ -44,4 +44,11 @@ public function delete(Contract $contract)
}
return back()->withErrors('Не удалось корректно удалить договор и сделку. Попробуйте позже.');
}
public function comment(Request $request, Contract $contract)
{
$contract->comment = $request->comment;
$contract->save();
return back()->with('success', 'Комментарий к договору сохранен');
}
}

View File

@ -3,15 +3,15 @@
namespace Modules\Contracts\Http\Livewire;
use Livewire\Component;
use App\Models\Company\Company;
use App\Models\Complex;
use App\Models\Agent\Agent;
use Modules\Main\Models\Company\Company;
use Modules\Main\Models\Complex;
use Modules\Main\Models\Agent\Agent;
use App\Models\Deal\Deal;
use App\Models\Deal\Contract;
use Modules\Contracts\Models\Contract;
use App\Models\Deal\ContractStatus;
use App\Models\User\UserRole;
use App\Models\User\Role;
use App\Models\Company\CompanyAdmin;
use Modules\Main\Models\Company\CompanyAdmin;
class ContractsTableLivewire extends Component
{

View File

@ -7,5 +7,7 @@
{
Route::any('/contracts', [ContractsController::class, 'index'])->name('contracts');
Route::post('/contracts/{contract}/delete', [ContractsController::class, 'delete'])->name('contract.delete');
Route::post('/contracts/{contract}/comment', [ContractsController::class, 'comment'])->name('contract.comment');
});

View File

@ -41,14 +41,7 @@
</td>
<td class="align-middle">
<?php
$agent = $contract->deal->agent;
$agentPaymentable = $agent->getPaymentable($contract->deal->complex);
$rewardPercent = $agentPaymentable->getPaymentablePercent();
if (!$rewardPercent) {
$rewardPercent = 0;
}
$price = $contract->price;
$contract->reward = ($price * $rewardPercent) / 100;
$contract->reward = GetAgentPaymentForContract($contract);
//$contract->reward = $contract->reward ? $contract->reward : 0;
$reward = Number::forHumans($contract->reward, precision: 2);
$reward = str_replace('million', 'млн', $reward);
@ -61,7 +54,7 @@
<span class="fw-bold">{!! $reward !!}</span>
@else
<span style="text-decoration:underline;text-decoration-style: dotted;cursor:pointer"
title='Рассчетное вознаграждение в размере {{ $rewardPercent }}%&#013;Вознаграждение будет зафиксировано при изменении статуса на "Выплачено"'>
title='Вознаграждение будет зафиксировано при изменении статуса на "Выплачено"'>
{!! $reward !!}
</span>
@endif
@ -84,7 +77,7 @@
<form method="post"
action="{{ route('contract.delete', ['contract' => $contract]) }}">
@csrf
<button class="dropdown-item" type="submit">Удалить</button>
<button class="dropdown-item disabled" type="submit">Удалить</button>
</form>
</div>
</div>

View File

@ -0,0 +1,5 @@
<?php
return [
];

View File

@ -0,0 +1,27 @@
<?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('mains', function (Blueprint $table) {
$table->id();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('mains');
}
};

View File

@ -0,0 +1,17 @@
<?php
namespace Modules\Main\Http\Controllers;
use Modules\Main\Models\Main;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class MainController extends Controller
{
public function index()
{
return view('main::index');
}
}

View File

@ -1,13 +1,13 @@
<?php
namespace App\Models\Agent;
namespace Modules\Main\Models\Agent;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Models\Company\Company;
use Modules\Main\Models\Company\Company;
use App\Models\User;
use App\Models\User\UserRole;
use App\Models\User\Role;

View File

@ -0,0 +1,7 @@
<?php
namespace Modules\Main\Models\Agent;
final class AgentStatus
{
public const ACTIVE = 'Active';
public const DISMISSED = 'Dismissed';
}

View File

@ -1,6 +1,6 @@
<?php
namespace App\Models;
namespace Modules\Main\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Models\Company;
namespace Modules\Main\Models\Company;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Models\Company;
namespace Modules\Main\Models\Company;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
@ -9,29 +9,32 @@
use App\Models\User\Role;
class CompanyAdmin extends Model
{
{
use HasFactory;
protected $fillable = [
'user_id',
'company_id'
];
public function company()
{
return $this->belongsTo(Company::class);
}
protected static function booted(): void
{
{
static::created(function (CompanyAdmin $admin)
{
{
UserRole::create([
'user_id' => $admin->user_id,
'role_id' => Role::COMPANY_ADMIN
]);
});
});
static::deleted(function (CompanyAdmin $admin)
{
{
UserRole::where([
'user_id' => $admin->user_id,
'role_id' => Role::COMPANY_ADMIN
])->delete();
});
});
}
}
}

View File

@ -1,5 +1,5 @@
<?php
namespace App\Models\Company;
namespace Modules\Main\Models\Company;
enum CompanyStatus: string
{
case STATUS_NEW = 'new';

View File

@ -1,8 +1,8 @@
<?php
namespace App\Models\Company;
namespace Modules\Main\Models\Company;
enum CompanyType: string
{
case Agency = "AGENCY";
{
case Agency = "AGENCY";
case SelfEmployer = "SELFEMP";
case SoleProperty = "SOLEPROP";
}
}

View File

@ -1,10 +1,10 @@
<?php
namespace App\Models\Company;
namespace Modules\Main\Models\Company;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Models\Company\Company;
use Modules\Main\Models\Company\Company;
class Details
{

View File

@ -1,11 +1,12 @@
<?php
namespace App\Models;
namespace Modules\Main\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Modules\Main\Models\City;
class Complex extends Model
{
use HasFactory;
@ -16,6 +17,6 @@ class Complex extends Model
];
public function city()
{
return $this->belongsTo(\App\Models\City::class, 'city_id')->withTrashed();
return $this->belongsTo(City::class, 'city_id')->withTrashed();
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace App\Modules\Main\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Main extends Model
{
use HasFactory;
}

View File

@ -0,0 +1,68 @@
<?php
namespace Modules\Main\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Blade;
use Livewire\Livewire;
class ModuleServiceProvider extends ServiceProvider
{
protected String $moduleName = 'Main';
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);
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace Modules\Main\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\\Main\\Http\\Controllers')
->group(app_path('Modules/Main/Routes/web.php'));
}
}

View File

@ -0,0 +1,13 @@
<?php
use Illuminate\Support\Facades\Route;
use Modules\Main\Http\Controllers\MainController;
Route::middleware(['auth'])->group(function() {
Route::get('/main', [MainController::class, 'index']);
Route::middleware(['hasAccess'])->group(function() {
/** Routes that need to be protected - Маршруты которые нужно защитить */
});
});

View File

@ -0,0 +1,4 @@
@extends('layouts.app')
@section('content')
<h1> Example views </h1>
@endsection

View File

@ -4,9 +4,9 @@
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Models\Agent\Agent;
use App\Models\Company\Company;
use App\Models\Complex;
use Modules\Main\Models\Agent\Agent;
use Modules\Main\Models\Company\Company;
use Modules\Main\Models\Complex;
class Payment extends Model
{
use HasFactory;

View File

@ -3,7 +3,7 @@
namespace Modules\Payment\Traits;
use Illuminate\Http\Request;
use Modules\Payment\Models\Payment;
use App\Models\Complex;
use Modules\Main\Models\Complex;
trait Paymentable
{
private $defaultValue = -1; // -1 || null

View File

@ -24,11 +24,18 @@ public function register(): void
{
//Получить имя модуля из имени каталога
$moduleName = basename($moduleDirectory);
$providerClassName = '\\Modules\\' . $moduleName . '\\Providers\\ModuleServiceProvider';
if (class_exists($providerClassName))
try
{
//Зарегистрировать поставщика услуг модуля, если он существует
$this->app->register($providerClassName);
$providerClassName = '\\Modules\\' . $moduleName . '\\Providers\\ModuleServiceProvider';
if (class_exists($providerClassName))
{
//Зарегистрировать поставщика услуг модуля, если он существует
$this->app->register($providerClassName);
}
}
catch (\Exception $e)
{
dd($e);
}
}
}

View File

@ -36,21 +36,6 @@ class="bi bi-arrow-right" viewBox="0 0 16 16">
<div class="fs-5 fw-bold text-secondary my-2">{{ $contract->deal->complex->name }}</div>
</div>
<div class="col-3 text-end">
<!--<a href="" class="btn border-1 border-secondary-subtle text-secondary rounded-4 p-3">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor"
class="bi bi-trash3" viewBox="0 0 16 16">
<path
d="M6.5 1h3a.5.5 0 0 1 .5.5v1H6v-1a.5.5 0 0 1 .5-.5M11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3A1.5 1.5 0 0 0 5 1.5v1H1.5a.5.5 0 0 0 0 1h.538l.853 10.66A2 2 0 0 0 4.885 16h6.23a2 2 0 0 0 1.994-1.84l.853-10.66h.538a.5.5 0 0 0 0-1zm1.958 1-.846 10.58a1 1 0 0 1-.997.92h-6.23a1 1 0 0 1-.997-.92L3.042 3.5zm-7.487 1a.5.5 0 0 1 .528.47l.5 8.5a.5.5 0 0 1-.998.06L5 5.03a.5.5 0 0 1 .47-.53Zm5.058 0a.5.5 0 0 1 .47.53l-.5 8.5a.5.5 0 1 1-.998-.06l.5-8.5a.5.5 0 0 1 .528-.47M8 4.5a.5.5 0 0 1 .5.5v8.5a.5.5 0 0 1-1 0V5a.5.5 0 0 1 .5-.5" />
</svg>
</a>
<a href="" class="btn border-1 border-secondary-subtle text-secondary rounded-4 p-3">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor"
class="bi bi-pen" viewBox="0 0 16 16">
<path
d="m13.498.795.149-.149a1.207 1.207 0 1 1 1.707 1.708l-.149.148a1.5 1.5 0 0 1-.059 2.059L4.854 14.854a.5.5 0 0 1-.233.131l-4 1a.5.5 0 0 1-.606-.606l1-4a.5.5 0 0 1 .131-.232l9.642-9.642a.5.5 0 0 0-.642.056L6.854 4.854a.5.5 0 1 1-.708-.708L9.44.854A1.5 1.5 0 0 1 11.5.796a1.5 1.5 0 0 1 1.998-.001m-.644.766a.5.5 0 0 0-.707 0L1.95 11.756l-.764 3.057 3.057-.764L14.44 3.854a.5.5 0 0 0 0-.708z" />
</svg>
</a>-->
</div>
</div>
<!--Основная часть-->
@ -60,7 +45,7 @@ class="bi bi-pen" viewBox="0 0 16 16">
<div class="col col-md-6">
<div class="fs-6 text-secondary">Статус</div>
<div class="fw-bold fs-5 text-truncate text-dark-emphasis">
{{ __('contract status ' . strtolower($contract->status)) }}
{{ __('contracts.status_' . $contract->status) }}
</div>
</div>
<div class="col col-md-6">
@ -70,18 +55,24 @@ class="bi bi-pen" viewBox="0 0 16 16">
</div>
</div>
<div class="row my-4">
<div class="col col-md-4">
<div class="fs-6 text-secondary">Площадь объекта</div>
<div class="fw-bold fs-5 text-truncate text-dark-emphasis">{{ $contract->square }}</div>
</div>
<div class="col col-md-4">
<div class="fs-6 text-secondary">Этаж</div>
<div class="fw-bold fs-5 text-truncate text-dark-emphasis">{{ $contract->floor }}</div>
</div>
<div class="col col-md-4">
<div class="fs-6 text-secondary">Помещение</div>
<div class="fw-bold fs-5 text-truncate text-dark-emphasis">{{ $contract->room }}</div>
</div>
@if ($contract->square)
<div class="col col-md-4">
<div class="fs-6 text-secondary">Площадь объекта</div>
<div class="fw-bold fs-5 text-truncate text-dark-emphasis">{{ $contract->square }}</div>
</div>
@endif
@if ($contract->floor)
<div class="col col-md-4">
<div class="fs-6 text-secondary">Этаж</div>
<div class="fw-bold fs-5 text-truncate text-dark-emphasis">{{ $contract->floor }}</div>
</div>
@endif
@if ($contract->room)
<div class="col col-md-4">
<div class="fs-6 text-secondary">Помещение</div>
<div class="fw-bold fs-5 text-truncate text-dark-emphasis">{{ $contract->room }}</div>
</div>
@endif
</div>
<div class="row my-4">
<div class="col col-md-6">
@ -96,15 +87,10 @@ class="bi bi-pen" viewBox="0 0 16 16">
<div class="col col-md-6">
<div class="fs-6 text-secondary">Вознаграждение</div>
<div class="fw-bold fs-5 text-truncate text-dark-emphasis">
{{ number_format($contract->reward, 2, ',', ' ') }}</div>
</div>
</div>
<div class="row my-4">
<div class="col">
<div class="fs-6 text-secondary">Комментарий к договору</div>
<div class="fw-bold fs-5 text-truncate text-dark-emphasis">{{ $contract->comment }}</div>
{{ number_format(GetAgentPaymentForContract($contract), 2, ',', ' ') }}</div>
</div>
</div>
</div>
<div class="col col-lg-4 p-3">
<div class="rounded-4 ratio ratio-1x1 rounded overflow-hidden" style="background-color:#ebeef5"
@ -128,6 +114,29 @@ class="bi bi-pen" viewBox="0 0 16 16">
</div>
</div>
</div>
<div class="row pt-3 border-1 border-top">
<div class="col">
<div class="fs-6 text-secondary hstack gap-2">
<span>Комментарий к договору</span>
@if ($contract->comment)
<a class="ms-auto" href="#" data-bs-toggle="modal" data-bs-target="#contractCommentModal">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-pen" viewBox="0 0 16 16">
<path
d="m13.498.795.149-.149a1.207 1.207 0 1 1 1.707 1.708l-.149.148a1.5 1.5 0 0 1-.059 2.059L4.854 14.854a.5.5 0 0 1-.233.131l-4 1a.5.5 0 0 1-.606-.606l1-4a.5.5 0 0 1 .131-.232l9.642-9.642a.5.5 0 0 0-.642.056L6.854 4.854a.5.5 0 1 1-.708-.708L9.44.854A1.5 1.5 0 0 1 11.5.796a1.5 1.5 0 0 1 1.998-.001m-.644.766a.5.5 0 0 0-.707 0L1.95 11.756l-.764 3.057 3.057-.764L14.44 3.854a.5.5 0 0 0 0-.708z" />
</svg>
</a>
@endif
</div>
@if ($contract->comment)
<div class="fw-bold fs-5 text-truncate text-dark-emphasis">{{ $contract->comment }}</div>
@else
<div><a href="#" data-bs-toggle="modal" data-bs-target="#contractCommentModal">Оставьте
комментарий</a>, он будет виден
только вам</div>
@endif
</div>
</div>
</div>
<div class="col-12 col-lg-4 py-3 text-dark" style="background-color:#eef5fb">
<div class="fw-bold fs-5 mb-3">История договора</div>
@ -155,6 +164,31 @@ class="bi bi-record-circle-fill align-middle" viewBox="0 0 16 16">
@endforeach
@endif
</div>
<!-- Modal -->
<div class="modal fade" id="contractCommentModal" tabindex="-1" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<form class="modal-dialog" method="post"
action="{{ route('contract.comment', ['contract' => $contract]) }}">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">Комментарий к договору</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
@csrf
<div class="mb-3">
<label for="contractComment" class="form-label">Ваш комментарий</label>
<textarea class="form-control" id="contractComment" name="comment" rows="3">{{ $contract->comment }}</textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Отмена</button>
<button type="submit" class="btn btn-primary">Сохранить</button>
</div>
</div>
</form>
</div>
</div>
<style>
.zoomable-container {

View File

@ -48,12 +48,8 @@
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body" style="">
<livewire:createClientForm />
<livewire:ClientCreator />
</div>
<!--<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Отмена</button>
<input type="submit" class="btn btn-primary" value="Добавить">
</div>-->
</div>
</div>
</div>

View File

@ -1,29 +1,44 @@
<div>
<div class="fs-5 bg-light p-0 m-0 border border-1 rounded-4 overflow-hidden">
<div class="fs-5 bg-light p-0 m-0 border border-1 rounded-4">
@if ($clients->count() == 0)
<div class="text-center py-5">Нет данных для отображения</div>
@endif
<div class="m-2">
<div class="vstack">
@foreach ($clients as $client)
<div class="row my-2">
<div class="col fw-semibold fs-5 align-middle">
{{ $client->name }}
</div>
<div class="col-1">
@if ($client->deals->count() > 1)
<span
class="badge rounded rounded-pill bg-primary">{{ $client->deals()->whereHas('contract')->count() }}</span>
@endif
</div>
@if ($mode == 'full')
<?php
$cities = [];
$filterRow = [];
$clientDeals = $client->deals;
foreach ($clientDeals as $deal) {
$filterRow[] = 'filter[deal_id][]=' . $deal->id;
$cities[] = $deal->complex->city->name;
}
$filterRow = implode('&', $filterRow);
$cities = array_unique($cities);
$cities = implode(', ', array: $cities);
$dealsWithContracts = $client->deals()->whereHas('contract');
?>
@if ($mode == 'full')
<div class="row m-0 my-2">
<div class="col fw-semibold fs-5 align-middle text-start">
{{ $client->name }}
</div>
<div class="col">
{{ $cities }}
</div>
<div class="col-3 align-middle">
{{ $client->phone }}
</div>
<div class="col-1">
@if ($client->deals->count() == 1)
<a href="{{ route('contract', ['contract' => $client->deals->first()->contract]) }}"
class="btn">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"
<div class="col-1 text-end">
@if ($dealsWithContracts->count() == 1)
<a href="{{ route('contract', ['contract' => $dealsWithContracts->first()->contract]) }}"
class="icon-link icon-link-hover">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20"
fill="currentColor" class="bi bi-file-earmark-text" viewBox="0 0 16 16">
<path
d="M5.5 7a.5.5 0 0 0 0 1h5a.5.5 0 0 0 0-1zM5 9.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5m0 2a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5" />
@ -31,16 +46,9 @@ class="btn">
d="M9.5 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V4.5zm0 1v2A1.5 1.5 0 0 0 11 4.5h2V14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1z" />
</svg>
</a>
@elseif($client->deals->count() > 1)
<?php
$filterRow = [];
foreach ($client->deals as $deal) {
$filterRow[] = 'filter[deal_id][]=' . $deal->id;
}
$filterRow = implode('&', $filterRow);
?>
<a href="{{ route('contracts', [$filterRow]) }}" class="btn">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"
@elseif($dealsWithContracts->count() > 1)
<a href="{{ route('contracts', [$filterRow]) }}" class="icon-link icon-link-hover">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20"
fill="currentColor" class="bi bi-arrow-right" viewBox="0 0 16 16">
<path fill-rule="evenodd"
d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8" />
@ -48,8 +56,41 @@ class="btn">
</a>
@endif
</div>
@endif
</div>
</div>
@else
<div class="m-2">
@if ($dealsWithContracts->count() == 1)
<a href="{{ route('contract', ['contract' => $dealsWithContracts->first()->contract]) }}"
class="icon-link icon-link-hover w-100 hstack gap-2 text-decoration-none">
<span class="text-dark">{{ $client->name }}</span>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20"
fill="currentColor" class="bi bi-file-earmark-text ms-auto" viewBox="0 0 16 16">
<path
d="M5.5 7a.5.5 0 0 0 0 1h5a.5.5 0 0 0 0-1zM5 9.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5m0 2a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5" />
<path
d="M9.5 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V4.5zm0 1v2A1.5 1.5 0 0 0 11 4.5h2V14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1z" />
</svg>
</a>
@elseif($dealsWithContracts->count() > 1)
<?php
$filterRow = [];
foreach ($client->deals as $deal) {
$filterRow[] = 'filter[deal_id][]=' . $deal->id;
}
$filterRow = implode('&', $filterRow);
?>
<a href="{{ route('contracts', [$filterRow]) }}"
class="icon-link icon-link-hover w-100 hstack gap-2 text-decoration-none">
<span class="text-dark">{{ $client->name }}</span>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20"
fill="currentColor" class="bi bi-arrow-right ms-auto" viewBox="0 0 16 16">
<path fill-rule="evenodd"
d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8" />
</svg>
</a>
@endif
</div>
@endif
@endforeach
</div>
</div>

View File

@ -23,19 +23,20 @@ class="list-group-item list-group-item-action p-3 bg-white rounded border border
</a>
</div>
<div class="mt-3">
<div class="d-flex">
<div class="hstack gap-2">
<div class="fs-5 fw-bold">Клиенты</div>
<div class="ms-auto p-2">
<a href="{{ route('clients.table') }}">Смотреть все</a>
</div>
</div>
@livewire('clientsTable', ['count' => 3, 'mode' => 'short'])
<div>
@livewire('clientsTable', ['count' => 6, 'mode' => 'short'])
</div>
</div>
</div>
<div class="col-12 col-lg-6">
<div class="p-2 px-sm-5 py-sm-3 bg-primary border rounded-3 mx-auto d-flex align-items-center"
style="min-height:30em;">
<livewire:createClientForm />
<div class="p-2 px-sm-4 py-sm-3 bg-primary border rounded-3 mx-auto" style="min-height:30em;">
<livewire:ClientCreator />
</div>
</div>
</div>