diff --git a/angular.json b/angular.json
index 4d7fd76..f91ed77 100644
--- a/angular.json
+++ b/angular.json
@@ -96,5 +96,8 @@
}
}
}
+ },
+ "cli": {
+ "analytics": false
}
}
diff --git a/package.json b/package.json
index d14c4d8..29b88ec 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,7 @@
"@angular/platform-browser": "^16.1.0",
"@angular/platform-browser-dynamic": "^16.1.0",
"@angular/router": "^16.1.0",
+ "creditcardpayments": "^1.0.3",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.13.0"
diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index 91ada6e..8802ab8 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -2,11 +2,19 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { EscogerRutaComponent } from './components/escoger-ruta/escoger-ruta.component';
import { CrearVueloComponent } from './components/crear-vuelo/crear-vuelo.component';
+import { LoginComponent } from './components/login/login.component';
+import { HomeComponent } from './components/home/home.component';
+import { AsientosComponent } from './components/asientos/asientos.component';
+import { PromocionesComponent } from './components/promociones/promociones.component';
const routes: Routes = [
- {path:'inicio', component:EscogerRutaComponent},
+ {path:'inicio', component:HomeComponent},
+ {path:'buscar-vuelo', component:EscogerRutaComponent},
{path:'guardar-vuelo', component:CrearVueloComponent},
- {path:'**', component:EscogerRutaComponent}];
+ {path:'login', component:LoginComponent},
+ {path:'promociones', component:PromocionesComponent},
+ {path:'**', component:HomeComponent},
+ ];
@NgModule({
imports: [RouterModule.forRoot(routes)],
diff --git a/src/app/app.component.html b/src/app/app.component.html
index a709aed..7dc820d 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -1,15 +1,3 @@
-
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 9c1402f..c092f37 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -8,13 +8,22 @@ import { HttpClientModule } from '@angular/common/http';
import { FormsModule } from '@angular/forms';
import { CrearVueloComponent } from './components/crear-vuelo/crear-vuelo.component';
import { PieComponent } from './components/pie/pie.component';
+import { LoginComponent } from './components/login/login.component';
+import { AuthService } from './services/auth.service';
+import { HomeComponent } from './components/home/home.component';
+import { PromocionesComponent } from './components/promociones/promociones.component';
+import { AsientosComponent } from './components/asientos/asientos.component';
@NgModule({
declarations: [
AppComponent,
EscogerRutaComponent,
CrearVueloComponent,
- PieComponent
+ PieComponent,
+ LoginComponent,
+ HomeComponent,
+ PromocionesComponent,
+ AsientosComponent
],
imports: [
BrowserModule,
@@ -22,7 +31,9 @@ import { PieComponent } from './components/pie/pie.component';
HttpClientModule,
FormsModule
],
- providers: [],
+ providers: [
+ AuthService
+ ],
bootstrap: [AppComponent]
})
export class AppModule { }
diff --git a/src/app/components/asientos/asientos.component.css b/src/app/components/asientos/asientos.component.css
new file mode 100644
index 0000000..49318ab
--- /dev/null
+++ b/src/app/components/asientos/asientos.component.css
@@ -0,0 +1,262 @@
+.plane {
+ margin: 20px auto;
+ max-width: 450px;
+}
+
+.cockpit {
+ height: 250px;
+ position: relative;
+ overflow: hidden;
+ text-align: center;
+ border-bottom: 5px solid #3a3939;
+
+ &:before {
+ content: "";
+ display: block;
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 700px;
+ width: 98.2%;
+ border-radius: 60%;
+ border-right: 5px solid #3a3939;
+ border-left: 5px solid #3a3939;
+ }
+
+ h1 {
+ width: 60%;
+ margin: 100px auto 35px auto;
+ }
+}
+
+.fuselage {
+ border: 5px solid #3a3939;
+ border-top: 0px;
+}
+
+ol {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.row {
+ --bs-gutter-x: 0rem;
+ --bs-gutter-y: 0;
+}
+
+.seats {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: nowrap;
+ justify-content: flex-start;
+}
+
+.seat {
+ display: flex;
+ height: 40px;
+ flex: 0 0 14.28571428571429%;
+ padding: 2px;
+ position: relative;
+
+ &:nth-child(3) {
+ margin-right: 14.28571428571429%;
+ }
+
+ input[type="checkbox"] {
+ position: absolute;
+ opacity: 0;
+ }
+
+ input[type="checkbox"]:checked {
+ +label {
+ background: #bada55;
+ -webkit-animation-name: rubberBand;
+ animation-name: rubberBand;
+ animation-duration: 300ms;
+ animation-fill-mode: both;
+ }
+ }
+
+ input[type="checkbox"]:disabled {
+ +label {
+ background: #dddddd;
+ text-indent: -9999px;
+ overflow: hidden;
+
+ &:after {
+ content: "X";
+ text-indent: 0;
+ position: absolute;
+ top: 4px;
+ left: 50%;
+ transform: translate(-50%, 0%);
+ }
+
+ &:hover {
+ box-shadow: none;
+ cursor: not-allowed;
+ }
+ }
+ }
+
+ .active {
+ background-color: green;
+ /* Estilo activado */
+ }
+
+ .inactive {
+ background-color: red;
+ /* Estilo desactivado */
+ }
+
+ label {
+ display: block;
+ position: relative;
+ width: 100%;
+ text-align: center;
+ font-size: 14px;
+ font-weight: bold;
+ line-height: 1.5rem;
+ padding: 2px 0;
+ border-radius: 5px;
+ animation-duration: 300ms;
+ animation-fill-mode: both;
+
+ &:before {
+ content: "";
+ position: absolute;
+ width: 75%;
+ height: 75%;
+ top: 1px;
+ left: 50%;
+ transform: translate(-50%, 0%);
+ background: rgb(255, 0, 0);
+ border-radius: 3px;
+ }
+
+ &:hover {
+ cursor: pointer;
+ box-shadow: 0 0 0px 2px #00ff48;
+ }
+ }
+}
+h2 {
+ font-family: 'Hug';
+ margin: 15px;
+ font-size: 12px;
+ text-align: center;
+ color: #fed809;
+}
+
+h5 {
+ font-family: 'Hug';
+ margin: 15px;
+ font-size: 13px;
+ text-align: center;
+ color: #f8770f;
+}
+
+.btn-primary {
+ font-family: 'Asap';
+ border-radius: 20px;
+ background-color: #fed809;
+ color: white;
+ align-items: center;
+ padding: 10px 20px;
+ cursor: pointer;
+ border: none;
+}
+
+.btn-danger {
+ font-family: 'Asap';
+ border-radius: 20px;
+ background-color: #e2097e;
+ color: white;
+ border: 3px #be8fa8;
+ padding: 10px 20px;
+ cursor: pointer;
+}
+
+.btn-success {
+ font-family: 'Asap';
+ border-radius: 20px;
+ background-color: white;
+ color: #e2097e;
+ border: 2px #e2097e;
+ padding: 10px 20px;
+ cursor: pointer;
+}
+
+.modal-header {
+ align-items: center;
+}
+
+.modal-title {
+ font-family: 'Hug';
+ margin: 15px;
+ font-size: 13px;
+ margin-left: 20px;
+ color: #f8770f;
+ text-align: center;
+}
+
+label {
+ margin: 2px;
+ display: inline-block;
+ font-family: 'gro';
+ font-size: 15px;
+
+}
+
+/* Estilo para etiquetas con contenido del 1A al 5F (color rosado) */
+label[for^="1"],
+label[for^="2"],
+label[for^="3"],
+label[for^="4"],
+label[for^="5"] {
+ color: #063147;
+}
+
+/* Estilo para etiquetas con contenido del 6A al 10F (color morado) */
+label[for^="6"],
+label[for^="7"],
+label[for^="8"],
+label[for^="9"],
+label[for^="10"] {
+ color: #203b06;
+}
+
+/* Estilo para la leyenda de colores */
+.legend {
+ list-style-type: none;
+ padding: 0;
+ margin: 0;
+ text-align: center;
+}
+
+/* Estilo para cada elemento de la leyenda */
+.legend li {
+ margin-bottom: 10px;
+}
+
+/* Estilo para los cuadros de colores */
+.legend-color {
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+ margin-right: 10px;
+ border: 1px solid #ffffff;
+ border-radius: 50%;
+ /* Borde alrededor de los cuadros de colores (opcional) */
+}
+
+/* Estilo para las imágenes de los asientos */
+.plane img {
+ position: absolute;
+ max-width: 40px;
+ max-height: 40px;
+ margin-left: 15px;
+ margin-bottom: 15px;
+ z-index: -1;
+}
\ No newline at end of file
diff --git a/src/app/components/asientos/asientos.component.html b/src/app/components/asientos/asientos.component.html
new file mode 100644
index 0000000..ae87885
--- /dev/null
+++ b/src/app/components/asientos/asientos.component.html
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ASIENTOS
DISPONBLES
+
+
+
+
+
+ -
+
+ -
+ = maxSelectedCheckboxes && !seat.selected || disabledCheckboxes.includes(seat.id)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/components/asientos/asientos.component.spec.ts b/src/app/components/asientos/asientos.component.spec.ts
new file mode 100644
index 0000000..52ce553
--- /dev/null
+++ b/src/app/components/asientos/asientos.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AsientosComponent } from './asientos.component';
+
+describe('AsientosComponent', () => {
+ let component: AsientosComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [AsientosComponent]
+ });
+ fixture = TestBed.createComponent(AsientosComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/components/asientos/asientos.component.ts b/src/app/components/asientos/asientos.component.ts
new file mode 100644
index 0000000..0ce932a
--- /dev/null
+++ b/src/app/components/asientos/asientos.component.ts
@@ -0,0 +1,198 @@
+import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
+
+@Component({
+ selector: 'app-asientos',
+ templateUrl: './asientos.component.html',
+ styleUrls: ['./asientos.component.css']
+})
+export class AsientosComponent implements OnInit{
+ rows: any[] = [];
+ disabledCheckboxes: string[] = [];
+ selected: number = 0;
+ isRandomActive = false;
+ public eventListenersAttached: boolean = false;
+ @Input() maxSelectedCheckboxes: number = 1;
+ @ViewChild('seatsContainer') seatsContainer!: ElementRef;
+ @Output() emitArrayAsientos = new EventEmitter();
+ allCheckboxes: HTMLInputElement[] = [];
+ habilitadoImageSrc: string = '../assets/habilitado.jpg';
+ desHabilitadoImageSrc: string = '../assets/desHabilitado.jpg';
+
+ constructor(private el: ElementRef) {
+ // Agrega las filas y asientos a la estructura
+ for (let rowNumber = 1; rowNumber <= 9; rowNumber++) {
+ const seats = ['A', 'B', 'C', 'D', 'E', 'F']; // Asientos de A a F por fila
+ const row = {
+ rowNumber: rowNumber,
+ seats: seats.map(seat => ({
+ id: `${rowNumber}${seat}`,
+ selected: true,
+ enabled: true, // Inicialmente, todos los asientos están habilitados
+ imageSrc: this.habilitadoImageSrc // Inicialmente, se muestra la imagen habilitada
+ }))
+ };
+ this.rows.push(row);
+ }
+ console.log(this.rows);
+ }
+ ngOnInit(): void {
+ this.disableCheckboxes();
+ }
+
+ toggleSeatState(seat: any) {
+ seat.enabled = !seat.enabled;
+ seat.imageSrc = seat.enabled ? this.habilitadoImageSrc : this.desHabilitadoImageSrc;
+ this.rows.forEach((row) => {
+ row.seats.forEach((seat: any) => {
+ seat.selected = false;
+ });
+ });
+ }
+
+ toggleRandom(): void {
+ this.isRandomActive = !this.isRandomActive;
+
+ if (!this.isRandomActive) {
+ this.selectedCheckboxes = [];
+ this.selected = 0;
+ const checkboxes = document.querySelectorAll('input[type="checkbox"]');
+ checkboxes.forEach((checkbox) => {
+ if (checkbox instanceof HTMLInputElement) {
+ checkbox.checked = false;
+ }
+ });
+ this.rows.forEach((row) => {
+ row.seats.forEach((seat: any) => {
+ seat.selected = false;
+ });
+ });
+ this.emitArrayAsientos.emit(this.selectedCheckboxes);
+ console.log(this.selectedCheckboxes);
+ for (const row of this.rows) {
+ for (const seat of row.seats) {
+ if (seat.selected) {
+ seat.enabled = !seat.enabled;
+ seat.imageSrc = seat.enabled ? this.habilitadoImageSrc : this.desHabilitadoImageSrc;
+ }
+ }
+ }
+ }
+
+ if (this.isRandomActive) {
+ // Aquí puedes llamar a la función para seleccionar aleatoriamente los checkboxes
+ this.selectedCheckboxes = [];
+ this.selected = 0;
+ const checkboxes = document.querySelectorAll('input[type="checkbox"]');
+ checkboxes.forEach((checkbox) => {
+ if (checkbox instanceof HTMLInputElement) {
+ checkbox.checked = false;
+ }
+ });
+ this.rows.forEach((row) => {
+ row.seats.forEach((seat: any) => {
+ seat.selected = false;
+ });
+ });
+ this.selectRandomCheckboxes();
+ this.emitArrayAsientos.emit(this.selectedCheckboxes);
+ console.log(this.selectedCheckboxes);
+ for (const row of this.rows) {
+ for (const seat of row.seats) {
+ if (seat.selected) {
+ seat.enabled = !seat.enabled;
+ seat.imageSrc = seat.enabled ? this.habilitadoImageSrc : this.desHabilitadoImageSrc;
+ }
+ }
+ }
+ }
+ }
+
+ selectedCheckboxes: string[] = [];
+
+ extractSelectedCheckboxes() {
+ this.selectedCheckboxes = [];
+ for (const row of this.rows) {
+ for (const seat of row.seats) {
+ if (seat.selected) {
+ this.selectedCheckboxes.push(seat.id);
+ }
+ }
+ }
+ }
+
+ handleCheckboxChange(event: Event) {
+ const checkbox = event.target as HTMLInputElement;
+ const rowIdMatches = checkbox.id.match(/^(\d+)/);
+ if (rowIdMatches) {
+ const rowId = Number(rowIdMatches[1]) - 1;
+ if (rowId >= 0 && rowId <= this.rows.length) {
+ const row = this.rows[rowId].seats;
+ const selectedSeat = row.find((seat: any) => seat.id === checkbox.id);
+
+ if (selectedSeat) {
+ selectedSeat.selected = checkbox.checked;
+ this.extractSelectedCheckboxes();
+ }
+
+ if (checkbox.checked) {
+ if (this.selectedCheckboxes.length <= this.maxSelectedCheckboxes) {
+ this.selected++;
+ if (this.selectedCheckboxes.length === this.maxSelectedCheckboxes) {
+ }
+ } else {
+ checkbox.checked = false;
+ }
+ } else {
+ this.selected--;
+ }
+ } else {
+ console.log('Row ID fuera de límites:', rowId);
+ }
+ }
+ }
+
+ disableCheckboxes() {
+ const checkboxes: NodeListOf = this.el.nativeElement.querySelectorAll(
+ 'input[type="checkbox"]'
+ );
+
+ checkboxes.forEach((checkbox) => {
+ if (this.disabledCheckboxes.includes(checkbox.id)) {
+ checkbox.disabled = true;
+ } else {
+ checkbox.disabled = false;
+ }
+ });
+ }
+
+// Selecciona aleatoriamente 'count' checkboxes de la matriz de checkboxes disponibles
+selectRandomCheckboxes() {
+ const checkboxes = Array.from(document.querySelectorAll('input[type="checkbox"]:not(:disabled)')) as HTMLInputElement[];
+ const availableCheckboxes = checkboxes.filter((checkbox) => !this.selectedCheckboxes.includes(checkbox.id));
+ let count = this.maxSelectedCheckboxes - this.selectedCheckboxes.length;
+
+ while (count > 0 && availableCheckboxes.length > 0) {
+ const randomIndex = Math.floor(Math.random() * availableCheckboxes.length);
+ const randomCheckbox = availableCheckboxes.splice(randomIndex, 1)[0];
+ randomCheckbox.checked = true;
+
+ // Simular un evento 'change' en el checkbox seleccionado aleatoriamente
+ const event = new Event('change', { bubbles: true });
+ Object.defineProperty(event, 'target', { value: randomCheckbox, enumerable: true });
+
+ this.handleCheckboxChange(event);
+
+ count--;
+ }
+}
+
+ displayStyle = "none";
+
+ openPopup() {
+ this.displayStyle = "block";
+ }
+ closePopup() {
+ this.emitArrayAsientos.emit(this.selectedCheckboxes);
+ this.displayStyle = "none";
+ }
+}
diff --git a/src/app/components/crear-vuelo/crear-vuelo.component.css b/src/app/components/crear-vuelo/crear-vuelo.component.css
index 945508c..8bc094c 100644
--- a/src/app/components/crear-vuelo/crear-vuelo.component.css
+++ b/src/app/components/crear-vuelo/crear-vuelo.component.css
@@ -1,127 +1,80 @@
-.formulario {
- height: auto;
- padding-bottom: 50px;
- padding-top: 150px;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- display: flex;
+* {
+ box-sizing: border-box;
+ font-family: 'Segoe UI';
}
-.titulo {
- color: #000000;
- font-size: 25px;
- font-family: Nunito Sans;
- text-shadow: 3px 3px 5px rgba(126, 138, 162, 0.5);
- padding-bottom: 50px;
-}
-
-.detalles {
- width: 400px;
- height: auto;
- flex-direction: column;
- justify-content: center;
- display: flex;
- align-items: center;
- gap: 10px;
-}
-.seccion{
- flex-direction: row;
- justify-content: center;
- display: flex;
- align-items: center;
- gap: 10px;
- padding-bottom: 20px;
-}
-.informacion {
- width: 250px;
- font-family: Nunito Sans;
- color: black;
- align-content: center;
- font-size: 18px;
- text-align: left;
-}
-
-.atributo {
- align-self: stretch;
- height: 40px;
- padding: 0px 20px;
- width: 220px;
- background: white;
- border: 0.50px #8CB4F1 solid;
- justify-content: space-between;
- align-items: center;
- gap: 10px;
- display: inline-flex;
-}
-
-.texto,
-.atributo input[type="number"],
-.nombreAerolinea,
-.origen,
-.destino,
-.horaSalida,
-.horaLlegada {
- width: 220px;
- color: #555;
- border: none;
- font-size: 18px;
- font-family: Poppins;
- background: transparent;
- word-wrap: break-word;
- outline: none;
-}
-
-.fechaSalida {
- width: 200px;
- border: none;
- color: #555;
- font-size: 16px;
- outline: none;
-}
-
-.textoFecha {
- width: 220px;
- color: #555;
- border: none;
- font-size: 18px;
- font-family: Poppins;
- background: transparent;
- word-wrap: break-word;
- outline: none;
-}
.boton {
- margin-top: 50px;
- width: 515px;
+ margin-top: 20px;
+ width: 490px;
color: white;
font-size: 18px;
font-family: Poppins;
font-weight: 600;
word-wrap: break-word
}
+.informacion-vuelos h2 {
+ text-align: center;
+ }
+
-.alert {
- padding: 10px;
- margin-top: 0px auto;
- margin-top: 10px;
- width: 515px;
- background-color: #d4edda;
- color: #155724;
- border: 1px solid #c3e6cb;
- border-radius: 4px;
- display: flex;
- justify-content: center;
- align-items: center;
+/* Agrega esta clase para el botón de edición en azul */
+.editar-btn-blue {
+ background-color: blue;
+ color: white;
+ border: none;
+ width: 70px;
+ padding: 8px 12px;
text-align: center;
- animation: fadeOut 3s ease-in-out; /* Animación para desvanecerse */
+ display: block;
+ margin: 0 auto;
+ cursor: pointer;
+ transition: background-color 0.3s ease;
+ margin-top: 10px;
+}
+
+.editar-btn-blue:hover {
+ background-color: darkblue;
}
+.informacion-vuelos {
+ margin: 0 auto;
+ max-width: 40%; /* Puedes ajustar este porcentaje según prefieras */
+ overflow-y: auto; /* Agrega un scroll vertical si la altura del contenido es mayor que un máximo */
+ max-height: 600px; /* Puedes ajustar esta altura según prefieras */
+ border: 5px solid #F23B88; /* Borde del recuadro */
+ padding: 10px;
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* Sombra opcional para darle profundidad */
+ }
+
-@keyframes fadeOut {
- 0% {
- opacity: 1;
- }
- 100% {
- opacity: 0;
- }
+.eliminar-btn {
+ display: block;
+ margin: 10px auto;
+ background-color: red;
+ color: white;
+ border: none;
+ padding: 5px 10px;
+ border-radius: 5px;
+ cursor: pointer;
+ transition: background-color 0.3s;
}
+.eliminar-btn:hover {
+ background-color: darkred;
+}
+
+.eliminar-btn {
+ color: white;
+ background-color: red;
+ border: none;
+ padding: 8px 12px;
+ text-align: center;
+ display: block;
+ margin: 0 auto;
+ cursor: pointer;
+ transition: background-color 0.3s ease;
+ }
+
+ .eliminar-btn:hover {
+ background-color: darkred;
+ }
+
diff --git a/src/app/components/crear-vuelo/crear-vuelo.component.html b/src/app/components/crear-vuelo/crear-vuelo.component.html
index 2e7a76d..5f30080 100644
--- a/src/app/components/crear-vuelo/crear-vuelo.component.html
+++ b/src/app/components/crear-vuelo/crear-vuelo.component.html
@@ -5,11 +5,10 @@
Inicio
Promociones
- Sign out
- ?
+ Log out
-