Prepare modules

This commit is contained in:
2025-03-22 12:41:56 -06:00
parent 04f5e973d7
commit 3916c62935
74 changed files with 4431 additions and 194 deletions

103
Livewire/Faq/FaqIndex.php Normal file
View File

@ -0,0 +1,103 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Livewire\Faq;
use Koneko\VuexyAdmin\Livewire\Table\AbstractIndexComponent;
use Koneko\VuexyWebsiteAdmin\Models\Faq;
class FaqIndex extends AbstractIndexComponent
{
/**
* Retorna la clase del modelo asociado.
*
* @return string
*/
protected function model(): string
{
return Faq::class;
}
/**
* Configura el encabezado (header) de la tabla (las columnas).
*
* @return array
*/
protected function columns(): array
{
return [
'action' => 'Acciones',
'status' => 'Estatus',
'created_at' => 'Fecha de Creación',
'updated_at' => 'Última Actualización',
];
}
/**
* Define los formatos de cada columna (se inyectará en $bt_datatable['format']).
*
* @return array
*/
protected function format(): array
{
return [
'action' => [
'formatter' => 'FaqActionFormatter',
'onlyFormatter' => true,
],
'status' => [
'formatter' => [
'name' => 'dynamicBooleanFormatter',
'params' => ['tag' => 'activo']
],
'align' => 'center',
],
'created_at' => [
'formatter' => 'textNowrapFormatter',
'align' => 'center',
'visible' => false,
],
'updated_at' => [
'formatter' => 'textNowrapFormatter',
'align' => 'center',
'visible' => false,
],
];
}
/**
* Retorna la configuración base (común) para la tabla Bootstrap Table.
*
* @return array
*/
protected function bootstraptableConfig(): array
{
return [
'sortName' => 'code',
'exportFileName' => 'Almacenes',
'showFullscreen' => false,
'showPaginationSwitch' => false,
'showRefresh' => false,
'pagination' => false,
];
}
/**
* Retorna la ruta de la vista Blade.
*
* @return string
*/
protected function viewPath(): string
{
// La vista que ya tienes creada para FaqIndex
return 'vuexy-website-admin::livewire.faq.index';
}
/**
* Métodos que necesites sobreescribir o extender.
*/
public function mount(): void
{
parent::mount();
}
}

View File

@ -0,0 +1,217 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Livewire\Faq;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
use Koneko\VuexyAdmin\Livewire\Form\AbstractFormOffCanvasComponent;
use Koneko\VuexyContacts\Services\ContactCatalogService;
use Koneko\VuexyStoreManager\Services\StoreCatalogService;
use Koneko\VuexyWarehouse\Models\Warehouse;
/**
* Class FaqOffcanvasForm
*
* Componente Livewire para gestionar almacenes.
* Extiende la clase AbstractFormOffCanvasComponent e implementa validaciones dinámicas,
* manejo de formularios, eventos y actualizaciones en tiempo real.
*
* @package Koneko\VuexyWarehouse\Livewire\Warehouses
*/
class FaqOffcanvasForm extends AbstractFormOffCanvasComponent
{
/**
* Propiedades del formulario relacionadas con el almacén.
*/
public $id, $store_id, $work_center_id, $code, $name, $description,
$manager_id, $tel, $tel2, $priority, $status, $confirmDeletion;
/**
* Listas de opciones para selects en el formulario.
*/
public $store_options = [],
$work_center_options = [],
$manager_options = [];
/**
* Eventos de escucha de Livewire.
*
* @var array
*/
protected $listeners = [
'editWarehouse' => 'loadFormModel',
'confirmDeletionWarehouse' => 'loadFormModelForDeletion',
];
/**
* Definición de tipos de datos que se deben castear.
*
* @var array
*/
protected $casts = [
'status' => 'boolean',
];
/**
* Define el modelo Eloquent asociado con el formulario.
*
* @return string
*/
protected function model(): string
{
return Warehouse::class;
}
/**
* Define los campos del formulario.
*
* @return array<string, mixed>
*/
protected function fields(): array
{
return (new Warehouse())->getFillable();
}
/**
* Valores por defecto para el formulario.
*
* @return array
*/
protected function defaults(): array
{
return [
'priority' => 0,
'status' => true,
];
}
/**
* Campo que se debe enfocar cuando se abra el formulario.
*
* @return string
*/
protected function focusOnOpen(): string
{
return 'code';
}
/**
* Define reglas de validación dinámicas basadas en el modo actual.
*
* @param string $mode El modo actual del formulario ('create', 'edit', 'delete').
* @return array
*/
protected function dynamicRules(string $mode): array
{
switch ($mode) {
case 'create':
case 'edit':
return [
'store_id' => ['required', 'integer', 'exists:stores,id'],
'work_center_id' => ['nullable', 'integer', 'exists:store_work_centers,id'],
'code' => ['required', 'string', 'max:16', Rule::unique('warehouses', 'code')->ignore($this->id)],
'name' => ['required', 'string', 'max:96'],
'description' => ['nullable', 'string', 'max:1024'],
'manager_id' => ['nullable', 'integer', 'exists:users,id'],
'tel' => ['nullable', 'regex:/^[0-9+\-\s]+$/', 'max:20'],
'tel2' => ['nullable', 'regex:/^[0-9+\-\s]+$/', 'max:20'],
'priority' => ['nullable', 'numeric', 'between:0,99'],
'status' => ['nullable', 'boolean'],
];
case 'delete':
return [
'confirmDeletion' => 'accepted', // Asegura que el usuario confirme la eliminación
];
default:
return [];
}
}
// ===================== VALIDACIONES =====================
/**
* Get custom attributes for validator errors.
*
* @return array<string, string>
*/
protected function attributes(): array
{
return [
'code' => 'código de almacén',
'name' => 'nombre del almacén',
];
}
/**
* Get the error messages for the defined validation rules.
*
* @return array<string, string>
*/
protected function messages(): array
{
return [
'store_id.required' => 'El almacén debe estar asociado a un negocio.',
'code.required' => 'El código del almacén es obligatorio.',
'code.unique' => 'Este código ya está en uso por otro almacén.',
'name.required' => 'El nombre del almacén es obligatorio.',
];
}
/**
* Carga el formulario con datos del almacén y actualiza las opciones dinámicas.
*
* @param int $id
*/
public function loadFormModel($id): void
{
parent::loadFormModel($id);
$this->work_center_options = DB::table('store_work_centers')
->where('store_id', $this->store_id)
->pluck('name', 'id')
->toArray();
}
/**
* Carga el formulario para eliminar un almacén, actualizando las opciones necesarias.
*
* @param int $id
*/
public function loadFormModelForDeletion($id): void
{
parent::loadFormModelForDeletion($id);
$this->work_center_options = DB::table('store_work_centers')
->where('store_id', $this->store_id)
->pluck('name', 'id')
->toArray();
}
/**
* Define las opciones de los selectores desplegables.
*
* @return array
*/
protected function options(): array
{
$storeCatalogService = app(StoreCatalogService::class);
$contactCatalogService = app(ContactCatalogService::class);
return [
'store_options' => $storeCatalogService->searchCatalog('stores', '', ['limit' => -1]),
'manager_options' => $contactCatalogService->searchCatalog('users', '', ['limit' => -1]),
];
}
/**
* Ruta de la vista asociada con este formulario.
*
* @return string
*/
protected function viewPath(): string
{
return 'vuexy-website-admin::livewire.faq.offcanvas-form';
}
}

View File

@ -0,0 +1,104 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Livewire\Images;
use Koneko\VuexyAdmin\Livewire\Table\AbstractIndexComponent;
use Koneko\VuexyWebsiteAdmin\Models\Faq;
use Koneko\VuexyWebsiteAdmin\Models\Images;
class ImagesIndex extends AbstractIndexComponent
{
/**
* Retorna la clase del modelo asociado.
*
* @return string
*/
protected function model(): string
{
return Faq::class;
}
/**
* Configura el encabezado (header) de la tabla (las columnas).
*
* @return array
*/
protected function columns(): array
{
return [
'action' => 'Acciones',
'status' => 'Estatus',
'created_at' => 'Fecha de Creación',
'updated_at' => 'Última Actualización',
];
}
/**
* Define los formatos de cada columna (se inyectará en $bt_datatable['format']).
*
* @return array
*/
protected function format(): array
{
return [
'action' => [
'formatter' => 'ImagesActionFormatter',
'onlyFormatter' => true,
],
'status' => [
'formatter' => [
'name' => 'dynamicBooleanFormatter',
'params' => ['tag' => 'activo']
],
'align' => 'center',
],
'created_at' => [
'formatter' => 'textNowrapFormatter',
'align' => 'center',
'visible' => false,
],
'updated_at' => [
'formatter' => 'textNowrapFormatter',
'align' => 'center',
'visible' => false,
],
];
}
/**
* Retorna la configuración base (común) para la tabla Bootstrap Table.
*
* @return array
*/
protected function bootstraptableConfig(): array
{
return [
'sortName' => 'code',
'exportFileName' => 'Almacenes',
'showFullscreen' => false,
'showPaginationSwitch' => false,
'showRefresh' => false,
'pagination' => false,
];
}
/**
* Retorna la ruta de la vista Blade.
*
* @return string
*/
protected function viewPath(): string
{
// La vista que ya tienes creada para ImagesIndex
return 'vuexy-website-admin::livewire.images.index';
}
/**
* Métodos que necesites sobreescribir o extender.
*/
public function mount(): void
{
parent::mount();
}
}

View File

@ -0,0 +1,217 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Livewire\LegalNotices;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
use Koneko\VuexyAdmin\Livewire\Form\AbstractFormOffCanvasComponent;
use Koneko\VuexyContacts\Services\ContactCatalogService;
use Koneko\VuexyStoreManager\Services\StoreCatalogService;
use Koneko\VuexyWarehouse\Models\Warehouse;
/**
* Class LegalNoticeOffCanvasForm
*
* Componente Livewire para gestionar almacenes.
* Extiende la clase AbstractFormOffCanvasComponent e implementa validaciones dinámicas,
* manejo de formularios, eventos y actualizaciones en tiempo real.
*
* @package Koneko\VuexyWarehouse\Livewire\Warehouses
*/
class LegalNoticeOffCanvasForm extends AbstractFormOffCanvasComponent
{
/**
* Propiedades del formulario relacionadas con el almacén.
*/
public $id, $store_id, $work_center_id, $code, $name, $description,
$manager_id, $tel, $tel2, $priority, $status, $confirmDeletion;
/**
* Listas de opciones para selects en el formulario.
*/
public $store_options = [],
$work_center_options = [],
$manager_options = [];
/**
* Eventos de escucha de Livewire.
*
* @var array
*/
protected $listeners = [
'editWarehouse' => 'loadFormModel',
'confirmDeletionWarehouse' => 'loadFormModelForDeletion',
];
/**
* Definición de tipos de datos que se deben castear.
*
* @var array
*/
protected $casts = [
'status' => 'boolean',
];
/**
* Define el modelo Eloquent asociado con el formulario.
*
* @return string
*/
protected function model(): string
{
return Warehouse::class;
}
/**
* Define los campos del formulario.
*
* @return array<string, mixed>
*/
protected function fields(): array
{
return (new Warehouse())->getFillable();
}
/**
* Valores por defecto para el formulario.
*
* @return array
*/
protected function defaults(): array
{
return [
'priority' => 0,
'status' => true,
];
}
/**
* Campo que se debe enfocar cuando se abra el formulario.
*
* @return string
*/
protected function focusOnOpen(): string
{
return 'code';
}
/**
* Define reglas de validación dinámicas basadas en el modo actual.
*
* @param string $mode El modo actual del formulario ('create', 'edit', 'delete').
* @return array
*/
protected function dynamicRules(string $mode): array
{
switch ($mode) {
case 'create':
case 'edit':
return [
'store_id' => ['required', 'integer', 'exists:stores,id'],
'work_center_id' => ['nullable', 'integer', 'exists:store_work_centers,id'],
'code' => ['required', 'string', 'max:16', Rule::unique('warehouses', 'code')->ignore($this->id)],
'name' => ['required', 'string', 'max:96'],
'description' => ['nullable', 'string', 'max:1024'],
'manager_id' => ['nullable', 'integer', 'exists:users,id'],
'tel' => ['nullable', 'regex:/^[0-9+\-\s]+$/', 'max:20'],
'tel2' => ['nullable', 'regex:/^[0-9+\-\s]+$/', 'max:20'],
'priority' => ['nullable', 'numeric', 'between:0,99'],
'status' => ['nullable', 'boolean'],
];
case 'delete':
return [
'confirmDeletion' => 'accepted', // Asegura que el usuario confirme la eliminación
];
default:
return [];
}
}
// ===================== VALIDACIONES =====================
/**
* Get custom attributes for validator errors.
*
* @return array<string, string>
*/
protected function attributes(): array
{
return [
'code' => 'código de almacén',
'name' => 'nombre del almacén',
];
}
/**
* Get the error messages for the defined validation rules.
*
* @return array<string, string>
*/
protected function messages(): array
{
return [
'store_id.required' => 'El almacén debe estar asociado a un negocio.',
'code.required' => 'El código del almacén es obligatorio.',
'code.unique' => 'Este código ya está en uso por otro almacén.',
'name.required' => 'El nombre del almacén es obligatorio.',
];
}
/**
* Carga el formulario con datos del almacén y actualiza las opciones dinámicas.
*
* @param int $id
*/
public function loadFormModel($id): void
{
parent::loadFormModel($id);
$this->work_center_options = DB::table('store_work_centers')
->where('store_id', $this->store_id)
->pluck('name', 'id')
->toArray();
}
/**
* Carga el formulario para eliminar un almacén, actualizando las opciones necesarias.
*
* @param int $id
*/
public function loadFormModelForDeletion($id): void
{
parent::loadFormModelForDeletion($id);
$this->work_center_options = DB::table('store_work_centers')
->where('store_id', $this->store_id)
->pluck('name', 'id')
->toArray();
}
/**
* Define las opciones de los selectores desplegables.
*
* @return array
*/
protected function options(): array
{
$storeCatalogService = app(StoreCatalogService::class);
$contactCatalogService = app(ContactCatalogService::class);
return [
'store_options' => $storeCatalogService->searchCatalog('stores', '', ['limit' => -1]),
'manager_options' => $contactCatalogService->searchCatalog('users', '', ['limit' => -1]),
];
}
/**
* Ruta de la vista asociada con este formulario.
*
* @return string
*/
protected function viewPath(): string
{
return 'vuexy-website-admin::livewire.legal-notices.offcanvas-form';
}
}

View File

@ -0,0 +1,109 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Livewire\LegalNotices;
use Livewire\Component;
use Koneko\VuexyAdmin\Rules\NotEmptyHtml;
use Koneko\VuexyAdmin\Services\SettingsService;
use Koneko\VuexyWebsiteAdmin\Services\WebsiteTemplateService;
class LegalNoticesIndex extends Component
{
private $targetNotify = "#website-legal-settings-card .notification-container";
public $legalVars = [];
public $currentSection = null;
protected $listeners = [
'saveLegalNotices' => 'save',
];
public function mount()
{
$this->loadSettings();
// Seleccionar la primera sección por defecto
$this->currentSection = array_key_first($this->legalVars);
}
function loadSettings()
{
$websiteTemplateService = app(WebsiteTemplateService::class);
switch ($this->currentSection) {
case 'legal_terminos_y_condiciones':
$this->legalVars['legal_terminos_y_condiciones'] = $websiteTemplateService->getLegalVars('legal_terminos_y_condiciones');
break;
case 'legal_aviso_de_privacidad':
$this->legalVars['legal_aviso_de_privacidad'] = $websiteTemplateService->getLegalVars('legal_aviso_de_privacidad');
break;
case 'legal_politica_de_devoluciones':
$this->legalVars['legal_politica_de_devoluciones'] = $websiteTemplateService->getLegalVars('legal_politica_de_devoluciones');
break;
case 'legal_politica_de_envios':
$this->legalVars['legal_politica_de_envios'] = $websiteTemplateService->getLegalVars('legal_politica_de_envios');
break;
case 'legal_politica_de_cookies':
$this->legalVars['legal_politica_de_cookies'] = $websiteTemplateService->getLegalVars('legal_politica_de_cookies');
break;
case 'legal_autorizaciones_y_licencias':
$this->legalVars['legal_autorizaciones_y_licencias'] = $websiteTemplateService->getLegalVars('legal_autorizaciones_y_licencias');
break;
case 'legal_informacion_comercial':
$this->legalVars['legal_informacion_comercial'] = $websiteTemplateService->getLegalVars('legal_informacion_comercial');
break;
case 'legal_consentimiento_para_el_login_de_terceros':
$this->legalVars['legal_consentimiento_para_el_login_de_terceros'] = $websiteTemplateService->getLegalVars('legal_consentimiento_para_el_login_de_terceros');
break;
case 'legal_leyendas_de_responsabilidad':
$this->legalVars['legal_leyendas_de_responsabilidad'] = $websiteTemplateService->getLegalVars('legal_leyendas_de_responsabilidad');
break;
default:
$this->legalVars = $websiteTemplateService->getLegalVars();
}
}
public function rules()
{
$rules = [];
if ($this->legalVars[$this->currentSection]['enabled']) {
$rules["legalVars.{$this->currentSection}.content"] = ['required', 'string', new NotEmptyHtml];
}
$rules["legalVars.{$this->currentSection}.enabled"] = 'boolean';
return $rules;
}
public function save()
{
$this->validate($this->rules());
$SettingsService = app(SettingsService::class);
$SettingsService->set($this->currentSection . '_enabled', $this->legalVars[$this->currentSection]['enabled'], null, 'vuexy-website-admin');
$SettingsService->set($this->currentSection . '_content', $this->legalVars[$this->currentSection]['content'], null, 'vuexy-website-admin');
$this->dispatch(
'notification',
target: $this->targetNotify,
type: 'success',
message: 'Se han guardado los cambios en las configuraciones.'
);
}
public function render()
{
return view('vuexy-website-admin::livewire.legal-notices.index');
}
}

View File

@ -0,0 +1,108 @@
<?php
namespace Modules\Admin\App\Livewire\WebsiteSettings;
use Livewire\Component;
use App\Services\WebsiteTemplateService;
use Modules\Admin\App\Rules\NotEmptyHtml;
use Modules\Admin\App\Services\WebsiteSettingsService;
class LegalSettings extends Component
{
private $targetNotify = "#website-legal-settings-card .notification-container";
public $legalVars = [];
public $currentSection = null;
protected $listeners = [
'saveLegal' => 'save',
];
public function mount()
{
$this->loadSettings();
// Seleccionar la primera sección por defecto
$this->currentSection = array_key_first($this->legalVars);
}
function loadSettings()
{
$websiteTemplateService = app(WebsiteTemplateService::class);
switch ($this->currentSection) {
case 'legal_terminos_y_condiciones':
$this->legalVars['legal_terminos_y_condiciones'] = $websiteTemplateService->getLegalVars('legal_terminos_y_condiciones');
break;
case 'legal_aviso_de_privacidad':
$this->legalVars['legal_aviso_de_privacidad'] = $websiteTemplateService->getLegalVars('legal_aviso_de_privacidad');
break;
case 'legal_politica_de_devoluciones':
$this->legalVars['legal_politica_de_devoluciones'] = $websiteTemplateService->getLegalVars('legal_politica_de_devoluciones');
break;
case 'legal_politica_de_envios':
$this->legalVars['legal_politica_de_envios'] = $websiteTemplateService->getLegalVars('legal_politica_de_envios');
break;
case 'legal_politica_de_cookies':
$this->legalVars['legal_politica_de_cookies'] = $websiteTemplateService->getLegalVars('legal_politica_de_cookies');
break;
case 'legal_autorizaciones_y_licencias':
$this->legalVars['legal_autorizaciones_y_licencias'] = $websiteTemplateService->getLegalVars('legal_autorizaciones_y_licencias');
break;
case 'legal_informacion_comercial':
$this->legalVars['legal_informacion_comercial'] = $websiteTemplateService->getLegalVars('legal_informacion_comercial');
break;
case 'legal_consentimiento_para_el_login_de_terceros':
$this->legalVars['legal_consentimiento_para_el_login_de_terceros'] = $websiteTemplateService->getLegalVars('legal_consentimiento_para_el_login_de_terceros');
break;
case 'legal_leyendas_de_responsabilidad':
$this->legalVars['legal_leyendas_de_responsabilidad'] = $websiteTemplateService->getLegalVars('legal_leyendas_de_responsabilidad');
break;
default:
$this->legalVars = $websiteTemplateService->getLegalVars();
}
}
public function rules()
{
$rules = [];
if ($this->legalVars[$this->currentSection]['enabled']) {
$rules["legalVars.{$this->currentSection}.content"] = ['required', 'string', new NotEmptyHtml];
}
$rules["legalVars.{$this->currentSection}.enabled"] = 'boolean';
return $rules;
}
public function save()
{
$this->validate($this->rules());
$websiteSettingsService = app(WebsiteSettingsService::class);
$websiteSettingsService->updateSetting($this->currentSection . '_enabled', $this->legalVars[$this->currentSection]['enabled']);
$websiteSettingsService->updateSetting($this->currentSection . '_content', $this->legalVars[$this->currentSection]['content']);
$this->dispatch(
'notification',
target: $this->targetNotify,
type: 'success',
message: 'Se han guardado los cambios en las configuraciones.'
);
}
public function render()
{
return view('admin::livewire.website-settings.legal-settings');
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Livewire\SitemapManager;
use Livewire\Component;
use Koneko\VuexyWebsiteAdmin\Models\SitemapUrl;
class SitemapManagerIndex extends Component
{
public $urls, $newUrl, $changefreq = 'weekly', $priority = 0.5;
public function mount()
{
$this->urls = SitemapUrl::all();
}
public function addUrl()
{
SitemapUrl::create([
'url' => $this->newUrl,
'changefreq' => $this->changefreq,
'priority' => $this->priority,
'lastmod' => now()
]);
$this->reset(['newUrl', 'changefreq', 'priority']);
$this->mount();
}
public function deleteUrl($id)
{
SitemapUrl::find($id)->delete();
$this->mount();
}
public function render()
{
return view('vuexy-website-admin::livewire.sitemap-manager.index', ['urls' => $this->urls]);
}}

View File

@ -0,0 +1,217 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Livewire\SitemapManager;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
use Koneko\VuexyAdmin\Livewire\Form\AbstractFormOffCanvasComponent;
use Koneko\VuexyContacts\Services\ContactCatalogService;
use Koneko\VuexyStoreManager\Services\StoreCatalogService;
use Koneko\VuexyWarehouse\Models\Warehouse;
/**
* Class SitemapUrlOffcanvasForm
*
* Componente Livewire para gestionar almacenes.
* Extiende la clase AbstractFormOffCanvasComponent e implementa validaciones dinámicas,
* manejo de formularios, eventos y actualizaciones en tiempo real.
*
* @package Koneko\VuexyWarehouse\Livewire\Warehouses
*/
class SitemapUrlOffcanvasForm extends AbstractFormOffCanvasComponent
{
/**
* Propiedades del formulario relacionadas con el almacén.
*/
public $id, $store_id, $work_center_id, $code, $name, $description,
$manager_id, $tel, $tel2, $priority, $status, $confirmDeletion;
/**
* Listas de opciones para selects en el formulario.
*/
public $store_options = [],
$work_center_options = [],
$manager_options = [];
/**
* Eventos de escucha de Livewire.
*
* @var array
*/
protected $listeners = [
'editWarehouse' => 'loadFormModel',
'confirmDeletionWarehouse' => 'loadFormModelForDeletion',
];
/**
* Definición de tipos de datos que se deben castear.
*
* @var array
*/
protected $casts = [
'status' => 'boolean',
];
/**
* Define el modelo Eloquent asociado con el formulario.
*
* @return string
*/
protected function model(): string
{
return Warehouse::class;
}
/**
* Define los campos del formulario.
*
* @return array<string, mixed>
*/
protected function fields(): array
{
return (new Warehouse())->getFillable();
}
/**
* Valores por defecto para el formulario.
*
* @return array
*/
protected function defaults(): array
{
return [
'priority' => 0,
'status' => true,
];
}
/**
* Campo que se debe enfocar cuando se abra el formulario.
*
* @return string
*/
protected function focusOnOpen(): string
{
return 'code';
}
/**
* Define reglas de validación dinámicas basadas en el modo actual.
*
* @param string $mode El modo actual del formulario ('create', 'edit', 'delete').
* @return array
*/
protected function dynamicRules(string $mode): array
{
switch ($mode) {
case 'create':
case 'edit':
return [
'store_id' => ['required', 'integer', 'exists:stores,id'],
'work_center_id' => ['nullable', 'integer', 'exists:store_work_centers,id'],
'code' => ['required', 'string', 'max:16', Rule::unique('warehouses', 'code')->ignore($this->id)],
'name' => ['required', 'string', 'max:96'],
'description' => ['nullable', 'string', 'max:1024'],
'manager_id' => ['nullable', 'integer', 'exists:users,id'],
'tel' => ['nullable', 'regex:/^[0-9+\-\s]+$/', 'max:20'],
'tel2' => ['nullable', 'regex:/^[0-9+\-\s]+$/', 'max:20'],
'priority' => ['nullable', 'numeric', 'between:0,99'],
'status' => ['nullable', 'boolean'],
];
case 'delete':
return [
'confirmDeletion' => 'accepted', // Asegura que el usuario confirme la eliminación
];
default:
return [];
}
}
// ===================== VALIDACIONES =====================
/**
* Get custom attributes for validator errors.
*
* @return array<string, string>
*/
protected function attributes(): array
{
return [
'code' => 'código de almacén',
'name' => 'nombre del almacén',
];
}
/**
* Get the error messages for the defined validation rules.
*
* @return array<string, string>
*/
protected function messages(): array
{
return [
'store_id.required' => 'El almacén debe estar asociado a un negocio.',
'code.required' => 'El código del almacén es obligatorio.',
'code.unique' => 'Este código ya está en uso por otro almacén.',
'name.required' => 'El nombre del almacén es obligatorio.',
];
}
/**
* Carga el formulario con datos del almacén y actualiza las opciones dinámicas.
*
* @param int $id
*/
public function loadFormModel($id): void
{
parent::loadFormModel($id);
$this->work_center_options = DB::table('store_work_centers')
->where('store_id', $this->store_id)
->pluck('name', 'id')
->toArray();
}
/**
* Carga el formulario para eliminar un almacén, actualizando las opciones necesarias.
*
* @param int $id
*/
public function loadFormModelForDeletion($id): void
{
parent::loadFormModelForDeletion($id);
$this->work_center_options = DB::table('store_work_centers')
->where('store_id', $this->store_id)
->pluck('name', 'id')
->toArray();
}
/**
* Define las opciones de los selectores desplegables.
*
* @return array
*/
protected function options(): array
{
$storeCatalogService = app(StoreCatalogService::class);
$contactCatalogService = app(ContactCatalogService::class);
return [
'store_options' => $storeCatalogService->searchCatalog('stores', '', ['limit' => -1]),
'manager_options' => $contactCatalogService->searchCatalog('users', '', ['limit' => -1]),
];
}
/**
* Ruta de la vista asociada con este formulario.
*
* @return string
*/
protected function viewPath(): string
{
return 'vuexy-website-admin::livewire.sitemap-manager.offcanvas-form';
}
}

View File

@ -0,0 +1,67 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Livewire\VuexyWebsiteAdmin;
use Koneko\VuexyAdmin\Services\SettingsService;
use Koneko\VuexyWebsiteAdmin\Services\WebsiteTemplateService;
use Livewire\Component;
class ChatSettings extends Component
{
private $targetNotify = "#website-chat-settings-card .notification-container";
public $chat_provider,
$chat_whatsapp_number,
$chat_whatsapp_message;
public function mount()
{
$this->resetForm();
}
public function save()
{
if ($this->chat_provider == 'whatsapp') {
$this->validate([
'chat_whatsapp_number' => 'required|string|max:20',
'chat_whatsapp_message' => 'required|string|max:255',
]);
}
// Guardar título del sitio en configuraciones
$SettingsService = app(SettingsService::class);
$SettingsService->set('chat.provider', $this->chat_provider, null, 'vuexy-website-admin');
$SettingsService->set('chat.whatsapp_number', $this->chat_whatsapp_number, null, 'vuexy-website-admin');
$SettingsService->set('chat.whatsapp_message', $this->chat_whatsapp_message, null, 'vuexy-website-admin');
// Limpiar cache de plantilla
app(WebsiteTemplateService::class)->clearWebsiteVarsCache();
// Recargamos el formulario
$this->resetForm();
// Notificación de éxito
$this->dispatch(
'notification',
target: $this->targetNotify,
type: 'success',
message: 'Se han guardado los cambios en las configuraciones.'
);
}
public function resetForm()
{
// Obtener los valores de las configuraciones de la base de datos
$settings = app(WebsiteTemplateService::class)->getWebsiteVars('chat');
$this->chat_provider = $settings['provider'];
$this->chat_whatsapp_number = $settings['whatsapp_number'];
$this->chat_whatsapp_message = $settings['whatsapp_message'];
}
public function render()
{
return view('vuexy-website-admin::livewire.vuexy.chat-settings');
}
}

View File

@ -0,0 +1,70 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Livewire\VuexyWebsiteAdmin;
use Koneko\VuexyAdmin\Services\SettingsService;
use Koneko\VuexyWebsiteAdmin\Services\WebsiteTemplateService;
use Livewire\Component;
class ContactFormSettings extends Component
{
private $targetNotify = "#website-contact-form-settings-card .notification-container";
public $to_email,
$to_email_cc,
$subject,
$submit_message;
public function mount()
{
$this->resetForm();
}
public function save()
{
$this->validate([
'to_email' => 'required|email',
'to_email_cc' => 'nullable|email',
'subject' => 'required|string',
'submit_message' => 'required|string'
]);
// Guardar título del sitio en configuraciones
$SettingsService = app(SettingsService::class);
$SettingsService->set('contact.form.to_email', $this->to_email, null, 'vuexy-website-admin');
$SettingsService->set('contact.form.to_email_cc', $this->to_email_cc, null, 'vuexy-website-admin');
$SettingsService->set('contact.form.subject', $this->subject, null, 'vuexy-website-admin');
$SettingsService->set('contact.form.submit_message', $this->submit_message, null, 'vuexy-website-admin');
// Limpiar cache de plantilla
app(WebsiteTemplateService::class)->clearWebsiteVarsCache();
// Recargamos el formulario
$this->resetForm();
// Notificación de éxito
$this->dispatch(
'notification',
target: $this->targetNotify,
type: 'success',
message: 'Se han guardado los cambios en las configuraciones.'
);
}
public function resetForm()
{
// Obtener los valores de las configuraciones de la base de datos
$settings = app(WebsiteTemplateService::class)->getWebsiteVars('contact');
$this->to_email = $settings['form']['to_email'];
$this->to_email_cc = $settings['form']['to_email_cc'];
$this->subject = $settings['form']['subject'];
$this->submit_message = $settings['form']['submit_message'];
}
public function render()
{
return view('vuexy-website-admin::livewire.vuexy.contact-form-settings');
}
}

View File

@ -0,0 +1,78 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Livewire\VuexyWebsiteAdmin;
use Koneko\VuexyAdmin\Services\SettingsService;
use Koneko\VuexyWebsiteAdmin\Services\WebsiteTemplateService;
use Livewire\Component;
class ContactInfoSettings extends Component
{
private $targetNotify = "#website-contact-info-settings-card .notification-container";
public $phone_number,
$phone_number_ext,
$phone_number_2,
$phone_number_2_ext,
$email,
$horario;
public function mount()
{
$this->resetForm();
}
public function save()
{
$this->validate([
'phone_number' => 'nullable|string',
'phone_number_ext' => 'nullable|string',
'phone_number_2' => 'nullable|string',
'phone_number_2_ext' => 'nullable|string',
'email' => 'nullable|email',
'horario' => 'nullable|string',
]);
// Guardar título del sitio en configuraciones
$SettingsService = app(SettingsService::class);
$SettingsService->set('contact.phone_number', $this->phone_number, null, 'vuexy-website-admin');
$SettingsService->set('contact.phone_number_ext', $this->phone_number_ext, null, 'vuexy-website-admin');
$SettingsService->set('contact.phone_number_2', $this->phone_number_2, null, 'vuexy-website-admin');
$SettingsService->set('contact.phone_number_2_ext', $this->phone_number_2_ext, null, 'vuexy-website-admin');
$SettingsService->set('contact.email', $this->email, null, 'vuexy-website-admin');
$SettingsService->set('contact.horario', $this->horario, null, 'vuexy-website-admin');
// Limpiar cache de plantilla
app(WebsiteTemplateService::class)->clearWebsiteVarsCache();
// Recargamos el formulario
$this->resetForm();
// Notificación de éxito
$this->dispatch(
'notification',
target: $this->targetNotify,
type: 'success',
message: 'Se han guardado los cambios en las configuraciones.'
);
}
public function resetForm()
{
// Obtener los valores de las configuraciones de la base de datos
$settings = app(WebsiteTemplateService::class)->getWebsiteVars('contact');
$this->phone_number = $settings['phone_number'];
$this->phone_number_ext = $settings['phone_number_ext'];
$this->phone_number_2 = $settings['phone_number_2'];
$this->phone_number_2_ext = $settings['phone_number_2_ext'];
$this->email = $settings['email'];
$this->horario = $settings['horario'];
}
public function render()
{
return view('vuexy-website-admin::livewire.vuexy.contact-info-settings');
}
}

View File

@ -0,0 +1,63 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Livewire\VuexyWebsiteAdmin;
use Koneko\VuexyAdmin\Services\SettingsService;
use Koneko\VuexyWebsiteAdmin\Services\WebsiteTemplateService;
use Livewire\Component;
class GoogleAnalyticsSettings extends Component
{
private $targetNotify = "#website-analytics-settings-card .notification-container";
public $google_analytics_enabled,
$google_analytics_id;
public function mount()
{
$this->resetForm();
}
public function save()
{
if ($this->google_analytics_enabled) {
$this->validate([
'google_analytics_id' => 'required|string|min:12|max:30',
]);
}
// Guardar título del sitio en configuraciones
$SettingsService = app(SettingsService::class);
$SettingsService->set('google.analytics_enabled', $this->google_analytics_enabled, null, 'vuexy-website-admin');
$SettingsService->set('google.analytics_id', $this->google_analytics_id, null, 'vuexy-website-admin');
// Limpiar cache de plantilla
app(WebsiteTemplateService::class)->clearWebsiteVarsCache();
// Recargamos el formulario
$this->resetForm();
// Notificación de éxito
$this->dispatch(
'notification',
target: $this->targetNotify,
type: 'success',
message: 'Se han guardado los cambios en las configuraciones.'
);
}
public function resetForm()
{
// Obtener los valores de las configuraciones de la base de datos
$settings = app(WebsiteTemplateService::class)->getWebsiteVars('google');
$this->google_analytics_enabled = $settings['analytics']['enabled'];
$this->google_analytics_id = $settings['analytics']['id'];
}
public function render()
{
return view('vuexy-website-admin::livewire.vuexy.analytics-settings');
}
}

View File

@ -0,0 +1,69 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Livewire\VuexyWebsiteAdmin;
use Koneko\VuexyAdmin\Services\SettingsService;
use Koneko\VuexyWebsiteAdmin\Services\WebsiteTemplateService;
use Livewire\Component;
class LocationSettings extends Component
{
private $targetNotify = "#website-location-settings-card .notification-container";
public $direccion,
$location_lat,
$location_lng;
public function mount()
{
$this->resetForm();
}
public function save()
{
$this->validate([
'direccion' => ['nullable', 'string', 'max:255'],
'location_lat' => ['nullable', 'numeric'],
'location_lng' => ['nullable', 'numeric'],
]);
// Guardar título del sitio en configuraciones
$SettingsService = app(SettingsService::class);
$location_lat = $this->location_lat? (float) $this->location_lat: null;
$location_lng = $this->location_lng? (float) $this->location_lng: null;
$SettingsService->set('contact.direccion', $this->direccion, null, 'vuexy-website-admin');
$SettingsService->set('contact.location.lat', $location_lat, null, 'vuexy-website-admin');
$SettingsService->set('contact.location.lng', $location_lng, null, 'vuexy-website-admin');
// Limpiar cache de plantilla
app(WebsiteTemplateService::class)->clearWebsiteVarsCache();
// Recargamos el formulario
$this->resetForm();
// Notificación de éxito
$this->dispatch(
'notification',
target: $this->targetNotify,
type: 'success',
message: 'Se han guardado los cambios en las configuraciones.'
);
}
public function resetForm()
{
// Obtener los valores de las configuraciones de la base de datos
$settings = app(WebsiteTemplateService::class)->getWebsiteVars('contact');
$this->direccion = $settings['direccion'];
$this->location_lat = $settings['location']['lat'];
$this->location_lng = $settings['location']['lng'];
}
public function render()
{
return view('vuexy-website-admin::livewire.vuexy.location-settings');
}
}

View File

@ -0,0 +1,61 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Livewire\VuexyWebsiteAdmin;
use Livewire\Component;
use Livewire\WithFileUploads;
use Koneko\VuexyWebsiteAdmin\Services\WebsiteSettingsService;
use Koneko\VuexyWebsiteAdmin\Services\WebsiteTemplateService;
class LogoOnDarkBgSettings extends Component
{
use WithFileUploads;
private $targetNotify = "#logo-on-dark-bg-settings-card .notification-container";
public $website_image_logo_dark,
$upload_image_logo_dark;
public function mount()
{
$this->resetForm();
}
public function save()
{
$this->validate([
'upload_image_logo_dark' => 'required|image|mimes:jpeg,png,jpg,svg,webp|max:20480',
]);
// Procesar favicon si se ha cargado una imagen
app(WebsiteSettingsService::class)->processAndSaveImageLogo($this->upload_image_logo_dark, 'dark');
// Limpiar cache de plantilla
app(WebsiteTemplateService::class)->clearWebsiteVarsCache();
// Recargamos el formulario
$this->resetForm();
// Notificación de éxito
$this->dispatch(
'notification',
target: $this->targetNotify,
type: 'success',
message: 'Se han guardado los cambios en las configuraciones.'
);
}
public function resetForm()
{
// Obtener los valores de las configuraciones de la base de datos
$settings = app(WebsiteTemplateService::class)->getWebsiteVars();
$this->upload_image_logo_dark = null;
$this->website_image_logo_dark = $settings['image_logo']['large_dark'];
}
public function render()
{
return view('vuexy-website-admin::livewire.vuexy.logo-on-dark-bg-settings');
}
}

View File

@ -0,0 +1,61 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Livewire\VuexyWebsiteAdmin;
use Livewire\Component;
use Livewire\WithFileUploads;
use Koneko\VuexyWebsiteAdmin\Services\WebsiteSettingsService;
use Koneko\VuexyWebsiteAdmin\Services\WebsiteTemplateService;
class LogoOnLightBgSettings extends Component
{
use WithFileUploads;
private $targetNotify = "#logo-on-light-bg-settings-card .notification-container";
public $website_image_logo,
$upload_image_logo;
public function mount()
{
$this->resetForm();
}
public function save()
{
$this->validate([
'upload_image_logo' => 'required|image|mimes:jpeg,png,jpg,svg,webp|max:20480',
]);
// Procesar favicon si se ha cargado una imagen
app(WebsiteSettingsService::class)->processAndSaveImageLogo($this->upload_image_logo);
// Limpiar cache de plantilla
app(WebsiteTemplateService::class)->clearWebsiteVarsCache();
// Recargamos el formulario
$this->resetForm();
// Notificación de éxito
$this->dispatch(
'notification',
target: $this->targetNotify,
type: 'success',
message: 'Se han guardado los cambios en las configuraciones.'
);
}
public function resetForm()
{
// Obtener los valores de las configuraciones de la base de datos
$settings = app(WebsiteTemplateService::class)->getWebsiteVars();
$this->upload_image_logo = null;
$this->website_image_logo = $settings['image_logo']['large'];
}
public function render()
{
return view('vuexy-website-admin::livewire.vuexy.logo-on-light-bg-settings');
}
}

View File

@ -0,0 +1,98 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Livewire\VuexyWebsiteAdmin;
use Koneko\VuexyAdmin\Services\SettingsService;
use Koneko\VuexyWebsiteAdmin\Services\WebsiteTemplateService;
use Livewire\Component;
class SocialMediaSettings extends Component
{
private $targetNotify = "#website-social-settings-card .notification-container";
public $social_whatsapp,
$social_whatsapp_message,
$social_facebook,
$social_instagram,
$social_linkedin,
$social_tiktok,
$social_x_twitter,
$social_google,
$social_pinterest,
$social_youtube,
$social_vimeo;
public function mount()
{
$this->resetForm();
}
public function save()
{
$this->validate([
'social_whatsapp' => 'string|max:20',
'social_whatsapp_message' => 'string|max:255',
'social_facebook' => 'url',
'social_instagram' => 'url',
'social_linkedin' => 'url',
'social_tiktok' => 'url',
'social_x_twitter' => 'url',
'social_google' => 'url',
'social_pinterest' => 'url',
'social_youtube' => 'url',
'social_vimeo' => 'url',
]);
// Guardar título del sitio en configuraciones
$SettingsService = app(SettingsService::class);
$SettingsService->set('social.whatsapp', $this->social_whatsapp, null, 'vuexy-website-admin');
$SettingsService->set('social.whatsapp_message', $this->social_whatsapp_message, null, 'vuexy-website-admin');
$SettingsService->set('social.facebook', $this->social_facebook, null, 'vuexy-website-admin');
$SettingsService->set('social.instagram', $this->social_instagram, null, 'vuexy-website-admin');
$SettingsService->set('social.linkedin', $this->social_linkedin, null, 'vuexy-website-admin');
$SettingsService->set('social.tiktok', $this->social_tiktok, null, 'vuexy-website-admin');
$SettingsService->set('social.x_twitter', $this->social_x_twitter, null, 'vuexy-website-admin');
$SettingsService->set('social.google', $this->social_google, null, 'vuexy-website-admin');
$SettingsService->set('social.pinterest', $this->social_pinterest, null, 'vuexy-website-admin');
$SettingsService->set('social.youtube', $this->social_youtube, null, 'vuexy-website-admin');
$SettingsService->set('social.vimeo', $this->social_vimeo, null, 'vuexy-website-admin');
// Limpiar cache de plantilla
app(WebsiteTemplateService::class)->clearWebsiteVarsCache();
// Recargamos el formulario
$this->resetForm();
// Notificación de éxito
$this->dispatch(
'notification',
target: $this->targetNotify,
type: 'success',
message: 'Se han guardado los cambios en las configuraciones.'
);
}
public function resetForm()
{
// Obtener los valores de las configuraciones de la base de datos
$settings = app(WebsiteTemplateService::class)->getSocialVars();
$this->social_whatsapp = $settings['whatsapp'];
$this->social_whatsapp_message = $settings['whatsapp_message'];
$this->social_facebook = $settings['facebook'];
$this->social_instagram = $settings['instagram'];
$this->social_linkedin = $settings['linkedin'];
$this->social_tiktok = $settings['tiktok'];
$this->social_x_twitter = $settings['x_twitter'];
$this->social_google = $settings['google'];
$this->social_pinterest = $settings['pinterest'];
$this->social_youtube = $settings['youtube'];
$this->social_vimeo = $settings['vimeo'];
}
public function render()
{
return view('vuexy-website-admin::livewire.vuexy.social-media-settings');
}
}

View File

@ -0,0 +1,62 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Livewire\VuexyWebsiteAdmin;
use Livewire\Component;
use Koneko\VuexyAdmin\Services\SettingsService;
use Koneko\VuexyWebsiteAdmin\Services\WebsiteTemplateService;
class WebsiteDescriptionSettings extends Component
{
private $targetNotify = "#website-description-settings-card .notification-container";
public $title,
$description;
public function mount()
{
$this->resetForm();
}
public function save()
{
$this->validate([
'title' => 'required|string|max:255',
'description' => 'nullable|string|max:255',
]);
// Guardar título del sitio en configuraciones
$SettingsService = app(SettingsService::class);
$SettingsService->set('website.title', $this->title, null, 'vuexy-website-admin');
$SettingsService->set('website.description', $this->description, null, 'vuexy-website-admin');
// Limpiar cache de plantilla
app(WebsiteTemplateService::class)->clearWebsiteVarsCache();
// Recargamos el formulario
$this->resetForm();
// Notificación de éxito
$this->dispatch(
'notification',
target: $this->targetNotify,
type: 'success',
message: 'Se han guardado los cambios en las configuraciones.'
);
}
public function resetForm()
{
// Obtener los valores de las configuraciones de la base de datos
$settings = app(WebsiteTemplateService::class)->getWebsiteVars();
$this->title = $settings['title'];
$this->description = $settings['description'];
}
public function render()
{
return view('vuexy-website-admin::livewire.vuexy.website-description-settings');
}
}

View File

@ -0,0 +1,72 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Livewire\VuexyWebsiteAdmin;
use Livewire\Component;
use Livewire\WithFileUploads;
use Koneko\VuexyWebsiteAdmin\Services\WebsiteSettingsService;
use Koneko\VuexyWebsiteAdmin\Services\WebsiteTemplateService;
class WebsiteFaviconSettings extends Component
{
use WithFileUploads;
private $targetNotify = "#website-favicon-settings-card .notification-container";
public $website_favicon_16x16,
$website_favicon_76x76,
$website_favicon_120x120,
$website_favicon_152x152,
$website_favicon_180x180,
$website_favicon_192x192;
public $upload_image_favicon;
public function mount()
{
$this->resetForm();
}
public function save()
{
$this->validate([
'upload_image_favicon' => 'required|image|mimes:jpeg,png,jpg,svg,webp|max:20480',
]);
// Procesar favicon
app(WebsiteSettingsService::class)->processAndSaveFavicon($this->upload_image_favicon);
// Limpiar cache de plantilla
app(WebsiteTemplateService::class)->clearWebsiteVarsCache();
// Recargamos el formulario
$this->resetForm();
// Notificación de éxito
$this->dispatch(
'notification',
target: $this->targetNotify,
type: 'success',
message: 'Se han guardado los cambios en las configuraciones.'
);
}
public function resetForm()
{
// Obtener los valores de las configuraciones de la base de datos
$settings = app(WebsiteTemplateService::class)->getWebsiteVars();
$this->upload_image_favicon = null;
$this->website_favicon_16x16 = $settings['favicon']['16x16'];
$this->website_favicon_76x76 = $settings['favicon']['76x76'];
$this->website_favicon_120x120 = $settings['favicon']['120x120'];
$this->website_favicon_152x152 = $settings['favicon']['152x152'];
$this->website_favicon_180x180 = $settings['favicon']['180x180'];
$this->website_favicon_192x192 = $settings['favicon']['192x192'];
}
public function render()
{
return view('vuexy-website-admin::livewire.vuexy.website-favicon-settings');
}
}