Skip to main content
All interactive UI in MediPro is built with Livewire Volt single-file components. Each component file contains a PHP anonymous class and a Blade template in the same .blade.php file. The prefix in the filename is the Volt naming convention that triggers automatic component discovery and registration.
Component names follow the directory path relative to resources/views/components/, using dot notation. For example, resources/views/components/ventanas/⚡app.blade.php is referenced as <livewire:ventanas.app />.

Window components

ComponentFileResponsibility
ventanas.appresources/views/components/ventanas/⚡app.blade.phpSystem selector — renders the grid of window type cards and conditionally mounts the correct configurator sub-component
ventanas.sistema-novaresources/views/components/ventanas/⚡sistema-nova.blade.phpSistema Nova configurator — full dimension input, 2D plan diagram, profile detail table, and multi-window tab management

Door components

ComponentFileResponsibility
puertas.appresources/views/components/puertas/⚡app.blade.phpDoor type selector — renders the grid of door type cards and conditionally mounts the correct configurator sub-component
puertas.normalresources/views/components/puertas/⚡normal.blade.phpClassic door configurator
puertas.personalizableresources/views/components/puertas/⚡personalizable.blade.phpCustom door configurator with aesthetic and technical options
puertas.corrediza1hojaresources/views/components/puertas/⚡corrediza1hoja.blade.phpSliding 1-leaf door configurator
puertas.corrediza2hojaresources/views/components/puertas/⚡corrediza2hoja.blade.phpSliding 2-leaf door configurator

State management in ventanas.sistema-nova

This is the most complex component in the application. Its state is organized into three layers.

Public properties (reactive state)

These properties are bound directly to form inputs via wire:model.blur and drive all computed values:
public float $ancho = 205;        // Total width in cm
public float $alto = 165;         // Total height in cm
public float $altoPuente = 130;   // Lower section height (bridge) in cm
public int   $numCorredizas = 1;  // Number of sliding panels
public int   $numFijos = 2;       // Number of fixed panels

Multi-window management

The component supports configuring multiple windows in a single session using a tab interface:
public array $ventanas = [];      // Array of window snapshots
public int   $ventanaActiva = 0;  // Index of the currently selected tab
Each entry in $ventanas is a snapshot array with the same keys as the public properties above, plus a nombre label (e.g., 'V - 1'). When the user switches tabs, cambiarVentana(int $i) saves the current snapshot, updates $ventanaActiva, and loads the new tab’s values into the public properties.

Internal adjustment constants

These protected properties define the correction factors used in glass dimension calculations:
protected float $vidrio = 0.6;       // Glass width adjustment per panel
protected float $pffijo = 0.3;       // Fixed upright height reduction
protected float $pfcorrediza = 2.0;  // Sliding upright height reduction
protected float $sobreluz = 2.1;     // Transom height offset
protected float $sbancho = 0.3;      // Transom panel width reduction
protected float $vfijo = 1.0;        // Fixed glass height reduction
protected float $vcorrediza = 3.5;   // Sliding glass height reduction

Lifecycle hooks

mount() — Called once when the component is first rendered. Loads the profile catalog from public/datos.xlsx via procesarPerfiles(), then restores any saved window set from session('ventanas', []). Defaults to a single window (V - 1) if no session exists. updated($propertyName) — Called automatically by Livewire after any public property changes. Saves the current window state as a snapshot and persists the entire $ventanas array to the session:
public function updated($propertyName)
{
    $this->guardarVentanaActual();
    session()->put('ventanas', $this->ventanas);
}
This ensures data survives page refreshes without any explicit save button.

Computed properties

Computed properties follow Livewire’s getXxxProperty() convention. They are accessed in templates as $this->xxx and recalculate on every render.
MethodAccessed asReturnsDescription
getDivisionesInferioresProperty()$this->divisionesInferioresintTotal panel count — sum of $numCorredizas and $numFijos
getAnchoAjustadoProperty()$this->anchoAjustadofloatWidth with a correction factor added based on panel count (+1 cm for 3 panels, +2 for 5, +3 for 6)
getAltoInfProperty()$this->altoInffloatLower section height — alias for $altoPuente
getAltoSupProperty()$this->altoSupfloatUpper transom height — max(0, $alto - $altoPuente - 2.1)
getBloquesProperty()$this->bloquesarrayOrdered array of 'Fijo' / 'Corrediza' strings representing the panel layout
getMedidasBloquesProperty()$this->medidasBloquesarrayGlass dimensions per panel: tipo ('F'/'C'), ancho, and alto in cm
getSobreluzPartesProperty()$this->sobreluzPartesarrayTransom sub-panel dimensions: ancho, alto, and label (e.g., 'TL 1')
getDetalleModulosProperty()$this->detalleModulosarrayProfile detail table data — keyed by profile name, each entry has label (product code), alto (cut length), and cantidad (quantity)
getAccesoriosProperty()$this->accesoriosarrayAccessories quantities: garruchas, pestillos, and topes derived from $numCorredizas

Panel layout algorithm

getBloquesProperty() distributes fixed and sliding panels with special rules for 5- and 6-panel configurations:
public function getBloquesProperty(): array
{
    $t = $this->divisionesInferiores;

    if ($t === 5) {
        return ['Fijo', 'Corrediza', 'Fijo', 'Corrediza', 'Fijo'];
    }
    if ($t === 6) {
        return ['Fijo', 'Corrediza', 'Fijo', 'Corrediza', 'Fijo', 'Corrediza'];
    }

    // Default: split fixed panels evenly on left and right of sliding panels
    $l = intdiv($this->numFijos, 2);
    return [
        ...array_fill(0, $l, 'Fijo'),
        ...array_fill(0, $this->numCorredizas, 'Corrediza'),
        ...array_fill(0, $this->numFijos - $l, 'Fijo'),
    ];
}

Browser events

The component dispatches events to JavaScript listeners using $this->dispatch():
EventTriggerJavaScript handler
disparar-impresion-totalAfter imprimirTodo() saves print data to sessionSets iframe#iframeLote src to route('plano.imprimir') and calls contentWindow.print() after a 600ms delay
correctoAfter agregarVentana() adds a new tabiziToast success notification in the top-right corner
deleteAfter eliminarVentana() removes a tabiziToast info notification in the top-right corner

imprimirTodo() — print action

This method collects all window configurations, calculates the full detail data for each, and triggers the print flow:
public function imprimirTodo(): void
{
    $ventanasCompletas = [];

    foreach ($this->ventanas as $index => $v) {
        $anchoAjustado = $this->calcularAnchoAjustado(
            $v['ancho'],
            $v['numCorredizas'],
            $v['numFijos']
        );

        $ventanasCompletas[] = [
            'nombre'        => $v['nombre'],
            'ancho'         => $v['ancho'],
            'alto'          => $v['alto'],
            'altoPuente'    => $v['altoPuente'],
            'numCorredizas' => $v['numCorredizas'],
            'numFijos'      => $v['numFijos'],
            'altoInf'       => $v['altoPuente'],
            'altoSup'       => max(0, $v['alto'] - $v['altoPuente'] - $this->sobreluz),
            'bloques'       => $this->calcularMedidasBloques(...),
            'sobreluz'      => $this->calcularSobreluz(...),
            'anchoAjustado' => $anchoAjustado,
            'detalle'       => $this->calcularDetalleModulos(...),
            'catalogo'      => $this->data,
        ];
    }

    session()->put('datos_lote', $ventanasCompletas);
    session()->save();

    $this->dispatch('disparar-impresion-total');
}
imprimirTodo() uses private helper methods (calcularMedidasBloques, calcularDetalleModulos, calcularSobreluz) instead of the reactive computed properties. This avoids temporarily mutating the component’s public state when iterating over windows other than the currently active one.

selector components (ventanas.app and puertas.app)

Both selector components follow the same pattern:
  1. $sistemaSeleccionado (or $PuertaSeleccionado) is null by default.
  2. mount() restores the selection from the session.
  3. seleccionar($sistema) sets the property and saves it to the session.
  4. resetear() clears both the property and the session key, returning to the selector grid.
  5. The Blade template conditionally renders either the card grid or the chosen sub-component using @if / @elseif blocks.
Door type 'Puerta 2 Hojas' does not have a dedicated Livewire sub-component yet — it falls through to the @else branch, which renders a “coming soon” placeholder screen.

Build docs developers (and LLMs) love