city managers created

This commit is contained in:
Thekindbull 2025-09-22 23:34:59 +08:00
parent e0b417a5f9
commit c5d1b1b973
12 changed files with 264 additions and 74 deletions

View File

@ -17,4 +17,15 @@ public function index(Request $request)
'filter' => $request->filter
]);
}
public function create(Request $request)
{
$manager = CityManager::firstOrCreate($request->only(['user_id', 'city_id']));
return to_route('admin.cities.managers');
}
public function delete(Request $request, CityManager $manager)
{
$manager->delete();
return to_route('admin.cities.managers');
}
}

View File

@ -33,6 +33,10 @@
Route::post('/admin/cities/{city}/delete', [Modules\Admin\Http\Controllers\AdminCitiesController::class, 'delete'])->name('admin.cities.delete');
Route::post('/admin/cities/{city}/restore', [Modules\Admin\Http\Controllers\AdminCitiesController::class, 'restore'])->withTrashed()->name('admin.cities.restore');
Route::get('/admin/cities/managers', [Modules\Admin\Http\Controllers\AdminCityManagersController::class, 'index'])->name('admin.cities.managers');
Route::post('/admin/cities/managers/create', [Modules\Admin\Http\Controllers\AdminCityManagersController::class, 'create'])->name('admin.cities.managers.create');
Route::post('/admin/cities/managers/{manager}/delete', [Modules\Admin\Http\Controllers\AdminCityManagersController::class, 'delete'])->name('admin.cities.managers.delete');
Route::get('/admin/complexes', [Modules\Admin\Http\Controllers\AdminComplexesController::class, 'index'])->name('admin.complexes');
Route::get('/admin/complexes/{complex}/edit', [Modules\Admin\Http\Controllers\AdminComplexesController::class, 'edit'])->name('admin.complexes.edit');

View File

@ -27,6 +27,40 @@
</div>
</div>
<div class="fs-5 bg-light p-0 m-0 border border-1 rounded-4 py-3">
<table class="table m-0">
<thead>
<tr scope="col">
<th>Пользователь</th>
<th>Город</th>
<th>Дата назначения</th>
<th></th>
</tr>
</thead>
<tbody class=" ">
@foreach ($managers as $manager)
<tr>
<td>{{ $manager->user->name }}</td>
<td>{{ $manager->city->name }}</td>
<td>{{ $manager->created_at->diffForHumans() }}</td>
<td>
<div class="dropdown" 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">
<form method="post"
action="{{ route('admin.cities.managers.delete', ['manager' => $manager]) }}">
@csrf
<button class="dropdown-item" type="submit">Удалить</button>
</form>
</div>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@ -34,7 +68,8 @@
<div class="modal fade" id="createCityManagerModal" tabindex="-1" aria-labelledby="createCityModalLabel"
aria-hidden="true">
<form class="modal-dialog modal-dialog-centered" action="{{ route('admin.cities.create') }}" method="post">
<form class="modal-dialog modal-dialog-centered" action="{{ route('admin.cities.managers.create') }}"
method="post">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="createCityModalLabel">Новый менеджер</h1>
@ -44,8 +79,15 @@
<div class="my-3">
@csrf
<div class="mb-3">
<div>
Пользователь:
</div>
@livewire('user-selector')
</div>
<div class="form-floating">
<select name="city" class="form-select" id="floatingSelectCity" aria-label="Укажите город">
<select name="city_id" class="form-select" id="floatingSelectCity" aria-label="Укажите город">
@foreach ($cities as $city)
<option value="{{ $city->id }}" @if ($filter == $city->id) selected @endif>
{{ $city->name }}</option>
@ -54,7 +96,6 @@
<label for="floatingSelectCity">Укажите город</label>
</div>
@livewire('user-selector')
</div>
</div>

View File

@ -0,0 +1,28 @@
<?php
namespace Modules\CityManager\Http\Livewire;
use Livewire\Component;
use Modules\CityManager\Models\CityManager;
class CityManagerInfo extends Component
{
public $manager = false;
public function mount()
{
$city = false;
if (($company = AdminCompanyOfUser()) || ($company = AgentCompanyOfUser()))
{
//print_r($company);
if ($cityManager = CityManager::where('city_id', $company->city->id)->first())
{
$this->manager = $cityManager->user;
}
}
}
public function render()
{
return view('citymanager::livewire.info.index');
}
}

View File

@ -4,7 +4,7 @@
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Models\User;
use Modules\User\Models\User;
use Modules\Main\Models\City;
class CityManager extends Model
{

View File

@ -8,7 +8,7 @@
class ModuleServiceProvider extends ServiceProvider
{
protected String $moduleName = 'CityManager';
protected string $moduleName = 'CityManager';
public function register()
{
@ -27,38 +27,41 @@ public function boot()
protected function registerViews()
{
$moduleViewsPath = __DIR__.'/../Views';
$moduleViewsPath = __DIR__ . '/../Views';
$this->loadViewsFrom(
$moduleViewsPath, strtolower($this->moduleName)
$moduleViewsPath,
strtolower($this->moduleName)
);
}
protected function registerLivewireViews()
{
$moduleViewsPath = __DIR__.'/../Views/livewire';
$moduleViewsPath = __DIR__ . '/../Views/livewire';
$this->loadViewsFrom(
$moduleViewsPath, strtolower($this->moduleName)
$moduleViewsPath,
strtolower($this->moduleName)
);
}
protected function registerMigrations()
{
$this->loadMigrationsFrom(
app_path('Modules/'.$this->moduleName.'/Database/Migrations')
app_path('Modules/' . $this->moduleName . '/Database/Migrations')
);
}
protected function registerConfig()
{
$path = app_path('Modules/'.$this->moduleName.'/Config/config.php');
$path = app_path('Modules/' . $this->moduleName . '/Config/config.php');
$this->mergeConfigFrom(
$path, strtolower($this->moduleName)
$path,
strtolower($this->moduleName)
);
}
protected function registerLivewire()
{
//Livewire::component('<name>', \Modules\<NAME>\Http\Livewire\<NAME>::class);
Livewire::component('citymanagerinfo', \Modules\CityManager\Http\Livewire\CityManagerInfo::class);
}
protected function registerComponent()

View File

@ -0,0 +1,12 @@
<div>
@if ($manager)
<div>Ваш менеджер:</div>
<div class="fw-bold text-uppercase text-primary">
{{ $manager->name }}
</div>
<div class="hstack gap-3 fs-6">
<span><i class="bi bi-telephone-fill"></i> {{ $manager->phone }}</span>
<span><i class="bi bi-envelope-fill"></i> {{ $manager->email }}</span>
</div>
@endif
</div>

View File

@ -20,6 +20,22 @@ function AdminCompanyOfUser()
}
}
if (!function_exists(function: 'AgentCompanyOfUser'))
{
function AgentCompanyOfUser()
{
$city = false;
if ($adminAccount = Agent::where('user_id', auth()->user()->id)->first())
{
return $adminAccount->company;
}
else
{
return false;
}
}
}
if (!function_exists('GetAvailableAgents'))
{
function GetAvailableAgents()

View File

@ -5,6 +5,7 @@
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Modules\Payment\Traits\Paymentable;
use Modules\Main\Models\City;
class Company extends Model
{
use HasFactory;
@ -30,4 +31,9 @@ class Company extends Model
'details' => 'array',
'type' => CompanyType::class
];
public function city()
{
return $this->belongsTo(City::class);
}
}

View File

@ -8,13 +8,43 @@
use Modules\Contracts\Models\ContractStatus;
use Modules\User\Models\UserRole;
use Modules\User\Models\Role;
use Modules\User\Models\User;
use Modules\Main\Models\Company\CompanyAdmin;
class UserSelectorLivewire extends Component
{
public $search;
public $id;
public $name;
public $query;
public $users;
public function mount()
{
$this->query = '';
$this->users = [];
}
public function clearSearch()
{
$this->query = '';
}
public function setUser($id)
{
$user = User::find($id);
$this->id = $id;
$this->name = $user->name;
}
public function unsetUser()
{
unset($this->id);
unset($this->name);
$this->query = '';
}
public function render()
{
if ($this->query)
{
$users = User::where('name', 'like', '%' . $this->query . '%')->take(10)->get();
$this->users = $users->toArray();
}
return view('user::livewire.search.selector');
}
}

View File

@ -1,22 +1,67 @@
<div>
<div class="position-relative">
<div class="position-relative">
<div class="position-absolute top-20" style="left: 10px;top:20%">
<i class="bi bi-search"></i>
</div>
<input type="text" wire:model.blur="search" class="form-control py-2" placeholder="Поиск пользователя..."
autocomplete="false" style="padding-right: 40px; padding-left: 35px;">
<div class="position-absolute" style="right: 10px;top:20%">
<button wire:click="clearSearch" class="btn-close" type="button"></button>
</div>
</div>
<div class="position-absolute w-100 z-3">
<div class="border rounded shadow bg-light-subtle" style="width: inherit;">
<div class="d-grid justify-content-center align-item-center p-3">
<i class="bi bi-person fs-2 text-center"></i>
<p class="mb-0 fs-6 fw-semibold">Пользователь не найден</p>
@if ($id && $name)
<div class="position-relative">
<div class="d-flex flex-wrap align-items-center text-muted gap-2">
<a
class="w-100 d-flex flex-row align-items-center justify-content-between gap-2 badge bg-secondary-subtle text-secondary-emphasis border border-secondary-subtle rounded text-decoration-none py-2 px-2">
<div class="d-flex align-items-center gap-3">
<div class="d-grid align-items-center">
<span class="fw-bold fs-6 text-ellipsis">
{{ $name }}
</span>
</div>
</div>
<button wire:click="unsetUser" class="btn-close" type="button"></button>
<input type="text" name="user_id" class="d-none form-control" aria-label="User name"
value="{{ $id }}">
</a>
</div>
</div>
</div>
@else
<div class="position-relative">
<div class="position-absolute top-20" style="left: 10px;top:20%">
<i class="bi bi-search"></i>
</div>
<input type="text" wire:model.live="query" class="form-control py-2"
placeholder="Поиск пользователя..." autocomplete="false"
style="padding-right: 40px; padding-left: 35px;">
@if ($query)
<div class="position-absolute" style="right: 10px;top:20%">
<button wire:click="clearSearch" class="btn-close" type="button"></button>
</div>
@endif
</div>
@if ($query && count($users) == 0)
<div class="position-absolute w-100 z-3">
<div class="border rounded shadow bg-light-subtle" style="width: inherit;">
<div class="d-grid justify-content-center align-item-center p-3">
<i class="bi bi-person fs-2 text-center"></i>
<p class="mb-0 fs-6 fw-semibold">Пользователь не найден</p>
</div>
</div>
</div>
@endif
@if ($query && count($users) > 0)
<div wire:replace class="position-absolute w-100 z-3">
<div class="border rounded shadow bg-light-subtle" style="width: inherit;">
<ul class="list-unstyled mb-0 px-2 py-2 overflow-y-auto box-custom-dropdown-user-selector"
style="">
@foreach ($users as $user)
<li>
<a type="button"
class="dropdown-item d-flex align-items-center gap-2 py-2 px-2 bg-secondary-soft-hover rounded-2 user-item"
wire:click="setUser({{ $user['id'] }})">
<span class="text-wrap fw-semibold">
{{ $user['name'] }}
</span>
</a>
</li>
@endforeach
</ul>
</div>
</div>
@endif
@endif
</div>
</div>

View File

@ -33,54 +33,48 @@
{{ $title }}
@endisset
</div>
<div class="col-auto col-sm-2">
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="{{ __('Toggle navigation') }}">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<!-- Left Side Of Navbar -->
<ul class="navbar-nav me-auto">
<ul class="navbar-nav me-auto">
</ul>
</ul>
<!-- Right Side Of Navbar -->
<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>
<img src="../../images/icons/user.png" class="img-fluid align-middle"
style="height: 40px;">
</a>
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="/profile">
Профиль
</a>
<a class="dropdown-item" href="{{ route('logout') }}"
onclick="event.preventDefault();
document.getElementById('logout-form').submit();">
Выйти
</a>
<hr class="dropdown-divider">
<a class="dropdown-item" href="#" data-bs-toggle="modal"
data-bs-target="#helpDeleteContract">
<i class="bi bi-question-diamond"></i> Помощь
</a>
<form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none">
@csrf
</form>
</div>
</li>
</ul>
<!-- Right Side Of Navbar -->
<ul class="navbar-nav align-items-center ms-auto">
<div class="nav-item">
@livewire('citymanagerinfo')
</div>
</div>
<div class="vr mx-3 d-none d-md-block"></div>
<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>
<img src="../../images/icons/user.png" class="img-fluid align-middle" style="height: 40px;">
</a>
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="/profile">
Профиль
</a>
<a class="dropdown-item" href="{{ route('logout') }}"
onclick="event.preventDefault();
document.getElementById('logout-form').submit();">
Выйти
</a>
<hr class="dropdown-divider">
<a class="dropdown-item" href="#" data-bs-toggle="modal"
data-bs-target="#helpDeleteContract">
<i class="bi bi-question-diamond"></i> Помощь
</a>
<form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none">
@csrf
</form>
</div>
</li>
</ul>
</div>
</nav>