Conecciones de Promociones

This commit is contained in:
Juan Pablo Vial
2025-04-03 13:15:56 -03:00
parent ced673e452
commit 8a1e6a7761
17 changed files with 1144 additions and 79 deletions

View File

@ -18,67 +18,293 @@
<p>
{{ $promotion->startDate->format('d-m-Y') }} -> {!! $promotion->endDate?->format('d-m-Y') ?? '&infin;' !!}
</p>
<p>Válido hasta: {!! $promotion->validUntil?->format('d-m-Y') ?? '&infin;' !!}</p>
<p>Válido hasta: {!! $promotion->validUntil?->format('d-m-Y') ?? '&empty;' !!}</p>
</div>
</div>
</div>
<table class="ui table" id="contracts">
<thead>
<tr>
<th>Proyecto</th>
<th>Operador</th>
<th class="center aligned" colspan="2">Unidad</th>
<th class="right aligned">
<button class="ui tertiary green icon button" id="add_button">
<i class="plus icon"></i>
</button>
</th>
</tr>
<tr>
<th colspan="2"></th>
<th>Tipo</th>
<th></th>
</tr>
</thead>
<tbody>
@if (count($promotion->projects()) > 0)
@foreach ($promotion->projects() as $project)
<tr>
<td>{{ $project->descripcion }}</td>
<td>Todos los Operadores</td>
<td colspan="2">Todas las Unidades</td>
</tr>
@endforeach
@endif
@if (count($promotion->contracts()) > 0)
@foreach($promotion->contracts() as $contract)
<tr>
<td>{{ $contract->project->descripcion }}</td>
<td>{{ $contract->broker->name }}</td>
<td colspan="2">Todas las Unidades</td>
</tr>
@endforeach
@endif
@if (count($promotion->units()) > 0)
@foreach($promotion->units() as $unit)
<tr>
<td>{{ $unit->project->descripcion }}</td>
<td>Todos los Operadores</td>
<td>{{ $unit->proyectoTipoUnidad->tipoUnidad->descripcion }}</td>
<td>{{ $unit->descripcion }}</td>
</tr>
@endforeach
@endif
@if (count($promotion->contractUnits()) > 0)
@foreach($promotion->contractUnits() as $contractUnit)
<tr>
<td>{{ $contractUnit->contract->project->descripcion }}</td>
<td>{{ $contractUnit->contract->broker->name }}</td>
<td>{{ $contractUnit->unidad->proyectoTipoUnidad->tipoUnidad->descripcion }}</td>
<td>{{ $contractUnit->unidad->descripcion }}</td>
</tr>
@endforeach
@endif
</tbody>
</table>
<div class="ui right aligned basic segment">
<button class="ui green tertiary icon button" id="add_button">
<i class="plus icon"></i>
</button>
</div>
<div class="ui top attached tabular menu" id="tables_tab_menu">
<div class="active item" data-tab="projects_table">Proyectos</div>
<div class="item" data-tab="brokers_table">Operadores</div>
<div class="item" data-tab="unit-types_table">Tipos</div>
<div class="item" data-tab="unit-lines_table">Líneas</div>
<div class="item" data-tab="units_table">Unidades</div>
</div>
<div class="ui bottom attached tab fitted segment" data-tab="projects_table"></div>
<div class="ui bottom attached tab fitted segment" data-tab="brokers_table"></div>
<div class="ui bottom attached tab fitted segment" data-tab="unit-types_table"></div>
<div class="ui bottom attached tab fitted segment" data-tab="unit-lines_table"></div>
<div class="ui bottom attached tab fitted segment" data-tab="units_table"></div>
@include('ventas.promotions.show.add_modal')
@endsection
@push('page_scripts')
<script>
class ContractTable {
table
constructor(tab) {
const parent = document.querySelector(`.ui.tab.segment[data-tab="${tab}"]`)
this.table = document.createElement('table')
this.table.className = 'ui table'
this.table.innerHTML = [
'<thead>',
'<tr>',
'<th>Proyecto</th>',
'<th>Operador</th>',
'<th class="center aligned" colspan="3">Unidad</th>',
'</tr>',
'<tr>',
'<th colspan="2"></th>',
'<th>Tipo</th>',
'<th>Línea</th>',
'<th>#</th>',
'<th></th>',
'</tr>',
'</thead>',
'<tbody></tbody>'
].join("\n")
parent.appendChild(this.table)
}
static fromProjects(data) {
const table = new ContractTable('projects_table')
data.forEach(project => {
const row = document.createElement('tr')
row.innerHTML = [
`<td>${project.descripcion}</td>`,
'<td>Todos los Operadores</td>',
'<td colspan="3">Todas las Unidades</td>',
`<td class="right aligned">`,
`<button class="ui red icon button remove_button project" data-id="${project.id}">`,
'<i class="plus icon"></i>',
'</button>',
`</td>`
].join("\n")
table.table.querySelector('tbody').appendChild(row)
})
document.querySelectorAll('.remove_button.project').forEach(button => {
button.addEventListener('click', () => {
const project_id = button.dataset.id
promotion.remove().project(project_id)
})
})
}
static fromBrokers(data) {
const table = new ContractTable('brokers_table')
data.forEach(contract => {
const row = document.createElement('tr')
row.innerHTML = [
`<td>${contract.project.descripcion}</td>`,
`<td>${contract.broker.name}</td>`,
'<td colspan="3">Todas las Unidades</td>',
`<td class="right aligned">`,
`<button class="ui red icon button remove_button broker" data-id="${contract.id}">`,
'<i class="plus icon"></i>',
'</button>',
`</td>`
].join("\n")
table.table.querySelector('tbody').appendChild(row)
})
document.querySelectorAll('.remove_button.broker').forEach(button => {
button.addEventListener('click', () => {
const contract_id = button.dataset.id
promotion.remove().contract(contract_id)
})
})
}
static fromUnitTypes(data) {
const table = new ContractTable('unit-types_table')
data.forEach(unitType => {
const row = document.createElement('tr')
const tipo = unitType.unitType.descripcion
row.innerHTML = [
`<td>${unitType.project.descripcion}</td>`,
'<td>Todos los Operadores</td>',
`<td colspan="3">Todos l@s ${tipo.charAt(0).toUpperCase() + tipo.slice(1)}s</td>`,
`<td class="right aligned">`,
`<button class="ui red icon button remove_button unit-type" data-project="${unitType.project.id}" data-id="${unitType.unitType.id}">`,
'<i class="plus icon"></i>',
'</button>',
`</td>`
].join("\n")
table.table.querySelector('tbody').appendChild(row)
})
document.querySelectorAll('.remove_button.unit-type').forEach(button => {
button.addEventListener('click', () => {
const project_id = button.dataset.project
const unit_type_id = button.dataset.id
promotion.remove().unitType(project_id, unit_type_id)
})
})
}
static fromUnitLines(data) {
const table = new ContractTable('unit-lines_table')
data.forEach(unitLine => {
const row = document.createElement('tr')
const tipo = unitLine.tipo_unidad.descripcion
row.innerHTML = [
`<td>${unitLine.proyecto.descripcion}</td>`,
'<td>Todos los Operadores</td>',
`<td>${tipo.charAt(0).toUpperCase() + tipo.slice(1)}</td>`,
`<td colspan="2">Todas las unidades de la línea ${unitLine.nombre} - ${unitLine.tipologia}</td>`,
`<td class="right aligned">`,
`<button class="ui red icon button remove_button unit-line" data-id="${unitLine.id}">`,
'<i class="plus icon"></i>',
'</button>',
`</td>`
].join("\n")
table.table.querySelector('tbody').appendChild(row)
})
document.querySelectorAll('.remove_button.unit-line').forEach(button => {
button.addEventListener('click', () => {
const unit_line_id = button.dataset.id
promotion.remove().unitLine(unit_line_id)
})
})
}
static fromUnits(data) {
const table = new ContractTable('units_table')
data.forEach(unit => {
const row = document.createElement('tr')
const tipo = unit.proyecto_tipo_unidad.tipo_unidad.descripcion
row.innerHTML = [
`<td>${unit.proyecto_tipo_unidad.proyecto.descripcion}</td>`,
`<td>Todos los Operadores</td>`,
`<td>${tipo.charAt(0).toUpperCase() + tipo.slice(1)}</td>`,
`<td>${unit.proyecto_tipo_unidad.nombre} - ${unit.proyecto_tipo_unidad.tipologia}</td>`,
`<td>${unit.descripcion}</td>`,
`<td class="right aligned">`,
`<button class="ui red icon button remove_button unit" data-id="${unit.id}">`,
'<i class="plus icon"></i>',
'</button>',
`</td>`
].join("\n")
table.table.querySelector('tbody').appendChild(row)
})
document.querySelectorAll('.remove_button.unit').forEach(button => {
button.addEventListener('click', () => {
const unit_id = button.dataset.id
promotion.remove().unit(unit_id)
})
})
}
}
const promotion = {
ids: {
table: '',
button: {
add: ''
}
},
handlers: {
add: null
},
watch() {
return {
add: () => {
document.getElementById(promotion.ids.button.add).addEventListener('click', clickEvent => {
clickEvent.preventDefault()
promotion.handlers.add.show()
})
}
}
},
remove() {
return {
project: project_id => {
const url = `{{$urls->api}}/ventas/promotion/{{ $promotion->id }}/connections/project/${project_id}`
const method = 'delete'
return APIClient.fetch(url, {method}).then(response => response.json()).then(json => {
if (json.success) {
window.location.reload()
}
})
},
contract: contract_id => {
const url = `{{$urls->api}}/ventas/promotion/{{ $promotion->id }}/connections/contract/${contract_id}`
const method = 'delete'
return APIClient.fetch(url, {method}).then(response => response.json()).then(json => {
if (json.success) {
window.location.reload()
}
})
},
unitType: (project_id, unit_type_id) => {
const url = `{{$urls->api}}/ventas/promotion/{{ $promotion->id }}/connections/unit-type/${project_id}/${unit_type_id}`
const method = 'delete'
return APIClient.fetch(url, {method}).then(response => response.json()).then(json => {
if (json.success) {
window.location.reload()
}
})
},
unitLine: unit_line_id => {
const url = `{{$urls->api}}/ventas/promotion/{{ $promotion->id }}/connections/unit-line/${unit_line_id}`
const method = 'delete'
return APIClient.fetch(url, {method}).then(response => response.json()).then(json => {
if (json.success) {
window.location.reload()
}
})
},
unit: unit_id => {
const url = `{{$urls->api}}/ventas/promotion/{{ $promotion->id }}/connections/unit/${unit_id}`
const method = 'delete'
return APIClient.fetch(url, {method}).then(response => response.json()).then(json => {
if (json.success) {
window.location.reload()
}
})
}
}
},
execute() {},
setup(ids) {
this.ids = ids
this.handlers.add = new AddModal()
$(`#${this.ids.menu} .item`).tab()
this.watch().add()
@if (count($promotion->projects()) > 0)
ContractTable.fromProjects({!! json_encode($promotion->projects()) !!})
@else
ContractTable.fromProjects([])
@endif
@if (count($promotion->contracts()) > 0)
ContractTable.fromBrokers({!! json_encode(array_map(function($contract) {$arr = json_decode(json_encode($contract));$arr['project'] = $contract->project; $arr['broker'] = $contract->broker;},$promotion->contracts())) !!})
@else
ContractTable.fromBrokers([])
@endif
@if (count($promotion->unitTypes()) > 0)
ContractTable.fromUnitTypes({!! json_encode($promotion->unitTypes()) !!})
@else
ContractTable.fromUnitTypes([])
@endif
@if (count($promotion->unitLines()) > 0)
ContractTable.fromUnitLines({!! json_encode($promotion->unitLines()) !!})
@else
ContractTable.fromUnitLines([])
@endif
@if (count($promotion->units()) > 0)
ContractTable.fromUnits({!! json_encode($promotion->units()) !!})
@else
ContractTable.fromUnits([])
@endif
}
}
$(document).ready(() => {
promotion.setup({
menu: 'tables_tab_menu',
table: 'contracts',
button: {
add: 'add_button'
}
})
})
</script>
@endpush

View File

@ -1,2 +1,288 @@
<div class="ui modal" id="add_connection_modal">
<div class="header">
Agregar
</div>
<div class="content">
<form class="ui form" id="add_connection_form">
<input type="hidden" name="promotion_id" value="{{$promotion->id}}" />
<div class="field" id="type">
<label>Tipo</label>
@foreach (['Proyecto' => 'project', 'Operador' => 'operator', 'Tipo' => 'type', 'Línea' => 'line', 'Unidad' => 'unit'] as $type => $value)
<div class="ui radio checkbox type" data-tab="{{ $value }}">
<input type="radio" name="type" value="{{$value}}" @if ($value === 'project') checked="checked"@endif />
<label>{{$type}}</label>
</div>
@endforeach
</div>
<div class="ui active tab segment" data-tab="project">
<div class="field">
<label>Proyecto</label>
<div class="ui search multiple selection dropdown" id="project">
<input type="hidden" name="project[]" />
<i class="dropdown icon"></i>
<div class="default text">Proyecto</div>
<div class="menu">
@foreach ($projects as $project)
<div class="item" data-value="{{$project->id}}">{{$project->descripcion}}</div>
@endforeach
</div>
</div>
</div>
</div>
<div class="ui tab segment" data-tab="operator">
<div class="field">
<label>Operador</label>
<div class="ui search multiple selection dropdown" id="operator">
<input type="hidden" name="operator[]" />
<i class="dropdown icon"></i>
<div class="default text">Operador</div>
<div class="menu">
@foreach ($contracts as $contract)
<div class="item" data-value="{{$contract->id}}">{{$contract->broker->name}} - {{$contract->project->descripcion}}</div>
@endforeach
</div>
</div>
</div>
</div>
<div class="ui tab segment" data-tab="type">
<div class="fields">
<div class="six wide field">
<label>Proyecto</label>
<div class="ui search selection dropdown" id="type_project">
<input type="hidden" name="type_project" />
<i class="dropdown icon"></i>
<div class="default text">Proyecto</div>
<div class="menu">
@foreach ($projects as $project)
<div class="item" data-value="{{$project->id}}">{{$project->descripcion}}</div>
@endforeach
</div>
</div>
</div>
<div class="six wide field">
<label>Tipo</label>
<div class="ui search multiple selection dropdown" id="unit_type">
<input type="hidden" name="unit_type[]" />
<i class="dropdown icon"></i>
<div class="default text">Tipo</div>
<div class="menu"></div>
</div>
</div>
</div>
</div>
<div class="ui tab segment" data-tab="line">
<div class="fields">
<div class="six wide field">
<label>Proyecto</label>
<div class="ui search selection dropdown" id="line_project">
<input type="hidden" name="line_project" />
<i class="dropdown icon"></i>
<div class="default text">Proyecto</div>
<div class="menu">
@foreach ($projects as $project)
<div class="item" data-value="{{$project->id}}">{{$project->descripcion}}</div>
@endforeach
</div>
</div>
</div>
<div class="six wide field">
<label>Línea</label>
<div class="ui search multiple selection dropdown" id="line">
<input type="hidden" name="line[]" />
<i class="dropdown icon"></i>
<div class="default text">Línea</div>
<div class="menu"></div>
</div>
</div>
</div>
</div>
<div class="ui tab segment" data-tab="unit">
<div class="fields">
<div class="six wide field">
<label>Proyecto</label>
<div class="ui search selection dropdown" id="unit_project">
<input type="hidden" name="unit_project" />
<i class="dropdown icon"></i>
<div class="default text">Proyecto</div>
<div class="menu">
@foreach ($projects as $project)
<div class="item" data-value="{{$project->id}}">{{$project->descripcion}}</div>
@endforeach
</div>
</div>
</div>
<div class="six wide field">
<label>Unidad</label>
<div class="ui search multiple selection dropdown" id="unit">
<input type="hidden" name="unit[]" />
<i class="dropdown icon"></i>
<div class="default text">Unidad</div>
<div class="menu"></div>
</div>
</div>
</div>
</div>
</form>
</div>
<div class="actions">
<div class="ui black deny button">
Cancelar
</div>
<div class="ui positive right labeled icon button">
Guardar
<i class="checkmark icon"></i>
</div>
</div>
</div>
@push('page_scripts')
<script>
class AddModal {
ids
modal
units = []
constructor() {
this.ids = {
form: 'add_connection_form',
modal: 'add_connection_modal',
radios: '#type .ui.radio.checkbox.type',
type_project: 'type_project',
unit_type: 'unit_type',
line_project: 'line_project',
line: 'line',
unit_project: 'unit_project',
unit: 'unit',
operator: 'operator'
}
this.modal = $(`#${this.ids.modal}`).modal({
onApprove: () => {
const form = document.getElementById(this.ids.form)
const body = new FormData(form)
const url = `{{$urls->api}}/ventas/promotion/{{$promotion->id}}/connections/add`
const method = 'post'
return APIClient.fetch(url, {method, body}).then(response => response.json()).then(json => {
if (json.success) {
window.location.reload()
}
})
}
})
$(`#${this.ids.form} ${this.ids.radios}`).checkbox({
fireOnInit: true,
onChecked: () => {
$(`#${this.ids.form} ${this.ids.radios}`).each((index, radio) => {
if ($(radio).checkbox('is checked')) {
const tab = radio.dataset.tab
$.tab('change tab', tab)
}
})
}
})
$('.ui.dropdown').dropdown()
const typeProject = $(`#${this.ids.type_project}`)
typeProject.dropdown('clear', false)
typeProject.dropdown({
onChange: (value, text, $choice) => {
this.draw().types(value)
}
})
const lineProject = $(`#${this.ids.line_project}`)
lineProject.dropdown('clear', false)
lineProject.dropdown({
onChange: (value, text, $choice) => {
this.draw().lines(value)
}
})
const unitProject = $(`#${this.ids.unit_project}`)
unitProject.dropdown('clear', false)
unitProject.dropdown({
onChange: (value, text, $choice) => {
this.draw().units(value)
}
})
}
show() {
this.modal.modal('show')
}
draw() {
return {
types: project_id => {
this.load().units(project_id).then(() => {
const values = []
this.units[project_id].forEach(unit => {
const tipo = unit.proyecto_tipo_unidad.tipo_unidad
if (values.find(value => value.value === tipo.id)) return
const label = `${tipo.descripcion.charAt(0).toUpperCase() + tipo.descripcion.slice(1)}`
values.push( {
value: tipo.id,
text: label,
name: label
} )
})
$(`#${this.ids.unit_type}`).dropdown('change values', values)
})
},
lines: project_id => {
this.load().units(project_id).then(() => {
const values = []
this.units[project_id].forEach(unit => {
const tipo = unit.proyecto_tipo_unidad.tipo_unidad
const linea = unit.proyecto_tipo_unidad
if (values.find(value => value.value === linea.id)) return
let name = linea.nombre
if (!linea.nombre.includes(tipo.descripcion.charAt(0).toUpperCase() + tipo.descripcion.slice(1))) {
name = `${tipo.descripcion.charAt(0).toUpperCase() + tipo.descripcion.slice(1)} ${name}`
}
const label = `${name} - ${linea.tipologia}`
values.push( {
value: linea.id,
text: label,
name: label
} )
})
$(`#${this.ids.line}`).dropdown('change values', values)
})
},
units: project_id => {
this.load().units(project_id).then(() => {
const values = this.units[project_id].map(unit => {
const tipo = unit.proyecto_tipo_unidad.tipo_unidad.descripcion
const label = `${tipo.charAt(0).toUpperCase() + tipo.slice(1)} - ${unit.descripcion}`
return {
value: unit.id,
text: label,
name: label
}
})
$(`#${this.ids.unit}`).dropdown('change values', values)
})
}
}
}
load() {
return {
units: project_id => {
if (typeof this.units[project_id] !== 'undefined' && this.units[project_id].length > 0) {
return new Promise( resolve => resolve(this.units[project_id]) )
}
const url = `{{ $urls->api }}/proyecto/${project_id}/unidades`
return APIClient.fetch(url).then(response => response.json()).then(json => {
if (json.unidades.length === 0) {
throw new Error('No se encontraron unidades')
}
const units = []
Object.values(json.unidades).forEach(unidades => {
unidades.forEach(unit => {
units.push(unit)
})
})
this.units[project_id] = units
return units
})
}
}
}
}
</script>
@endpush