Add rank management feature with CRUD and UI
Introduces a new rank management system including the Rank model, migrations for the ranks table and user IP address, Livewire components for managing and displaying ranks, and related Blade views. Updates navigation and routes to include the new 'Gestión Rangos' section, and enhances the ShareCodeComponent with user data. Also adds a reusable input field component for forms.
This commit is contained in:
@@ -42,6 +42,10 @@ class MenuController extends Controller
|
||||
{
|
||||
return view('menu/tarifas');
|
||||
}
|
||||
public function showgestionrangos()
|
||||
{
|
||||
return view('menu/gestion-rangos');
|
||||
}
|
||||
public function showclientes()
|
||||
{
|
||||
return view('menu/clientes');
|
||||
|
||||
@@ -7,6 +7,13 @@ use Livewire\Component;
|
||||
|
||||
class ShareCodeComponent extends Component
|
||||
{
|
||||
public $user;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->user = Auth::user();
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
$referrals = Auth::user()->children()
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire;
|
||||
|
||||
use App\Models\Rank;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithFileUploads;
|
||||
|
||||
class ShowGestionRangos extends Component
|
||||
{
|
||||
use WithFileUploads;
|
||||
|
||||
public $ranks;
|
||||
public $nombre, $cashback, $bono_equipo, $tope_bono_equipo;
|
||||
public $compra_personal_min, $directos_activos_min, $niveles_min, $volumen_equipo_min, $volumen_por_nivel_min;
|
||||
public $rank_id;
|
||||
|
||||
public $logo;
|
||||
public $logo_url;
|
||||
|
||||
public $modal = false;
|
||||
|
||||
protected $rules = [
|
||||
'nombre' => 'required|string|max:100',
|
||||
'cashback' => 'required|numeric|min:0',
|
||||
'bono_equipo' => 'required|numeric|min:0',
|
||||
'tope_bono_equipo' => 'required|numeric|min:0',
|
||||
'compra_personal_min' => 'required|numeric|min:0',
|
||||
'directos_activos_min' => 'required|integer|min:0',
|
||||
'niveles_min' => 'required|integer|min:0',
|
||||
'volumen_equipo_min' => 'required|numeric|min:0',
|
||||
'volumen_por_nivel_min' => 'required|numeric|min:0',
|
||||
'logo' => 'nullable|image|max:2048',
|
||||
];
|
||||
|
||||
protected $messages = [
|
||||
'nombre.required' => 'El nombre del rango es obligatorio.',
|
||||
'nombre.string' => 'El nombre debe ser una cadena de texto válida.',
|
||||
'nombre.max' => 'El nombre no puede tener más de 100 caracteres.',
|
||||
|
||||
'cashback.required' => 'El porcentaje de cashback es obligatorio.',
|
||||
'cashback.numeric' => 'El cashback debe ser un valor numérico.',
|
||||
'cashback.min' => 'El cashback no puede ser menor a 0.',
|
||||
|
||||
'bono_equipo.required' => 'El porcentaje de bono de equipo es obligatorio.',
|
||||
'bono_equipo.numeric' => 'El bono de equipo debe ser un valor numérico.',
|
||||
'bono_equipo.min' => 'El bono de equipo no puede ser menor a 0.',
|
||||
|
||||
'tope_bono_equipo.required' => 'El tope del bono de equipo es obligatorio.',
|
||||
'tope_bono_equipo.numeric' => 'El tope del bono de equipo debe ser un valor numérico.',
|
||||
'tope_bono_equipo.min' => 'El tope del bono de equipo no puede ser menor a 0.',
|
||||
|
||||
'compra_personal_min.required' => 'La compra personal mínima es obligatoria.',
|
||||
'compra_personal_min.numeric' => 'La compra personal mínima debe ser un número.',
|
||||
'compra_personal_min.min' => 'La compra personal mínima no puede ser menor a 0.',
|
||||
|
||||
'directos_activos_min.required' => 'El número de directos activos mínimos es obligatorio.',
|
||||
'directos_activos_min.integer' => 'Los directos activos deben ser un número entero.',
|
||||
'directos_activos_min.min' => 'Los directos activos no pueden ser menores a 0.',
|
||||
|
||||
'niveles_min.required' => 'El número de niveles mínimos es obligatorio.',
|
||||
'niveles_min.integer' => 'Los niveles mínimos deben ser un número entero.',
|
||||
'niveles_min.min' => 'Los niveles mínimos no pueden ser menores a 0.',
|
||||
|
||||
'volumen_equipo_min.required' => 'El volumen mínimo de equipo es obligatorio.',
|
||||
'volumen_equipo_min.numeric' => 'El volumen mínimo de equipo debe ser un número.',
|
||||
'volumen_equipo_min.min' => 'El volumen mínimo de equipo no puede ser menor a 0.',
|
||||
|
||||
'volumen_por_nivel_min.required' => 'El volumen por nivel mínimo es obligatorio.',
|
||||
'volumen_por_nivel_min.numeric' => 'El volumen por nivel mínimo debe ser un número.',
|
||||
'volumen_por_nivel_min.min' => 'El volumen por nivel mínimo no puede ser menor a 0.',
|
||||
|
||||
'logo.image' => 'El archivo del logo debe ser una imagen válida (JPG, PNG, etc.).',
|
||||
'logo.max' => 'El logo no puede superar los 2 MB.',
|
||||
];
|
||||
|
||||
public function render()
|
||||
{
|
||||
$this->ranks = Rank::orderBy('volumen_equipo_min')->get();
|
||||
|
||||
return view('livewire.show-gestion-rangos');
|
||||
}
|
||||
|
||||
public function crear()
|
||||
{
|
||||
$this->resetExcept('ranks');
|
||||
$this->modal = true;
|
||||
}
|
||||
|
||||
public function editar($id)
|
||||
{
|
||||
$rank = Rank::findOrFail($id);
|
||||
$this->fill($rank->toArray());
|
||||
$this->rank_id = $rank->id;
|
||||
$this->modal = true;
|
||||
}
|
||||
|
||||
public function guardar()
|
||||
{
|
||||
$this->validate();
|
||||
|
||||
$rutaLogo = null;
|
||||
|
||||
if ($this->logo) {
|
||||
$rutaLogo = $this->logo->store('photos');
|
||||
}
|
||||
|
||||
Rank::updateOrCreate(
|
||||
['id' => $this->rank_id],
|
||||
[
|
||||
'nombre' => $this->nombre,
|
||||
'cashback' => $this->cashback,
|
||||
'bono_equipo' => $this->bono_equipo,
|
||||
'tope_bono_equipo' => $this->tope_bono_equipo,
|
||||
'compra_personal_min' => $this->compra_personal_min,
|
||||
'directos_activos_min' => $this->directos_activos_min,
|
||||
'niveles_min' => $this->niveles_min,
|
||||
'volumen_equipo_min' => $this->volumen_equipo_min,
|
||||
'volumen_por_nivel_min' => $this->volumen_por_nivel_min,
|
||||
'logo' => $rutaLogo ?? $this->logo_url,
|
||||
]
|
||||
);
|
||||
|
||||
$this->modal = false;
|
||||
$this->resetExcept('ranks');
|
||||
}
|
||||
|
||||
public function eliminar($id)
|
||||
{
|
||||
Rank::findOrFail($id)->delete();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire;
|
||||
|
||||
use Livewire\Component;
|
||||
|
||||
class ShowRangos extends Component
|
||||
{
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.show-rangos');
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class ShowSavingIp extends Component
|
||||
{
|
||||
public $ip_address;
|
||||
public $ip_address;
|
||||
|
||||
protected $listeners = ['setIpAddress'];
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Rank extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'nombre',
|
||||
'cashback',
|
||||
'bono_equipo',
|
||||
'tope_bono_equipo',
|
||||
'compra_personal_min',
|
||||
'directos_activos_min',
|
||||
'niveles_min',
|
||||
'volumen_equipo_min',
|
||||
'volumen_por_nivel_min',
|
||||
'logo'
|
||||
];
|
||||
|
||||
public function users()
|
||||
{
|
||||
return $this->hasMany(User::class, 'rank_id');
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -23,11 +23,11 @@ class User extends Authenticatable
|
||||
'rol_id',
|
||||
'subvendedor_id',
|
||||
'subvendedor',
|
||||
'ip_address',
|
||||
|
||||
'referral_code',
|
||||
'parent_id',
|
||||
|
||||
|
||||
'rank_id',
|
||||
];
|
||||
|
||||
@@ -126,10 +126,10 @@ class User extends Authenticatable
|
||||
return $this->hasMany(User::class, 'parent_id')->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
// public function rank()
|
||||
// {
|
||||
// return $this->belongsTo(Rank::class);
|
||||
// }
|
||||
public function rank()
|
||||
{
|
||||
return $this->belongsTo(Rank::class, 'rank_id');
|
||||
}
|
||||
|
||||
protected static function boot()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\View\Components;
|
||||
|
||||
use Illuminate\View\Component;
|
||||
|
||||
class InputField extends Component
|
||||
{
|
||||
public $label;
|
||||
public $model;
|
||||
public $type;
|
||||
public $step;
|
||||
|
||||
public function __construct($label, $model, $type = 'text', $step = null)
|
||||
{
|
||||
$this->label = $label;
|
||||
$this->model = $model;
|
||||
$this->type = $type;
|
||||
$this->step = $step;
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('components.input-field');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user