HEX
Server: Apache/2.4.41 (Ubuntu)
System: Linux ip-172-31-42-149 5.15.0-1084-aws #91~20.04.1-Ubuntu SMP Fri May 2 07:00:04 UTC 2025 aarch64
User: ubuntu (1000)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: /var/www/vhost/disk-apps/alq-webapp-boleteria/src/views/Tickets.vue
<template>
  <div>
    <Header></Header>
    <div class="container marketing">
      <br>
      <div class="row featurette">
        <div class="col-md-7 order-md-2">
          <h2 class="featurette-heading">Hola {{user.first_name}}. <span class="text-muted">Boletería DIM ahora también aquí.</span></h2>
          <p class="lead">Este es un nuevo portal en donde podrás realizar la compra de boletería DIM.</p>
        </div>
        <div class="col-md-5 order-md-1">
          <br><br>
          <img src="@/assets/stadium.png" alt="" height="300" width="350" class="mx-auto">
          <!-- <svg class="bd-placeholder-img bd-placeholder-img-lg featurette-image img-fluid mx-auto" width="500" height="500" xmlns="@/assets/stadium.png" role="img" aria-label="Placeholder: 500x500" preserveAspectRatio="xMidYMid slice" focusable="false"><title>Placeholder</title><rect width="100%" height="100%" fill="#eee"></rect><text x="50%" y="50%" fill="#aaa" dy=".3em">500x500</text></svg> -->
        </div>
      </div>
      <hr class="featurette-divider">
    </div>

    <div class="container">
      <main>

        <!-- Message -->
        <div class="py-5 text-center">
          <h2>Tickets</h2>
          <p class="lead">Escoge todas las sillas que deseas y procede con el proceso de compra por medios digitales.</p>
        </div>

        <div class="row g-5">

          <!-- Tickets -->
          <div class="col-md-5 col-lg-4 order-md-last">
            <h4 class="d-flex justify-content-between align-items-center mb-3">
              <span class="text-primary">Tus Tickets</span>
              <span><span class="badge bg-primary rounded-pill">{{quantityTickets}}</span>  <fa icon="trash-can" color="red" v-on:click="getStart()" /></span>
            </h4>
            <ul class="list-group mb-3">
              <div v-if="quantityTickets == 0">
                <li class="list-group-item d-flex justify-content-between">
                  <div>
                    <h6 class="my-0">Ningún Ticket seleccionado</h6>
                  </div>
                </li>
              </div>
              <div v-else>
                <li v-for="ticket in ticketsSelected" :key="ticket" class="list-group-item d-flex justify-content-between lh-sm">
                  <div><fa icon="trash" color="black" v-on:click="deleteTicket(ticket)" /></div>
                  <div>
                    <h6 class="my-0">{{ticket.Event.name}}</h6>
                    <small class="text-muted">{{ticket.Tribuna}} - {{ticket.Zone.name.split('_')[0]}} {{ticket.Zone.name.split('_')[1]}} - {{ticket.Seat.letter.name}}{{ticket.Seat.code}}</small>
                  </div>
                  <span class="text-muted">$ {{new Intl.NumberFormat().format(ticket.Price)}}</span>
                </li>
              </div>
              <li class="list-group-item d-flex justify-content-between">
                <strong><span>Total (COP)</span></strong>
                <strong>$ {{new Intl.NumberFormat().format(totalToPay)}}</strong>
              </li>
            </ul>

            <div class="card p-2">
                <button type="button" class="btn btn-primary aling-center btn-lg" v-on:click="goToPay()">Pagar</button>
            </div>
          </div>

          <!-- Choose seat -->
          <div class="col-md-7 col-lg-8">
            <h4 class="mb-3">Selecciona silla</h4>
            <form class="needs-validation" validate>

              <div class="row g-3">
                <div class="col-12">
                  <label for="event" class="form-label">Partido</label>
                  <select class="form-select" id="event" v-model="eventSelected" required>
                    <option value="">Seleccionar...</option>
                    <option v-for="event in events" :value="event" :key="event.id">{{event.name}} - {{new Date(event.event_start)}}</option>
                  </select>
                </div>
              </div><br>

              <div class="row g-3">
                <div class="col-12">
                  <label for="event" class="form-label">Tribuna</label>
                  <select @change="selectTribuna($event)" v-model="tribunaSelected" class="form-select" id="event" required>
                    <option value="">Seleccionar...</option>
                    <option value="4">Norte</option>
                    <option value="5">Sur</option>
                    <option value="3">Oriental</option>
                    <option value="2">Occidental</option>
                  </select>
                </div>
              </div><br>

              <div class="row g-3">
                <div class="col-12">
                  <label for="event" class="form-label">Sector</label>
                  <select @change="selectSubZone($event)" v-model="subZoneSelected" class="form-select" id="event" required>
                    <option value="">Seleccionar...</option>
                    <option v-for="sub_zone in sub_zones" :value="sub_zone" :key="sub_zone.id">{{sub_zone.name.split('_')[0]}} {{sub_zone.name.split('_')[1]}}</option>
                  </select>
                </div>
              </div><br>

              <div class="row g-3">
                <div class="col-12">
                  <label for="event" class="form-label">Silla</label>
                  <select v-model="seatSelected" class="form-select" id="event" required>
                    <option value="">Seleccionar...</option>
                    <option v-for="seat in seats" :value="seat" :key="seat.id">{{seat.letter.name}} - {{seat.code}}</option>
                  </select>
                </div>
              </div>

              <hr class="my-4">

              <button class="w-100 btn btn-success btn-lg" type="button" v-on:click="addTicket()">Agregar silla</button>

            </form>
          </div>
        </div>
      </main>
    </div>
    <Footer></Footer>
  </div>
</template>

<script>

import Header from '@/components/Header.vue'
import Footer from '@/components/Footer.vue'
import axios from 'axios'

const urlApi = 'https://alq-cali.bikenow.co/api/'
const urlAdmin = 'https://alq-cali.bikenow.co/'

export default {
  name: 'Tickets',
  components: {
    Header,
    Footer
  },
  data: function () {
    return {
      user: JSON.parse(localStorage.user_info),
      events: [],
      sub_zones: [],
      seats: [],
      eventSelected: '',
      tribunaSelected: '',
      subZoneSelected: '',
      seatSelected: '',
      ticketsSelected: [],
      quantityTickets: 0,
      totalToPay: 0,
      tickets_to_pay: [],
      priceSeatSelected: Number
    }
  },
  mounted: function () {
    const config = {
      headers: { Authorization: `Bearer ${localStorage.token}` }
    }
    axios.get(urlApi + 'tickets/match_events', config)
      .then(matchEvents => {
        matchEvents.data.forEach(element => {
          if (new Date(Date.now()) >= new Date(element.event_start_sale) && new Date(Date.now()) <= new Date(element.event_end_sale)) {
            this.events.push(element)
          }
        })
        // console.log(this.events)
      })
  },
  methods: {
    selectTribuna () {
      this.subZoneSelected = ''
      this.seatSelected = ''
      this.sub_zones = []
      this.seats = []
      axios.get(urlApi + 'tickets/get_sub_zones/' + event.target.value, { headers: { Authorization: `Bearer ${localStorage.token}` } })
        .then(subZones => {
          if (subZones.data.r) {
            // console.log('Sub Zones: ' + subZones.data.data)
            this.sub_zones = subZones.data.data
          } else {
            console.log('Error getting sub_zones: ' + subZones.data)
          }
        })
    },
    selectSubZone () {
      this.seatSelected = ''
      this.seats = []
      axios.get(urlApi + 'tickets/get_seats/' + this.subZoneSelected.id + '/' + this.eventSelected.id, { headers: { Authorization: `Bearer ${localStorage.token}` } })
        .then(seats => {
          if (seats.data.original.r) {
            // console.log('Seats: ' + seats.data.original.data)
            seats.data.original.data.forEach(element => {
              if (!element.ticket && !element.ticket_user_block) {
                this.seats.push(element)
              }
            })
          } else {
            console.log('Error getting seats: ' + seats.data.original)
            this.$swal('Zona no disponible para la venta')
          }
        })
    },
    addTicket () {
      // Validaciones
      if (!this.eventSelected) {
        this.$swal('Por favor selecciona un partido')
        return
      }
      if (!this.tribunaSelected) {
        this.$swal('Por favor selecciona una tribuna')
        return
      }
      if (!this.subZoneSelected) {
        this.$swal('Por favor selecciona una zona')
        return
      }
      if (!this.seatSelected) {
        this.$swal('Por favor selecciona una silla')
        return
      }
      // Verifica que el ticket sea del mismo partido, tribuna y sector
      if (this.ticketsSelected.length !== 0) {
        if (this.ticketsSelected[0].Event.id !== this.eventSelected.id || this.ticketsSelected[0].Zone.id !== this.subZoneSelected.id) {
          this.$swal('Solo puedes agregar tickets correspondientes al mismo partido, a la misma tribuna y a la misma zona ya agregada')
          return
        }
      }

      let tribuna
      let ticketsEqual = 0
      // Valida precio
      axios.get(urlApi + 'tickets/get_seat_price/' + this.subZoneSelected.id + '/' + this.eventSelected.id, { headers: { Authorization: `Bearer ${localStorage.token}` } })
        .then(seatsPrice => {
          // console.log(seatsPrice)
          if (seatsPrice.data.original.r) {
            // Verifica tickets escogidos
            this.ticketsSelected.forEach(item => {
              if (item.Event.id === this.eventSelected.id && item.Seat.id === this.seatSelected.id) {
                ticketsEqual = ticketsEqual + 1
              }
            })
            // Valida si el ticket no ha sido escogido
            if (ticketsEqual === 0) {
              this.priceSeatSelected = seatsPrice.data.original.data.price
              // Organiza elemento
              if (this.tribunaSelected === '2') {
                tribuna = 'Occidental'
              }
              if (this.tribunaSelected === '3') {
                tribuna = 'Oriental'
              }
              if (this.tribunaSelected === '4') {
                tribuna = 'Norte'
              }
              if (this.tribunaSelected === '5') {
                tribuna = 'Sur'
              }
              this.ticketsSelected.push({ Event: this.eventSelected, Tribuna: tribuna, Zone: this.subZoneSelected, Seat: this.seatSelected, Price: this.priceSeatSelected })
              this.tickets_to_pay.push({
                seat: this.seatSelected,
                match_event_id: this.eventSelected.id,
                ticket_type_id: 1,
                match_event_price: seatsPrice.data.original.data,
                zone_name: tribuna + ' - ' + this.subZoneSelected.name.split('_')[0] + ' ' + this.subZoneSelected.name.split('_')[1]
              })
              this.quantityTickets = this.quantityTickets + 1
              this.totalToPay = this.totalToPay + this.priceSeatSelected
              this.seatSelected = ''
            } else {
              this.$swal('Este ticket ya ha sido agregado')
              this.seatSelected = ''
            }
          } else {
            console.log('Error getting seatsPrice: ' + seatsPrice.data.original.m)
            this.$swal(seatsPrice.data.original.m)
            this.seatSelected = ''
          }
        })
    },
    goToPay () {
      if (this.quantityTickets === 0) {
        this.$swal('Primero agrega un ticket')
        return
      }
      this.$swal({
        title: '¿Seguro que deseas realizar la compra?',
        showDenyButton: true,
        confirmButtonText: 'Si',
        icon: 'question',
        showClass: {
          popup: 'animate__animated animate__fadeInDown'
        },
        hideClass: {
          popup: 'animate__animated animate__fadeOutUp'
        }
      }).then((result) => {
        if (result.isConfirmed) {
          const info = {
            tickets: this.tickets_to_pay,
            type_process: 'block',
            amount: this.totalToPay,
            ticket_type_id: 1,
            tournament_id: 1
          }
          console.log(info)
          console.log(this.ticketsSelected)
          console.log(this.totalToPay)
          console.log(this.tickets_to_pay)
          axios.post(urlApi + 'tickets/createBlocks', info, { headers: { Authorization: `Bearer ${localStorage.token}` } })
            .then(response => {
              if (response.data.r) {
                console.log(response.data)
                window.open(urlAdmin + 'tickets/purchase?id=' + response.data.data, '_blank')
                this.getStart()
                this.$swal(response.data.m)
              } else {
                console.log(response.data)
                this.$swal(response.data.m)
              }
            })
        }
      })
    },
    getStart () {
      this.eventSelected = ''
      this.tribunaSelected = ''
      this.subZoneSelected = ''
      this.seatSelected = ''
      this.ticketsSelected = []
      this.quantityTickets = 0
      this.totalToPay = 0
      this.tickets_to_pay = []
    },
    deleteTicket (ticketDelete) {
      this.tickets_to_pay = this.tickets_to_pay.filter(function (ticket) {
        return (ticket.seat.id !== ticketDelete.Seat.id && ticket.match_event_id === ticketDelete.Event.id) || ticket.match_event_id !== ticketDelete.Event.id
      })
      this.ticketsSelected = this.ticketsSelected.filter(function (ticket) {
        return (ticket.Seat.id !== ticketDelete.Seat.id && ticket.Event.id === ticketDelete.Event.id) || ticket.Event.id !== ticketDelete.Event.id
      })
      this.quantityTickets = 0
      this.totalToPay = 0
      this.tickets_to_pay.forEach(element => {
        this.quantityTickets = this.quantityTickets + 1
        this.totalToPay = this.totalToPay + element.match_event_price.price
      })
    }
  }
}
</script>

<style scoped>

/* GLOBAL STYLES
-------------------------------------------------- */
/* Padding below the footer and lighter body text */

body {
  padding-top: 3rem;
  padding-bottom: 3rem;
  color: #5a5a5a;
}

/* CUSTOMIZE THE CAROUSEL
-------------------------------------------------- */

/* Carousel base class */
.carousel {
  margin-bottom: 4rem;
}
/* Since positioning the image, we need to help out the caption */
.carousel-caption {
  bottom: 3rem;
  z-index: 10;
}

/* Declare heights because of positioning of img element */
.carousel-item {
  height: 32rem;
}
.carousel-item > img {
  position: absolute;
  top: 0;
  left: 0;
  min-width: 100%;
  height: 32rem;
}

/* MARKETING CONTENT
-------------------------------------------------- */

/* Center align the text within the three columns below the carousel */
.marketing .col-lg-4 {
  margin-bottom: 1.5rem;
  text-align: center;
}
.marketing h2 {
  font-weight: 400;
}
/* rtl:begin:ignore */
.marketing .col-lg-4 p {
  margin-right: .75rem;
  margin-left: .75rem;
}
/* rtl:end:ignore */

/* Featurettes
------------------------- */

.featurette-divider {
  margin: 5rem 0; /* Space out the Bootstrap <hr> more */
}

/* Thin out the marketing headings */
.featurette-heading {
  font-weight: 300;
  line-height: 1;
  /* rtl:remove */
  letter-spacing: -.05rem;
}

/* RESPONSIVE CSS
-------------------------------------------------- */

@media (min-width: 40em) {
  /* Bump up size of carousel content */
  .carousel-caption p {
    margin-bottom: 1.25rem;
    font-size: 1.25rem;
    line-height: 1.4;
  }

  .featurette-heading {
    font-size: 50px;
  }
}

@media (min-width: 62em) {
  .featurette-heading {
    margin-top: 7rem;
  }
}

</style>