company agents admin interface updated

This commit is contained in:
Thekindbull 2024-12-15 02:45:17 +08:00
parent 0740b4c9fd
commit d6eccdfe6e
23 changed files with 562 additions and 164 deletions

View File

@ -4,7 +4,7 @@
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\User; use App\Models\User;
use App\Models\Agent; use App\Models\Agent\Agent;
use App\Models\Company\Company; use App\Models\Company\Company;
use Illuminate\Foundation\Auth\RegistersUsers; use Illuminate\Foundation\Auth\RegistersUsers;
@ -12,7 +12,7 @@
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
class RegisterController extends Controller class RegisterController extends Controller
{ {
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Register Controller | Register Controller
@ -39,9 +39,9 @@ class RegisterController extends Controller
* @return void * @return void
*/ */
public function __construct() public function __construct()
{ {
$this->middleware('guest'); $this->middleware('guest');
} }
/** /**
* Get a validator for an incoming registration request. * Get a validator for an incoming registration request.
@ -50,7 +50,7 @@ public function __construct()
* @return \Illuminate\Contracts\Validation\Validator * @return \Illuminate\Contracts\Validation\Validator
*/ */
protected function validator(array $data) protected function validator(array $data)
{ {
return Validator::make($data, [ return Validator::make($data, [
'name' => ['required', 'string', 'max:255'], 'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
@ -58,7 +58,7 @@ protected function validator(array $data)
'password' => ['required', 'string', 'min:8', 'confirmed'], 'password' => ['required', 'string', 'min:8', 'confirmed'],
'inn' => ['required', 'unique:companies'] 'inn' => ['required', 'unique:companies']
]); ]);
} }
/** /**
* Create a new user instance after a valid registration. * Create a new user instance after a valid registration.
@ -67,8 +67,8 @@ protected function validator(array $data)
* @return \App\Models\User * @return \App\Models\User
*/ */
protected function create(array $data) protected function create(array $data)
{ {
$user = User::create([ $user = User::create([
'name' => $data['name'], 'name' => $data['name'],
'email' => $data['email'], 'email' => $data['email'],
'phone' => $data['phone'], 'phone' => $data['phone'],
@ -88,7 +88,7 @@ protected function create(array $data)
'user_id' => $user->id, 'user_id' => $user->id,
'company_id' => $company->id 'company_id' => $company->id
]); ]);
return $user; return $user;
}
} }
}

View File

@ -5,20 +5,22 @@
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\Models\Deal; use App\Models\Deal;
use App\Models\Agent; use App\Models\Agent\Agent;
use App\Models\City; use App\Models\City;
class ClientsTableController extends Controller class ClientsTableController extends Controller
{ {
public function index(Request $request) { public function index(Request $request)
{
$user = auth()->user(); $user = auth()->user();
$agent = Agent::where('user_id', $user->id)->first(); $agent = Agent::where('user_id', $user->id)->first();
return view( return view(
'clients.table', [ 'clients.table',
'deals' => $agent->deals, [
'status' => $request->status, 'deals' => $agent->deals,
'cities' => City::all() 'status' => $request->status,
'cities' => City::all()
] ]
); );
}
} }
}

View File

@ -4,21 +4,40 @@
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\Models\Agent; use App\Models\Agent\Agent;
use App\Models\Agent\AgentStatus;
use App\Models\Company\CompanyAdmin; use App\Models\Company\CompanyAdmin;
use App\Models\City;
class AgentsTableController extends Controller class AgentsTableController extends Controller
{ {
public function index() { public function index(Request $request)
{
$user = auth()->user(); $user = auth()->user();
$admin = CompanyAdmin::where('user_id', $user->id); $admin = CompanyAdmin::where('user_id', $user->id);
if ($admin->count()) { if ($admin->count())
{
$admin = $admin->first(); $admin = $admin->first();
$agents = Agent::where('company_id', $admin->company_id);
switch ( $request->status )
{
case AgentStatus::DISMISSED:
$agents->whereNotNull('deleted_at');
break;
default:
$agents->withTrashed();
}
return view('company.agents.table', [ return view('company.agents.table', [
'agents' => Agent::where('company_id', $admin->company_id)->get() 'agents' => $agents->get(),
]); 'status' => $request->status,
} else { 'cities' => City::all()
])->with('statuses', AgentStatus::class);
}
else
{
echo 'has no permissions'; echo 'has no permissions';
return; return;
}
} }
} }
}

View File

@ -4,35 +4,42 @@
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Auth\Events\Registered; use Illuminate\Foundation\Auth\RegistersUsers;
use App\Models\Company\Company; use App\Models\Company\Company;
use App\Models\Company\CompanyAdmin; use App\Models\Company\CompanyAdmin;
use App\Models\User; use App\Models\User;
class ConfirmCompanyController extends Controller class ConfirmCompanyController extends Controller
{
public function __invoke(Request $request)
{ {
use RegistersUsers;
public function __invoke(Request $request)
{
$company = Company::find($request->company_id); $company = Company::find($request->company_id);
if ($company->secret == $request->secret) { if ($company->secret == $request->secret)
{
$company->status = $request->status; $company->status = $request->status;
$company->save(); $company->save();
$user = User::where('email', $company->email); $user = User::where('email', $company->email);
if ($user->count() == 1) { if ($user->count() == 1)
{
$user = $user->first(); $user = $user->first();
} else { }
else
{
$user = User::create([ $user = User::create([
'name' => $request->user_name, 'name' => $request->user_name,
'email' => $company->email, 'email' => $company->email,
'phone' => $request->user_phone, 'phone' => $request->user_phone,
'password' => uniqid(), 'password' => uniqid(),
]); ]);
} }
CompanyAdmin::create([ CompanyAdmin::create([
'user_id' => $user->id, 'user_id' => $user->id,
'company_id' => $company->id 'company_id' => $company->id
]); ]);
}; return true;
} }
} return false;
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace App\Livewire;
use Livewire\Component;
use Livewire\WithPagination;
use Livewire\WithoutUrlPagination;
use App\Models\Company\CompanyAdmin;
use App\Models\Agent\Agent;
use App\Models\Agent\AgentStatus;
use App\Models\Deal;
class AgentsTable extends Component
{
use WithPagination;
public $status;
public function mount($status = null)
{
$this->status = $status;
}
public function render()
{
$user = auth()->user();
$admin = CompanyAdmin::where('user_id', $user->id)->first();
$agents = Agent::where('company_id', $admin->company_id);
if ($this->status == AgentStatus::DISMISSED)
{
$agents->whereNotNull('deleted_at');
}
return view(
'livewire.agents-table',
[
'agents' => $agents->paginate(10)
]
);
}
}

View File

@ -6,32 +6,38 @@
use Livewire\WithPagination; use Livewire\WithPagination;
use Livewire\WithoutUrlPagination; use Livewire\WithoutUrlPagination;
use App\Models\Agent; use App\Models\Agent\Agent;
use App\Models\Deal; use App\Models\Deal;
class ClientsTable extends Component class ClientsTable extends Component
{ {
use WithPagination; use WithPagination;
public $status; public $status;
public function mount($status = null) { public function mount($status = null)
{
$this->status = $status; $this->status = $status;
} }
public function render() public function render()
{ {
$user = auth()->user(); $user = auth()->user();
$agent = Agent::where('user_id', $user->id)->first(); $agent = Agent::where('user_id', $user->id)->first();
$deals = []; $deals = [];
if ($this->status && $this->status=='UNIQUE') { if ($this->status && $this->status == 'UNIQUE')
{
$deals = Deal::where('agent_id', $agent->id)->where('status', $this->status)->paginate(8); $deals = Deal::where('agent_id', $agent->id)->where('status', $this->status)->paginate(8);
} else { }
else
{
$deals = Deal::where('agent_id', $agent->id)->paginate(8); $deals = Deal::where('agent_id', $agent->id)->paginate(8);
}; }
;
return view( return view(
'livewire.clients-table', [ 'livewire.clients-table',
'deals' => $deals [
'deals' => $deals
] ]
); );
}
} }
}

View File

@ -7,12 +7,12 @@
use App\Models\Deal; use App\Models\Deal;
use App\Models\Complex; use App\Models\Complex;
use App\Models\Status; use App\Models\Status;
use App\Models\Agent; use App\Models\Agent\Agent;
use App\Models\Bitrix\SendClient; use App\Models\Bitrix\SendClient;
class CreateClientForm extends Component class CreateClientForm extends Component
{ {
const NEW = 1; const NEW = 1;
const ERROR = 2; const ERROR = 2;
const SUCCESS = 3; const SUCCESS = 3;
@ -28,14 +28,16 @@ class CreateClientForm extends Component
'client.phone.regex' => 'Телефон должен содержать 10 симвлов без указания кода страны "+7" или "8"', 'client.phone.regex' => 'Телефон должен содержать 10 симвлов без указания кода страны "+7" или "8"',
'client.phone.unique' => 'Клиент с таким телефоном уже существует' 'client.phone.unique' => 'Клиент с таким телефоном уже существует'
]; ];
protected function rules() { protected function rules()
{
return [ return [
'client.firstName' => ['required', 'string', 'max:255'], 'client.firstName' => ['required', 'string', 'max:255'],
'client.secondName' => ['required', 'string', 'max:255'], 'client.secondName' => ['required', 'string', 'max:255'],
'client.phone' => ['required', 'string', 'regex:/\(?([0-9]{3})\)([-]{1})([0-9]{3})([-]{1})([0-9]{4})/i'] 'client.phone' => ['required', 'string', 'regex:/\(?([0-9]{3})\)([-]{1})([0-9]{3})([-]{1})([0-9]{4})/i']
]; ];
} }
public function mount() { public function mount()
{
$userBroker = Agent::where('user_id', auth()->user()->id)->first(); $userBroker = Agent::where('user_id', auth()->user()->id)->first();
$this->complexes = Complex::all(); $this->complexes = Complex::all();
$this->client = [ $this->client = [
@ -45,82 +47,104 @@ public function mount() {
'complexId' => '' 'complexId' => ''
]; ];
$this->status = self::NEW; $this->status = self::NEW;
} }
public function update() { public function update()
} {
}
public function updated($propertyName) public function updated($propertyName)
{ {
$this->status = self::NEW; $this->status = self::NEW;
if ($propertyName == 'client.phone') { if ($propertyName == 'client.phone')
{
$phone = preg_replace('/[^0-9]/', "", $this->client['phone']); $phone = preg_replace('/[^0-9]/', "", $this->client['phone']);
if (strlen($phone) == 10) if (strlen($phone) == 10)
{ {
$sArea = substr($phone, 0, 3); $sArea = substr($phone, 0, 3);
$sPrefix = substr($phone, 3, 3); $sPrefix = substr($phone, 3, 3);
$sNumber = substr($phone, 6, 4); $sNumber = substr($phone, 6, 4);
$phone = "(" . $sArea . ")-" . $sPrefix . "-" . $sNumber; $phone = "(" . $sArea . ")-" . $sPrefix . "-" . $sNumber;
$this->client['phone'] = $phone; $this->client['phone'] = $phone;
} elseif (strlen($this->client['phone']) == 1) {
if ($this->client['phone'] == "8" || $this->client['phone'] == "7" || $this->client['phone'] == "+") {
$this->client['phone'] = null;
} else {
$this->client['phone'] = $phone;
} }
} else { elseif (strlen($this->client['phone']) == 1)
{
if ($this->client['phone'] == "8" || $this->client['phone'] == "7" || $this->client['phone'] == "+")
{
$this->client['phone'] = null;
}
else
{
$this->client['phone'] = $phone;
}
}
else
{
$this->client['phone'] = $phone; $this->client['phone'] = $phone;
}
} }
}
$this->validateOnly($propertyName); $this->validateOnly($propertyName);
} }
public function render() public function render()
{ {
if ($this->client['firstName'] if (
$this->client['firstName']
&& $this->client['secondName'] && $this->client['secondName']
&& $this->client['phone'] && $this->client['phone']
&& $this->client['complexId'] && $this->client['complexId']
&& $this->status == self::NEW && $this->status == self::NEW
) { )
{
$this->status = self::READY; $this->status = self::READY;
} }
return view('livewire.create-client-form'); return view('livewire.create-client-form');
} }
public function resetData() { public function resetData()
{
$this->mount(); $this->mount();
} }
public function back() { public function back()
{
$this->status = self::NEW; $this->status = self::NEW;
} }
public function save() { public function save()
{
$validated = $this->validate($this->rules()); $validated = $this->validate($this->rules());
$agent = Agent::where('user_id', auth()->user()->id)->first(); $agent = Agent::where('user_id', auth()->user()->id)->first();
$phone = '+7' . $this->client['phone']; $phone = '+7' . $this->client['phone'];
$newUser = User::updateOrCreate( $newUser = User::updateOrCreate(
['phone' => $phone], ['phone' => $phone],
[ [
'name' => trim($this->client['firstName'] . ' ' . $this->client['secondName']) 'name' => trim($this->client['firstName'] . ' ' . $this->client['secondName']),
, 'phone' => $phone 'phone' => $phone
]); ]
);
$data = [ $data = [
'agent_id' => $agent->id 'agent_id' => $agent->id
, 'client_id' => $newUser->id ,
, 'complex_id' => $this->client['complexId'] 'client_id' => $newUser->id
,
'complex_id' => $this->client['complexId']
]; ];
$data['confirm_token'] = $this->client['confirmToken'] = hash('sha256', json_encode($data)); $data['confirm_token'] = $this->client['confirmToken'] = hash('sha256', json_encode($data));
if ($newDeal = Deal::create($data)) { if ($newDeal = Deal::create($data))
if ($bitrixId = $this->sendToBitrix($newDeal->id)) { {
if ($bitrixId = $this->sendToBitrix($newDeal->id))
{
$newDeal->bitrix_id = $bitrixId; $newDeal->bitrix_id = $bitrixId;
$newDeal->status = 'MODERATION'; $newDeal->status = 'MODERATION';
$newDeal->save(); $newDeal->save();
$this->result = $bitrixId; $this->result = $bitrixId;
return $this->status = self::SUCCESS; return $this->status = self::SUCCESS;
} else { }
else
{
$newDeal->delete(); $newDeal->delete();
}
} }
}
return $this->status = self::ERROR; return $this->status = self::ERROR;
} }
public function sendToBitrix($id) { public function sendToBitrix($id)
{
$user = auth()->user(); $user = auth()->user();
$agent = Agent::where('user_id', $user->id)->first(); $agent = Agent::where('user_id', $user->id)->first();
$agentName = $agent->user->getPartialsName(); $agentName = $agent->user->getPartialsName();
@ -137,10 +161,13 @@ public function sendToBitrix($id) {
]; ];
$sender = new SendClient($id, $data); $sender = new SendClient($id, $data);
$response = $sender->send(); $response = $sender->send();
if ($response) { if ($response)
{
return $response; return $response;
} else { }
else
{
return false; return false;
}
} }
} }
}

View File

@ -1,29 +1,37 @@
<?php <?php
namespace App\Models; namespace App\Models\Agent;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Models\Company;
use App\Models\Company\Company;
use App\Models\User; use App\Models\User;
use App\Models\Deal; use App\Models\Deal;
class Agent extends Model class Agent extends Model
{ {
use HasFactory; use HasFactory;
use SoftDeletes;
public const STATUS_ACTIVE = "ACTIVE";
public const STATUS_DISMISSED = "DISMISSED";
protected $fillable = [ protected $fillable = [
'user_id', 'user_id',
'company_id' 'company_id'
]; ];
public function company() { public function company()
{
return $this->belongsTo(Company::class); return $this->belongsTo(Company::class);
} }
public function user() { public function user()
{
return $this->belongsTo(User::class); return $this->belongsTo(User::class);
} }
public function deals() { public function deals()
{
return $this->hasMany(Deal::class); return $this->hasMany(Deal::class);
}
} }
}

View File

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

View File

@ -1,8 +1,6 @@
<?php <?php
namespace App\Models\Bitrix; namespace App\Models\Bitrix;
use App\Models\Company;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
class BitrixSender class BitrixSender

View File

@ -7,11 +7,11 @@
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
class SendCompany class SendCompany
{ {
private $IBLOCK_TYPE_ID = 'rest_entity'; private $IBLOCK_TYPE_ID = 'rest_entity';
//CONFIG для Альфы //CONFIG для Альфы
private $URL = 'https://b24alfa.pro/rest/3165/v90a792nderzu0dj/lists.element.add.json'; private $URL = 'https://b24alfa.pro/rest/3165/v90a792nderzu0dj/lists.element.add.json';
private $IBLOCK_ID = 24; private $IBLOCK_ID = 24;
private $ID; private $ID;
@ -23,42 +23,47 @@ class SendCompany
const CALLBACK_URL = "PROPERTY_122"; const CALLBACK_URL = "PROPERTY_122";
private $data = []; private $data = [];
public function __construct(Company $company) { public function __construct(Company $company)
{
$this->ID = $company->id; $this->ID = $company->id;
$data = array_change_key_case($company->attributesToArray(), CASE_UPPER); $data = array_change_key_case($company->attributesToArray(), CASE_UPPER);
$finalData = $this->castConstants($data); $finalData = $this->castConstants($data);
$finalData[self::CALLBACK_URL] = route('company.status.update', [ $finalData[self::CALLBACK_URL] = route('company.status.update', [
'company' => $this->ID 'company' => $this->ID,
'secret' => $company->secret
]); ]);
$this->data = $finalData; $this->data = $finalData;
return; return;
} }
private function castConstants($data) { private function castConstants($data)
{
$finalData = []; $finalData = [];
$refl = new \ReflectionClass(__CLASS__); $refl = new \ReflectionClass(__CLASS__);
$constants = $refl->getConstants(); $constants = $refl->getConstants();
foreach ( $constants as $constName => $constValue ) foreach ($constants as $constName => $constValue)
{
foreach ($data as $key => $value)
{ {
if ( $constName == $key ) { foreach ($data as $key => $value)
{
if ($constName == $key)
{
$finalData[$constValue] = $value; $finalData[$constValue] = $value;
break; break;
}
} }
} }
}
return $finalData; return $finalData;
} }
public function send() { public function send()
{
$data = [ $data = [
'IBLOCK_TYPE_ID' => $this->IBLOCK_TYPE_ID, 'IBLOCK_TYPE_ID' => $this->IBLOCK_TYPE_ID,
'IBLOCK_ID' => $this->IBLOCK_ID, 'IBLOCK_ID' => $this->IBLOCK_ID,
'ELEMENT_CODE' => $this->ID, 'ELEMENT_CODE' => $this->ID,
'FIELDS' => $this->data, 'FIELDS' => $this->data,
'PROPERTY_VALUES' => $this->data 'PROPERTY_VALUES' => $this->data
]; ];
$sender = new BitrixSender($this->URL, $data); $sender = new BitrixSender($this->URL, $data);
$sender->send(); $sender->send();
}
} }
}

View File

@ -83,7 +83,7 @@
| |
*/ */
'locale' => 'en', 'locale' => 'ru',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------

View File

@ -36,7 +36,7 @@
'mailers' => [ 'mailers' => [
'smtp' => [ 'smtp' => [
'transport' => 'smtp', 'transport' => 'smtp',
'url' => env('MAIL_URL'), //'url' => env('MAIL_URL'),
'host' => env('MAIL_HOST', 'smtp.mailgun.org'), 'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
'port' => env('MAIL_PORT', 587), 'port' => env('MAIL_PORT', 587),
'encryption' => env('MAIL_ENCRYPTION', 'tls'), 'encryption' => env('MAIL_ENCRYPTION', 'tls'),

20
lang/en/auth.php Normal file
View File

@ -0,0 +1,20 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used during authentication for various
| messages that we need to display to the user. You are free to modify
| these language lines according to your application's requirements.
|
*/
'failed' => 'These credentials do not match our records.',
'password' => 'The provided password is incorrect.',
'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
];

19
lang/en/pagination.php Normal file
View File

@ -0,0 +1,19 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Pagination Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used by the paginator library to build
| the simple pagination links. You are free to change them to anything
| you want to customize your views to better match your application.
|
*/
'previous' => '&laquo; Previous',
'next' => 'Next &raquo;',
];

22
lang/en/passwords.php Normal file
View File

@ -0,0 +1,22 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Password Reset Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are the default lines which match reasons
| that are given by the password broker for a password update attempt
| has failed, such as for an invalid token or invalid new password.
|
*/
'reset' => 'Your password has been reset.',
'sent' => 'We have emailed your password reset link.',
'throttled' => 'Please wait before retrying.',
'token' => 'This password reset token is invalid.',
'user' => "We can't find a user with that email address.",
];

191
lang/en/validation.php Normal file
View File

@ -0,0 +1,191 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such
| as the size rules. Feel free to tweak each of these messages here.
|
*/
'accepted' => 'The :attribute field must be accepted.',
'accepted_if' => 'The :attribute field must be accepted when :other is :value.',
'active_url' => 'The :attribute field must be a valid URL.',
'after' => 'The :attribute field must be a date after :date.',
'after_or_equal' => 'The :attribute field must be a date after or equal to :date.',
'alpha' => 'The :attribute field must only contain letters.',
'alpha_dash' => 'The :attribute field must only contain letters, numbers, dashes, and underscores.',
'alpha_num' => 'The :attribute field must only contain letters and numbers.',
'array' => 'The :attribute field must be an array.',
'ascii' => 'The :attribute field must only contain single-byte alphanumeric characters and symbols.',
'before' => 'The :attribute field must be a date before :date.',
'before_or_equal' => 'The :attribute field must be a date before or equal to :date.',
'between' => [
'array' => 'The :attribute field must have between :min and :max items.',
'file' => 'The :attribute field must be between :min and :max kilobytes.',
'numeric' => 'The :attribute field must be between :min and :max.',
'string' => 'The :attribute field must be between :min and :max characters.',
],
'boolean' => 'The :attribute field must be true or false.',
'can' => 'The :attribute field contains an unauthorized value.',
'confirmed' => 'The :attribute field confirmation does not match.',
'current_password' => 'The password is incorrect.',
'date' => 'The :attribute field must be a valid date.',
'date_equals' => 'The :attribute field must be a date equal to :date.',
'date_format' => 'The :attribute field must match the format :format.',
'decimal' => 'The :attribute field must have :decimal decimal places.',
'declined' => 'The :attribute field must be declined.',
'declined_if' => 'The :attribute field must be declined when :other is :value.',
'different' => 'The :attribute field and :other must be different.',
'digits' => 'The :attribute field must be :digits digits.',
'digits_between' => 'The :attribute field must be between :min and :max digits.',
'dimensions' => 'The :attribute field has invalid image dimensions.',
'distinct' => 'The :attribute field has a duplicate value.',
'doesnt_end_with' => 'The :attribute field must not end with one of the following: :values.',
'doesnt_start_with' => 'The :attribute field must not start with one of the following: :values.',
'email' => 'The :attribute field must be a valid email address.',
'ends_with' => 'The :attribute field must end with one of the following: :values.',
'enum' => 'The selected :attribute is invalid.',
'exists' => 'The selected :attribute is invalid.',
'extensions' => 'The :attribute field must have one of the following extensions: :values.',
'file' => 'The :attribute field must be a file.',
'filled' => 'The :attribute field must have a value.',
'gt' => [
'array' => 'The :attribute field must have more than :value items.',
'file' => 'The :attribute field must be greater than :value kilobytes.',
'numeric' => 'The :attribute field must be greater than :value.',
'string' => 'The :attribute field must be greater than :value characters.',
],
'gte' => [
'array' => 'The :attribute field must have :value items or more.',
'file' => 'The :attribute field must be greater than or equal to :value kilobytes.',
'numeric' => 'The :attribute field must be greater than or equal to :value.',
'string' => 'The :attribute field must be greater than or equal to :value characters.',
],
'hex_color' => 'The :attribute field must be a valid hexadecimal color.',
'image' => 'The :attribute field must be an image.',
'in' => 'The selected :attribute is invalid.',
'in_array' => 'The :attribute field must exist in :other.',
'integer' => 'The :attribute field must be an integer.',
'ip' => 'The :attribute field must be a valid IP address.',
'ipv4' => 'The :attribute field must be a valid IPv4 address.',
'ipv6' => 'The :attribute field must be a valid IPv6 address.',
'json' => 'The :attribute field must be a valid JSON string.',
'lowercase' => 'The :attribute field must be lowercase.',
'lt' => [
'array' => 'The :attribute field must have less than :value items.',
'file' => 'The :attribute field must be less than :value kilobytes.',
'numeric' => 'The :attribute field must be less than :value.',
'string' => 'The :attribute field must be less than :value characters.',
],
'lte' => [
'array' => 'The :attribute field must not have more than :value items.',
'file' => 'The :attribute field must be less than or equal to :value kilobytes.',
'numeric' => 'The :attribute field must be less than or equal to :value.',
'string' => 'The :attribute field must be less than or equal to :value characters.',
],
'mac_address' => 'The :attribute field must be a valid MAC address.',
'max' => [
'array' => 'The :attribute field must not have more than :max items.',
'file' => 'The :attribute field must not be greater than :max kilobytes.',
'numeric' => 'The :attribute field must not be greater than :max.',
'string' => 'The :attribute field must not be greater than :max characters.',
],
'max_digits' => 'The :attribute field must not have more than :max digits.',
'mimes' => 'The :attribute field must be a file of type: :values.',
'mimetypes' => 'The :attribute field must be a file of type: :values.',
'min' => [
'array' => 'The :attribute field must have at least :min items.',
'file' => 'The :attribute field must be at least :min kilobytes.',
'numeric' => 'The :attribute field must be at least :min.',
'string' => 'The :attribute field must be at least :min characters.',
],
'min_digits' => 'The :attribute field must have at least :min digits.',
'missing' => 'The :attribute field must be missing.',
'missing_if' => 'The :attribute field must be missing when :other is :value.',
'missing_unless' => 'The :attribute field must be missing unless :other is :value.',
'missing_with' => 'The :attribute field must be missing when :values is present.',
'missing_with_all' => 'The :attribute field must be missing when :values are present.',
'multiple_of' => 'The :attribute field must be a multiple of :value.',
'not_in' => 'The selected :attribute is invalid.',
'not_regex' => 'The :attribute field format is invalid.',
'numeric' => 'The :attribute field must be a number.',
'password' => [
'letters' => 'The :attribute field must contain at least one letter.',
'mixed' => 'The :attribute field must contain at least one uppercase and one lowercase letter.',
'numbers' => 'The :attribute field must contain at least one number.',
'symbols' => 'The :attribute field must contain at least one symbol.',
'uncompromised' => 'The given :attribute has appeared in a data leak. Please choose a different :attribute.',
],
'present' => 'The :attribute field must be present.',
'present_if' => 'The :attribute field must be present when :other is :value.',
'present_unless' => 'The :attribute field must be present unless :other is :value.',
'present_with' => 'The :attribute field must be present when :values is present.',
'present_with_all' => 'The :attribute field must be present when :values are present.',
'prohibited' => 'The :attribute field is prohibited.',
'prohibited_if' => 'The :attribute field is prohibited when :other is :value.',
'prohibited_unless' => 'The :attribute field is prohibited unless :other is in :values.',
'prohibits' => 'The :attribute field prohibits :other from being present.',
'regex' => 'The :attribute field format is invalid.',
'required' => 'The :attribute field is required.',
'required_array_keys' => 'The :attribute field must contain entries for: :values.',
'required_if' => 'The :attribute field is required when :other is :value.',
'required_if_accepted' => 'The :attribute field is required when :other is accepted.',
'required_unless' => 'The :attribute field is required unless :other is in :values.',
'required_with' => 'The :attribute field is required when :values is present.',
'required_with_all' => 'The :attribute field is required when :values are present.',
'required_without' => 'The :attribute field is required when :values is not present.',
'required_without_all' => 'The :attribute field is required when none of :values are present.',
'same' => 'The :attribute field must match :other.',
'size' => [
'array' => 'The :attribute field must contain :size items.',
'file' => 'The :attribute field must be :size kilobytes.',
'numeric' => 'The :attribute field must be :size.',
'string' => 'The :attribute field must be :size characters.',
],
'starts_with' => 'The :attribute field must start with one of the following: :values.',
'string' => 'The :attribute field must be a string.',
'timezone' => 'The :attribute field must be a valid timezone.',
'unique' => 'The :attribute has already been taken.',
'uploaded' => 'The :attribute failed to upload.',
'uppercase' => 'The :attribute field must be uppercase.',
'url' => 'The :attribute field must be a valid URL.',
'ulid' => 'The :attribute field must be a valid ULID.',
'uuid' => 'The :attribute field must be a valid UUID.',
/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
|--------------------------------------------------------------------------
|
| Here you may specify custom validation messages for attributes using the
| convention "attribute.rule" to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule.
|
*/
'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
],
],
/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
| The following language lines are used to swap our attribute placeholder
| with something more reader friendly such as "E-Mail Address" instead
| of "email". This simply helps us make our message more expressive.
|
*/
'attributes' => [],
];

3
lang/ru.json Normal file
View File

@ -0,0 +1,3 @@
{
"Login": "Вход на сайт"
}

View File

@ -5,15 +5,14 @@
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-8"> <div class="col-md-8">
<div class="card"> <div class="card">
<div class="card-header">{{ __('Login') }}</div> <div class="card-header">Форма входа</div>
<div class="card-body"> <div class="card-body">
<form method="POST" action="{{ route('login') }}"> <form method="POST" action="{{ route('login') }}">
@csrf @csrf
<div class="row mb-3"> <div class="row mb-3">
<label for="email" <label for="email" class="col-md-4 col-form-label text-md-end">Электронная почта</label>
class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label>
<div class="col-md-6"> <div class="col-md-6">
<input id="email" type="email" <input id="email" type="email"
@ -29,9 +28,7 @@ class="form-control @error('email') is-invalid @enderror" name="email"
</div> </div>
<div class="row mb-3"> <div class="row mb-3">
<label for="password" <label for="password" class="col-md-4 col-form-label text-md-end">Пароль</label>
class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label>
<div class="col-md-6"> <div class="col-md-6">
<input id="password" type="password" <input id="password" type="password"
class="form-control @error('password') is-invalid @enderror" name="password" class="form-control @error('password') is-invalid @enderror" name="password"
@ -52,7 +49,7 @@ class="form-control @error('password') is-invalid @enderror" name="password"
{{ old('remember') ? 'checked' : '' }}> {{ old('remember') ? 'checked' : '' }}>
<label class="form-check-label" for="remember"> <label class="form-check-label" for="remember">
{{ __('Remember Me') }} Запомнить меня
</label> </label>
</div> </div>
</div> </div>
@ -61,12 +58,12 @@ class="form-control @error('password') is-invalid @enderror" name="password"
<div class="row mb-0"> <div class="row mb-0">
<div class="col-md-8 offset-md-4"> <div class="col-md-8 offset-md-4">
<button type="submit" class="btn btn-primary"> <button type="submit" class="btn btn-primary">
{{ __('Login') }} Войти
</button> </button>
@if (Route::has('password.request')) @if (Route::has('password.request'))
<a class="btn btn-link" href="{{ route('password.request') }}"> <a class="btn btn-link" href="{{ route('password.request') }}">
{{ __('Forgot Your Password?') }} Восстановить пароль
</a> </a>
@endif @endif
</div> </div>

View File

@ -2,20 +2,19 @@
@section('content') @section('content')
<div> <div>
<form class="d-flex mb-3" method="GET" action="{{ route('clients.table') }}"> <form class="d-flex mb-3" method="GET" action="{{ route('agents.table') }}">
<div class="p-2 border rounded-3 border-1 p-1 bg-white"> <div class="p-2 border rounded-3 border-1 p-1 bg-white">
<input type="radio" class="btn-check" name="status" value="all" id="option5" autocomplete="off" <input type="radio" class="btn-check" name="status" value="all" id="option5" autocomplete="off"
onclick="this.form.submit()" {{ $status == 'all' ? 'checked' : '' }}> onclick="this.form.submit()" {{ $status == 'all' || !$status ? 'checked' : '' }}>
<label class="btn p-2 fs-5" for="option5">Все</label> <label class="btn p-2 fs-5" for="option5">Все</label>
<input type="radio" class="btn-check" name="status" value="unique" id="option6" autocomplete="off" <input type="radio" class="btn-check" name="status" value="{{ $statuses::ACTIVE }}" id="option6"
onclick="this.form.submit()" {{ $status == 'unique' ? 'checked' : '' }}> autocomplete="off" onclick="this.form.submit()" {{ $status == $statuses::ACTIVE ? 'checked' : '' }}>
<label class="btn p-2 fs-5" for="option6">Уникальные</label> <label class="btn p-2 fs-5" for="option6">Активные</label>
<input type="radio" class="btn-check" name="status" value="not unique" id="option7" autocomplete="off" <input type="radio" class="btn-check" name="status" value="{{ $statuses::DISMISSED }}" id="option7"
onclick="this.form.submit()" {{ $status == 'not unique' ? 'checked' : '' }}> autocomplete="off" onclick="this.form.submit()" {{ $status == $statuses::DISMISSED ? 'checked' : '' }}>
<label class="btn p-2 fs-5" for="option7">Не <label class="btn p-2 fs-5" for="option7">Уволенные</label>
уникальные</label>
</div> </div>
<div class="ms-auto p-2"> <div class="ms-auto p-2">
<select class="form-select form-select-lg" aria-label="Large select example"> <select class="form-select form-select-lg" aria-label="Large select example">
@ -26,17 +25,17 @@
</select> </select>
</div> </div>
</form> </form>
@if (!$status || $status == 'all' || $status == 'unique') @if (!$status || $status == 'all' || $status == $statuses::ACTIVE)
<h4 class="fw-bold mt-5 mb-3">Уникальные</h4> <h4 class="fw-bold mt-5 mb-3">Активные</h4>
<div class="fs-5 bg-light mb-2"> <div class="fs-5 bg-light mb-2">
@livewire('clientsTable', ['status' => 'UNIQUE']) @livewire('agentsTable', ['status' => $statuses::ACTIVE])
</div> </div>
@endif @endif
@if (!$status || $status == 'all' || $status == 'not unique') @if (!$status || $status == 'all' || $status == $statuses::DISMISSED)
<h4 class="fw-bold mt-5 mb-3">Не уникальные</h4> <h4 class="fw-bold mt-5 mb-3">Уволенные</h4>
<div class="fs-5 bg-light mb-2"> <div class="fs-5 bg-light mb-2">
@livewire('clientsTable', ['status' => 'NOT UNIQUE']) @livewire('agentsTable', ['status' => $statuses::DISMISSED])
</div> </div>
@endif @endif
</div> </div>

View File

@ -0,0 +1,27 @@
<div>
<div class="fs-5 bg-light p-0 m-0 border border-1 rounded-4 overflow-hidden">
<table class="table m-0">
<tbody class="">
@foreach ($agents as $agent)
<tr>
<td>
<img src="../../images/icons/user.png" class="img-fluid align-middle" style="height: 50px;">
</td>
<td class="fw-semibold fs-5 align-middle">
{{ $agent->user->name }}
</td>
<td class="align-middle">
{{ $agent->user->phone }}
</td>
<td class="align-middle">
{{ $agent->user->email }}
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<div class="mt-3">
{{ $agents->links('layouts.pagination') }}
</div>
</div>

View File

@ -2,7 +2,6 @@
@section('content') @section('content')
<main class="form-signin w-100 m-auto" style="max-width: 330px;"> <main class="form-signin w-100 m-auto" style="max-width: 330px;">
<a class="btn btn-primary w-100 py-2 mb-2" href="{{ route('login') }}">Войти</a> <a class="btn btn-primary w-100 py-2 mb-2" href="{{ route('login') }}">Войти</a>
<a class="btn btn-secondary w-100 py-2 mb-2" href="{{ route('register') }}">Зарегистрироваться</a> <a class="btn btn-secondary w-100 py-2 mb-2" href="{{ route('register') }}">Зарегистрироваться</a>
<a class="btn btn-secondary w-100 py-2 mb-2" href="{{ route('company.form.create') }}">Создать компанию</a> <a class="btn btn-secondary w-100 py-2 mb-2" href="{{ route('company.form.create') }}">Создать компанию</a>

View File

@ -3,7 +3,7 @@
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
use Illuminate\Foundation\Auth\EmailVerificationRequest; use Illuminate\Foundation\Auth\EmailVerificationRequest;
use App\Http\Controllers\Company\CreateCompanyController; use App\Http\Controllers\Company\CreateCompanyController;
/* /*
@ -17,31 +17,34 @@
| |
*/ */
Route::get('/', function () { Route::get('/', function ()
{
return view(view: 'welcome'); return view(view: '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');
//Company //Company
Route::get('/company/create', function () { Route::get('/company/create', function ()
{
return view(view: 'company.create'); return view(view: 'company.create');
})->name('company.form.create'); })->name('company.form.create');
Route::post('/company/create', CreateCompanyController::class)->name('company.create');
Route::get('/company/confirmer', function () Route::get('/company/confirmer', function ()
{ {
return view(view: 'company.post_confirmer'); return view(view: 'company.post_confirmer');
}); });
Route::post('/company/create', CreateCompanyController::class)->name('company.create'); 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('/company/details/', [App\Http\Controllers\Company\DetailsController::class, 'index'])->name('company.details'); Route::get('/company/details/', [App\Http\Controllers\Company\DetailsController::class, 'index'])->name('company.details');
Route::post('/company/{company}/details/', [App\Http\Controllers\Company\DetailsController::class, 'store'])->name('company.details.store'); Route::post('/company/{company}/details/', [App\Http\Controllers\Company\DetailsController::class, 'store'])->name('company.details.store');
Route::get('/agents/table', [App\Http\Controllers\Company\AgentsTableController::class, 'index'])->name('agents.table'); Route::get('/agents/table', [App\Http\Controllers\Company\AgentsTableController::class, 'index'])->name('agents.table');
});