Agregar, editar y eliminar promociones

This commit is contained in:
Juan Pablo Vial
2025-03-18 19:12:59 -03:00
parent 39c148b7b3
commit 2b3f476df7
11 changed files with 610 additions and 0 deletions

View File

@ -0,0 +1,172 @@
@extends('ventas.promotions.base')
@section('promotions_content')
<table class="ui table" id="promotions">
<thead>
<tr>
<th>Promoción</th>
<th>Tipo</th>
<th>Valor</th>
<th>Fecha Inicio</th>
<th>Fecha Término</th>
<th>Válido Hasta</th>
<th>Contratos</th>
<th class="right aligned">
<button type="button" class="ui small tertiary green icon button" id="add_button">
<i class="plus icon"></i>
</button>
</th>
</tr>
</thead>
<tbody>
@foreach($promotions as $promotion)
<tr>
<td>
<a href="{{ $urls->base }}/ventas/promotion/{{ $promotion->id }}">
{{ $promotion->description }}
</a>
</td>
<td>{{ ucwords($promotion->type->name()) }}</td>
<td>{{ ($promotion->type === Incoviba\Model\Venta\Promotion\Type::FIXED) ? $format->ufs($promotion->amount) : $format->percent($promotion->amount, 2, true) }}</td>
<td>{{ $promotion->startDate->format('d-m-Y') }}</td>
<td>{{ $promotion->endDate?->format('d-m-Y') }}</td>
<td>{{ $promotion->validUntil?->format('d-m-Y') }}</td>
<td>
Proyectos: {{ count(array_unique(array_map(function ($contract) { return $contract->project->descripcion; }, $promotion->contracts()))) }} <br />
Operadores: {{ count(array_unique(array_map(function ($contract) { return $contract->broker->name; }, $promotion->contracts()))) }}
</td>
<td class="right aligned">
<button type="button" class="ui small tertiary icon button edit_button" data-id="{{ $promotion->id }}">
<i class="edit icon"></i>
</button>
<button type="button" class="ui red small tertiary icon button remove_button" data-id="{{ $promotion->id }}">
<i class="trash icon"></i>
</button>
</td>
</tr>
@endforeach
</tbody>
</table>
@include('ventas.promotions.add_modal')
@include('ventas.promotions.edit_modal')
@endsection
@push('page_scripts')
<script>
const promotions = {
ids: {
buttons: {
add: '',
edit: '',
remove: ''
},
},
handlers: {
add: null,
edit: null,
},
data: JSON.parse('{!! json_encode($promotions) !!}'),
execute() {
return {
add: data => {
const url = '{{$urls->api}}/ventas/promotions/add'
const method = 'post'
const body = new FormData()
body.set('promotions[]', JSON.stringify(data))
return APIClient.fetch(url, {method, body}).then(response => {
if (!response) {
console.error(response.errors)
alert('No se pudo agregar promoción.')
return
}
return response.json().then(json => {
if (!json.success) {
console.error(json.errors)
alert('No se pudo agregar promoción.')
return
}
window.location.reload()
})
})
},
edit: data => {
const url = '{{$urls->api}}/ventas/promotions/edit'
const method = 'post'
const body = new FormData()
body.set('promotions[]', JSON.stringify(data))
return APIClient.fetch(url, {method, body}).then(response => {
if (!response) {
console.error(response.errors)
alert('No se pudo editar promoción.')
return
}
return response.json().then(json => {
if (!json.success) {
console.error(json.errors)
alert('No se pudo editar promoción.')
return
}
window.location.reload()
})
})
},
remove: promotion_id => {
const url = `{{$urls->api}}/ventas/promotion/${promotion_id}/remove`
const method = 'delete'
return APIClient.fetch(url, {method}).then(response => {
if (!response) {
console.error(response.errors)
alert('No se pudo eliminar promoción.')
return
}
return response.json().then(json => {
if (!json.success) {
console.error(json.errors)
alert('No se pudo eliminar promoción.')
return
}
window.location.reload()
})
})
}
}
},
watch() {
document.getElementById(promotions.ids.buttons.add).addEventListener('click', clickEvent => {
clickEvent.preventDefault()
promotions.handlers.add.show()
})
Array.from(document.getElementsByClassName(promotions.ids.buttons.edit)).forEach(button => {
button.addEventListener('click', clickEvent => {
const id = clickEvent.currentTarget.dataset.id
promotions.handlers.edit.load(id)
})
})
Array.from(document.getElementsByClassName(promotions.ids.buttons.remove)).forEach(button => {
button.addEventListener('click', clickEvent => {
clickEvent.preventDefault()
const id = clickEvent.currentTarget.dataset.id
promotions.execute().remove(id)
})
})
},
setup(ids) {
promotions.ids = ids
promotions.handlers.add = new AddModal()
promotions.handlers.edit = new EditModal(promotions.data)
promotions.watch()
}
}
$(document).ready(() => {
promotions.setup({
buttons: {
add: 'add_button',
edit: 'edit_button',
remove: 'remove_button'
}
})
})
</script>
@endpush

View File

@ -0,0 +1,100 @@
<div class="ui modal" id="add_promotion_modal">
<div class="header">
Agregar Promoción
</div>
<div class="content">
<form class="ui form" id="add_promotion_form">
<div class="field">
<label for="description">Descripción</label>
<input type="text" id="description" name="description" placeholder="Descripción" required />
</div>
<div class="fields">
<div class="field">
<label for="type">Tipo</label>
<select id="type" name="type" class="ui select dropdown" required>
<option value="1">Valor Fijo</option>
<option value="2">Valor Variable</option>
</select>
</div>
<div class="field">
<label for="value">Valor</label>
<input type="text" id="value" name="value" placeholder="Valor" required />
</div>
</div>
<div class="fields">
<div class="field">
<label for="start_date">Fecha de Inicio</label>
<div class="ui calendar" id="start_date">
<div class="ui left icon input">
<i class="calendar icon"></i>
<input type="text" name="start_date" placeholder="Fecha de Inicio" required />
</div>
</div>
</div>
<div class="field">
<label for="end_date">Fecha de Término</label>
<div class="ui calendar" id="end_date">
<div class="ui left icon input">
<i class="calendar icon"></i>
<input type="text" name="end_date" placeholder="Fecha de Término" />
</div>
</div>
</div>
<div class="field">
<label for="valid_range">Válido por N Días Después del Término</label>
<input type="text" id="valid_range" name="valid_range" placeholder="Válido por N Días" value="7" required />
</div>
</div>
</form>
</div>
<div class="actions">
<div class="ui black deny button">
Cancelar
</div>
<div class="ui positive right labeled icon button">
Agregar
<i class="checkmark icon"></i>
</div>
</div>
@push('page_scripts')
<script>
class AddModal {
ids = {
modal: '#add_promotion_modal',
}
modal
constructor() {
this.modal = $(this.ids.modal)
this.modal.find('.ui.dropdown').dropdown()
this.modal.find('.ui.calendar').calendar(calendar_date_options)
this.modal.modal({
onApprove: () => {
const form = document.getElementById('add_promotion_form')
const type = $(form.querySelector('[name="type"]')).dropdown('get value')
const start_date = $(form.querySelector('#start_date')).calendar('get date')
const end_date = $(form.querySelector('#end_date')).calendar('get date')
let valid_until = null
if (end_date !== null) {
valid_until = new Date(end_date)
valid_until.setDate(valid_until.getDate() + parseInt(form.querySelector('[name="valid_range"]').value))
}
const data = {
description: form.querySelector('[name="description"]').value,
type,
value: form.querySelector('[name="value"]').value,
start_date: [start_date.getFullYear(), start_date.getMonth() + 1, start_date.getDate()].join('-'),
end_date: end_date === null ? null : [end_date.getFullYear(), end_date.getMonth() + 1, end_date.getDate()].join('-'),
valid_until: valid_until === null ? null : [valid_until.getFullYear(), valid_until.getMonth() + 1, valid_until.getDate()].join('-'),
}
promotions.execute().add(data)
}
})
}
show() {
this.modal.modal('show')
}
}
</script>
@endpush

View File

@ -0,0 +1,10 @@
@extends('layout.base')
@section('page_content')
<div class="ui container">
<h2 class="ui header">
Promociones
</h2>
@yield('promotions_content')
</div>
@endsection

View File

@ -0,0 +1,126 @@
<div class="ui modal" id="edit_promotion_modal">
<div class="header">
Editar Promoción - <span class="description"></span>
</div>
<div class="content">
<form class="ui form" id="edit_promotion_form">
<input type="hidden" name="id" />
<div class="field">
<label for="description">Descripción</label>
<input type="text" id="description" name="description" placeholder="Descripción" required />
</div>
<div class="fields">
<div class="field">
<label for="type">Tipo</label>
<select id="type" name="type" class="ui select dropdown" required>
<option value="1">Valor Fijo</option>
<option value="2">Valor Variable</option>
</select>
</div>
<div class="field">
<label for="value">Valor</label>
<input type="text" id="value" name="value" placeholder="Valor" required />
</div>
</div>
<div class="fields">
<div class="field">
<label for="edit_start_date">Fecha de Inicio</label>
<div class="ui calendar" id="edit_start_date">
<div class="ui left icon input">
<i class="calendar icon"></i>
<input type="text" name="edit_start_date" placeholder="Fecha de Inicio" required />
</div>
</div>
</div>
<div class="field">
<label for="edit_end_date">Fecha de Término</label>
<div class="ui calendar" id="edit_end_date">
<div class="ui left icon input">
<i class="calendar icon"></i>
<input type="text" name="edit_end_date" placeholder="Fecha de Término" />
</div>
</div>
</div>
<div class="field">
<label for="valid_range">Válido por N Días Después del Término</label>
<input type="text" id="valid_range" name="valid_range" placeholder="Válido por N Días" value="7" required />
</div>
</div>
</form>
</div>
<div class="actions">
<div class="ui black deny button">
Cancelar
</div>
<div class="ui positive right labeled icon button">
Editar
<i class="checkmark icon"></i>
</div>
</div>
@push('page_scripts')
<script>
class EditModal {
ids = {
modal: '#edit_promotion_modal',
}
modal
promotions
constructor(data) {
this.promotions = data
this.modal = $(this.ids.modal)
this.modal.find('.ui.dropdown').dropdown()
this.modal.find('.ui.calendar').calendar(calendar_date_options)
this.modal.modal({
onApprove: () => {
const form = document.getElementById('edit_promotion_form')
const type = $(form.querySelector('[name="type"]')).dropdown('get value')
const start_date = $(form.querySelector('#edit_start_date')).calendar('get date')
const end_date = $(form.querySelector('#edit_end_date')).calendar('get date')
let valid_until = null
if (end_date !== null) {
valid_until = new Date(end_date)
valid_until.setDate(valid_until.getDate() + parseInt(form.querySelector('[name="valid_range"]').value))
}
const data = {
id: form.querySelector('[name="id"]').value,
description: form.querySelector('[name="description"]').value,
type,
value: form.querySelector('[name="value"]').value,
start_date: [start_date.getFullYear(), start_date.getMonth() + 1, start_date.getDate()].join('-'),
end_date: end_date === null ? null : [end_date.getFullYear(), end_date.getMonth() + 1, end_date.getDate()].join('-'),
valid_until: valid_until === null ? null : [valid_until.getFullYear(), valid_until.getMonth() + 1, valid_until.getDate()].join('-'),
}
promotions.execute().edit(data)
}
})
}
load(promotion_id) {
const promotion = this.promotions.find(promotion => promotion.id === parseInt(promotion_id))
const form = document.getElementById('edit_promotion_form')
form.reset()
form.querySelector('[name="id"]').value = promotion.id
form.querySelector('[name="description"]').value = promotion.description
form.querySelector('[name="type"]').value = promotion.type
form.querySelector('[name="value"]').value = promotion.amount
const start_date_parts = promotion.start_date.split('-')
const start_date = new Date(start_date_parts[0], start_date_parts[1] - 1, start_date_parts[2])
$('#edit_start_date').calendar('set date', start_date)
if (promotion.end_date !== null) {
const end_date_parts = promotion.end_date.split('-')
const end_date = new Date(end_date_parts[0], end_date_parts[1] - 1, end_date_parts[2])
$('#edit_end_date').calendar('set date', end_date)
if (promotion.valid_until !== null) {
const valid_until_parts = promotion.valid_until.split('-')
const valid_until = new Date(valid_until_parts[0], valid_until_parts[1] - 1, valid_until_parts[2])
form.querySelector('[name="valid_range"]').value = valid_until.getDate() - end_date.getDate()
}
}
this.modal.modal('show')
}
}
</script>
@endpush