Skip to content
Snippets Groups Projects
Commit 51ec11a0 authored by paborte's avatar paborte
Browse files

Merge branch 'develop' into 'master'

Merge a master del proyecto final

See merge request paborte/tfg!1
parents b4d0b193 bfa38367
No related branches found
No related tags found
No related merge requests found
Showing
with 38415 additions and 12044 deletions
https://paborte:cFeUs84c@gitlab.inf.uva.es
...@@ -5,6 +5,9 @@ ...@@ -5,6 +5,9 @@
/tmp /tmp
/out-tsc /out-tsc
/bazel-out /bazel-out
.firebaserc
.firebase/
firebase.json
# Node # Node
/node_modules /node_modules
...@@ -36,7 +39,7 @@ yarn-error.log ...@@ -36,7 +39,7 @@ yarn-error.log
/libpeerconnection.log /libpeerconnection.log
testem.log testem.log
/typings /typings
/.git.store
# System files # System files
.DS_Store .DS_Store
Thumbs.db Thumbs.db
...@@ -22,12 +22,14 @@ ...@@ -22,12 +22,14 @@
"main": "src/main.ts", "main": "src/main.ts",
"polyfills": "src/polyfills.ts", "polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json", "tsConfig": "tsconfig.app.json",
"assets": [ "assets": ["src/favicon.ico", "src/assets"],
"src/favicon.ico",
"src/assets"
],
"styles": [ "styles": [
"src/styles.css" "node_modules/bootstrap/dist/css/bootstrap.min.css",
"node_modules/bootstrap/dist/css/bootstrap.css",
"src/styles.css",
"node_modules/primeng/resources/themes/saga-blue/theme.css",
"node_modules/primeng/resources/primeng.min.css",
"node_modules/primeicons/primeicons.css"
], ],
"scripts": [] "scripts": []
}, },
...@@ -36,8 +38,8 @@ ...@@ -36,8 +38,8 @@
"budgets": [ "budgets": [
{ {
"type": "initial", "type": "initial",
"maximumWarning": "500kb", "maximumWarning": "2mb",
"maximumError": "1mb" "maximumError": "5mb"
}, },
{ {
"type": "anyComponentStyle", "type": "anyComponentStyle",
...@@ -89,13 +91,8 @@ ...@@ -89,13 +91,8 @@
"polyfills": "src/polyfills.ts", "polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json", "tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js", "karmaConfig": "karma.conf.js",
"assets": [ "assets": ["src/favicon.ico", "src/assets"],
"src/favicon.ico", "styles": ["src/styles.css"],
"src/assets"
],
"styles": [
"src/styles.css"
],
"scripts": [] "scripts": []
} }
} }
......
...@@ -3,14 +3,14 @@ ...@@ -3,14 +3,14 @@
module.exports = function (config) { module.exports = function (config) {
config.set({ config.set({
basePath: '', basePath: "",
frameworks: ['jasmine', '@angular-devkit/build-angular'], frameworks: ["jasmine", "@angular-devkit/build-angular"],
plugins: [ plugins: [
require('karma-jasmine'), require("karma-jasmine"),
require('karma-chrome-launcher'), require("karma-chrome-launcher"),
require('karma-jasmine-html-reporter'), require("karma-jasmine-html-reporter"),
require('karma-coverage'), require("karma-coverage"),
require('@angular-devkit/build-angular/plugins/karma') require("@angular-devkit/build-angular/plugins/karma"),
], ],
client: { client: {
jasmine: { jasmine: {
...@@ -19,26 +19,26 @@ module.exports = function (config) { ...@@ -19,26 +19,26 @@ module.exports = function (config) {
// for example, you can disable the random execution with `random: false` // for example, you can disable the random execution with `random: false`
// or set a specific seed with `seed: 4321` // or set a specific seed with `seed: 4321`
}, },
clearContext: false // leave Jasmine Spec Runner output visible in browser clearContext: false, // leave Jasmine Spec Runner output visible in browser
}, },
jasmineHtmlReporter: { jasmineHtmlReporter: {
suppressAll: true // removes the duplicated traces suppressAll: true, // removes the duplicated traces
}, },
coverageReporter: { coverageReporter: {
dir: require('path').join(__dirname, './coverage/tienda-chocolates-veganos'), dir: require("path").join(
subdir: '.', __dirname,
reporters: [ "./coverage/tienda-chocolates-veganos"
{ type: 'html' }, ),
{ type: 'text-summary' } subdir: ".",
] reporters: [{ type: "html" }, { type: "text-summary" }],
}, },
reporters: ['progress', 'kjhtml'], reporters: ["progress", "kjhtml"],
port: 9876, port: 9876,
colors: true, colors: true,
logLevel: config.LOG_INFO, logLevel: config.LOG_INFO,
autoWatch: true, autoWatch: true,
browsers: ['Chrome'], browsers: ["Chrome"],
singleRun: false, singleRun: false,
restartOnFileChange: true restartOnFileChange: true,
}); });
}; };
This diff is collapsed.
...@@ -10,22 +10,33 @@ ...@@ -10,22 +10,33 @@
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
"@angular/animations": "~13.2.0", "@angular/animations": "~13.3.3",
"@angular/common": "~13.2.0", "@angular/common": "~13.3.3",
"@angular/compiler": "~13.2.0", "@angular/compiler": "~13.3.3",
"@angular/core": "~13.2.0", "@angular/core": "~13.3.3",
"@angular/forms": "~13.2.0", "@angular/fire": "^7.3.0",
"@angular/platform-browser": "~13.2.0", "@angular/forms": "~13.3.3",
"@angular/platform-browser-dynamic": "~13.2.0", "@angular/localize": "~13.3.3",
"@angular/router": "~13.2.0", "@angular/platform-browser": "~13.3.3",
"@angular/platform-browser-dynamic": "~13.3.3",
"@angular/router": "~13.3.3",
"@ng-bootstrap/ng-bootstrap": "^12.0.2",
"@popperjs/core": "^2.11.5",
"bootstrap": "^5.1.3",
"firebase": "^9.8.3",
"firebase-tools": "^10.1.1",
"jquery": "^3.6.0",
"primeflex": "^3.1.3",
"primeicons": "^5.0.0",
"primeng": "^13.3.3",
"rxjs": "~7.5.0", "rxjs": "~7.5.0",
"tslib": "^2.3.0", "tslib": "^2.3.0",
"zone.js": "~0.11.4" "zone.js": "~0.11.4"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "~13.2.3", "@angular-devkit/build-angular": "~13.3.3",
"@angular/cli": "~13.2.3", "@angular/cli": "~13.3.3",
"@angular/compiler-cli": "~13.2.0", "@angular/compiler-cli": "~13.3.3",
"@types/jasmine": "~3.10.0", "@types/jasmine": "~3.10.0",
"@types/node": "^12.11.1", "@types/node": "^12.11.1",
"jasmine-core": "~4.0.0", "jasmine-core": "~4.0.0",
......
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { CondicionesServicioComponent } from './condiciones-servicio/condiciones-servicio.component';
const routes: Routes = []; import { ContactoComponent } from './contacto/contacto.component';
import { HomepageComponent } from './homepage/homepage.component';
import { SobreNosotrosComponent } from './sobre-nosotros/sobre-nosotros.component';
import { TiendaComponent } from './tienda/tienda.component';
import { CestaCompraComponent } from './cesta-compra/cesta/cesta.component';
import { PerfilCuentaComponent } from './mi-cuenta/perfil-cuenta/perfil-cuenta.component';
import { InicioSesionRegistroComponent } from './mi-cuenta/inicio-sesion-registro/inicio-sesion-registro.component';
import { DatosPersonalesComponent } from './mi-cuenta/perfil-cuenta/datos-personales/datos-personales.component';
import { PedidosComponent } from './mi-cuenta/perfil-cuenta/pedidos/pedidos.component';
import { DireccionesComponent } from './mi-cuenta/perfil-cuenta/direcciones/direcciones.component';
import { DatosPagoComponent } from './mi-cuenta/perfil-cuenta/datos-pago/datos-pago.component';
import { ProductoComponent } from './tienda/producto/producto.component';
import { CompletarPedidoComponent } from './cesta-compra/completar-pedido/completar-pedido.component';
import { CompletarPedidoPagoComponent } from './cesta-compra/completar-pedido-pago/completar-pedido-pago.component';
import { CompletarRegistroComponent } from './mi-cuenta/completar-registro/completar-registro.component';
import { GridProductosComponent } from './tienda/grid-productos/grid-productos.component';
import { CategoriasComponent } from './tienda/categorias/categorias.component';
import { TiendaTiendaComponent } from './tienda/tienda-tienda/tienda-tienda.component';
import { RegistroCompletoComponent } from './mi-cuenta/registro-completo/registro-completo.component';
import { AuthGuardService } from './shared/servicios/auth-guard.service';
import { CerrarSesionComponent } from './mi-cuenta/perfil-cuenta/cerrar-sesion/cerrar-sesion.component';
import { PedidoComponent } from './mi-cuenta/perfil-cuenta/pedidos/pedido/pedido.component';
import { PedidoGuardService } from './shared/servicios/pedido-guard.service';
import { ContrasenaOlvidadaComponent } from './mi-cuenta/contrasena-olvidada/contrasena-olvidada.component';
import { RestablecerPasswordComponent } from './mi-cuenta/restablecer-password/restablecer-password.component';
/* Rutas de la aplicacion */
const appRoutes: Routes = [
{ path: '', redirectTo: '/homepage', pathMatch: 'full' },
{ path: 'homepage', component: HomepageComponent },
{
path: 'tienda',
component: TiendaComponent,
children: [
{ path: 'producto/:productoID', component: ProductoComponent },
{ path: 'categorias', component: CategoriasComponent },
{ path: 'tienda', component: TiendaTiendaComponent },
{ path: 'categoria/:nombreCategoria', component: GridProductosComponent },
],
},
{ path: 'sobreNosotros', component: SobreNosotrosComponent },
{ path: 'condiciones', component: CondicionesServicioComponent },
{ path: 'contacto', component: ContactoComponent },
{
path: 'perfil',
component: PerfilCuentaComponent,
canActivate: [AuthGuardService],
children: [
{ path: 'datosPersonales', component: DatosPersonalesComponent },
{ path: 'pedidos', component: PedidosComponent },
{ path: 'pedidos/:numeroPedido', component: PedidoComponent },
{ path: 'direcciones', component: DireccionesComponent },
{ path: 'datosPago', component: DatosPagoComponent },
{ path: 'cerrarSesion', component: CerrarSesionComponent },
],
},
{
path: 'auth',
component: InicioSesionRegistroComponent,
},
{
path: 'forgotPassword',
component: ContrasenaOlvidadaComponent,
},
{
path: 'resetPassword',
component: RestablecerPasswordComponent,
},
{
path: 'registro',
component: CompletarRegistroComponent,
},
{
path: 'registroCompleto',
component: RegistroCompletoComponent,
},
{ path: 'cesta', component: CestaCompraComponent },
{
path: 'realizarPedido',
component: CompletarPedidoComponent,
canActivate: [PedidoGuardService],
},
{
path: 'realizarPedidoPago',
component: CompletarPedidoPagoComponent,
canActivate: [PedidoGuardService],
},
];
@NgModule({ @NgModule({
imports: [RouterModule.forRoot(routes)], imports: [RouterModule.forRoot(appRoutes)],
exports: [RouterModule] exports: [RouterModule],
}) })
export class AppRoutingModule {} export class AppRoutingModule {}
This diff is collapsed.
import { TestBed } from '@angular/core/testing'; import { TestBed } from '@angular/core/testing';
import { AngularFireDatabase } from '@angular/fire/compat/database';
import { RouterTestingModule } from '@angular/router/testing'; import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { AuthService } from './shared/servicios/auth.service';
import { CestaCompraService } from './shared/servicios/cesta-compra.service';
import { DatabaseService } from './shared/servicios/database.service';
class MockTestService {
constructor() {}
autoLogin() {}
recuperarCestaFromLocalStorage() {}
}
describe('AppComponent', () => { describe('AppComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [ imports: [RouterTestingModule],
RouterTestingModule declarations: [AppComponent],
], providers: [
declarations: [ { provide: AuthService, useClass: MockTestService },
AppComponent { provide: DatabaseService, useClass: MockTestService },
{ provide: CestaCompraService, useClass: MockTestService },
{ provide: AngularFireDatabase, useClass: MockTestService },
], ],
}).compileComponents(); }).compileComponents();
}); });
...@@ -25,11 +36,4 @@ describe('AppComponent', () => { ...@@ -25,11 +36,4 @@ describe('AppComponent', () => {
const app = fixture.componentInstance; const app = fixture.componentInstance;
expect(app.title).toEqual('tiendaChocolatesVeganos'); expect(app.title).toEqual('tiendaChocolatesVeganos');
}); });
it('should render title', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('.content span')?.textContent).toContain('tiendaChocolatesVeganos app is running!');
});
}); });
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { OnInit } from '@angular/core';
import { AuthService } from './shared/servicios/auth.service';
import { CestaCompraService } from './shared/servicios/cesta-compra.service';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
templateUrl: './app.component.html', templateUrl: './app.component.html',
styleUrls: ['./app.component.css'] styleUrls: ['./app.component.css'],
}) })
export class AppComponent { export class AppComponent implements OnInit {
title = 'tiendaChocolatesVeganos'; title = 'tiendaChocolatesVeganos';
constructor(
private authService: AuthService,
private cestaService: CestaCompraService
) {}
/* Realiza una llamada al AuthService para tratar de hacer autologin al usuario y otra al cesta service para recuperar la cesta de la compra */
ngOnInit(): void {
this.authService.autoLogin();
this.cestaService.recuperarCestaFromLocalStorage();
}
} }
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { getAuth, provideAuth } from '@angular/fire/auth';
import { AngularFireModule } from '@angular/fire/compat';
import { AngularFirestoreModule } from '@angular/fire/compat/firestore';
import { AngularFireAuthModule } from '@angular/fire/compat/auth';
import { AngularFireStorageModule } from '@angular/fire/compat/storage';
import { initializeApp, provideFirebaseApp } from '@angular/fire/app';
import { environment } from 'src/environments/environment';
import { AppRoutingModule } from './app-routing.module'; import { AppRoutingModule } from './app-routing.module';
import { AuthService } from './shared/servicios/auth.service';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { HeaderComponent } from './header/header.component';
import { ContactoComponent } from './contacto/contacto.component';
import { SobreNosotrosComponent } from './sobre-nosotros/sobre-nosotros.component';
import { CestaCompraComponent } from './cesta-compra/cesta/cesta.component';
import { ItemCestaComponent } from './cesta-compra/cesta/item-cesta/item-cesta.component';
import { CompletarPedidoComponent } from './cesta-compra/completar-pedido/completar-pedido.component';
import { CompletarPedidoPagoComponent } from './cesta-compra/completar-pedido-pago/completar-pedido-pago.component';
import { CondicionesServicioComponent } from './condiciones-servicio/condiciones-servicio.component';
import { HomepageComponent } from './homepage/homepage.component';
import { CarouselProductosComponent } from './tienda/carousel-productos/carousel-productos.component';
import { TiendaComponent } from './tienda/tienda.component';
import { TiendaTiendaComponent } from './tienda/tienda-tienda/tienda-tienda.component';
import { CategoriasComponent } from './tienda/categorias/categorias.component';
import { GridProductosComponent } from './tienda/grid-productos/grid-productos.component';
import { CardProductoComponent } from './tienda/card-producto/card-producto.component';
import { ProductoComponent } from './tienda/producto/producto.component';
import { InicioSesionRegistroComponent } from './mi-cuenta/inicio-sesion-registro/inicio-sesion-registro.component';
import { CompletarRegistroComponent } from './mi-cuenta/completar-registro/completar-registro.component';
import { RegistroCompletoComponent } from './mi-cuenta/registro-completo/registro-completo.component';
import { ContrasenaOlvidadaComponent } from './mi-cuenta/contrasena-olvidada/contrasena-olvidada.component';
import { RestablecerPasswordComponent } from './mi-cuenta/restablecer-password/restablecer-password.component';
import { PerfilCuentaComponent } from './mi-cuenta/perfil-cuenta/perfil-cuenta.component';
import { DireccionesComponent } from './mi-cuenta/perfil-cuenta/direcciones/direcciones.component';
import { DatosPersonalesComponent } from './mi-cuenta/perfil-cuenta/datos-personales/datos-personales.component';
import { DatosPagoComponent } from './mi-cuenta/perfil-cuenta/datos-pago/datos-pago.component';
import { PedidosComponent } from './mi-cuenta/perfil-cuenta/pedidos/pedidos.component';
import { CardPedidoResumenPerfilComponent } from './mi-cuenta/perfil-cuenta/pedidos/card-pedido-resumen-perfil/card-pedido-resumen-perfil.component';
import { PedidoComponent } from './mi-cuenta/perfil-cuenta/pedidos/pedido/pedido.component';
import { PedidoItemComponent } from './mi-cuenta/perfil-cuenta/pedidos/pedido/pedido-item/pedido-perfil-item.component';
import { CerrarSesionComponent } from './mi-cuenta/perfil-cuenta/cerrar-sesion/cerrar-sesion.component';
import { ToastModule } from 'primeng/toast';
import { CarouselModule } from 'primeng/carousel';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { DatabaseService } from './shared/servicios/database.service';
@NgModule({ @NgModule({
declarations: [ declarations: [
AppComponent AppComponent,
HeaderComponent,
ContactoComponent,
SobreNosotrosComponent,
CestaCompraComponent,
CondicionesServicioComponent,
CompletarPedidoComponent,
CompletarPedidoPagoComponent,
HomepageComponent,
TiendaComponent,
TiendaTiendaComponent,
ItemCestaComponent,
InicioSesionRegistroComponent,
CompletarRegistroComponent,
PerfilCuentaComponent,
PedidosComponent,
DatosPersonalesComponent,
DireccionesComponent,
DatosPagoComponent,
RegistroCompletoComponent,
CardPedidoResumenPerfilComponent,
CerrarSesionComponent,
PedidoComponent,
PedidoItemComponent,
RestablecerPasswordComponent,
ContrasenaOlvidadaComponent,
GridProductosComponent,
CategoriasComponent,
ProductoComponent,
CardProductoComponent,
CarouselProductosComponent,
], ],
imports: [ imports: [
BrowserModule, BrowserModule,
AppRoutingModule AngularFireModule.initializeApp(environment.firebaseConfig),
provideFirebaseApp(() => initializeApp(environment.firebaseConfig)),
provideAuth(() => getAuth()),
AngularFirestoreModule,
AngularFireAuthModule,
AngularFireStorageModule,
AppRoutingModule,
FormsModule,
AppRoutingModule,
NgbModule,
CarouselModule,
ToastModule,
], ],
providers: [], providers: [AuthService, DatabaseService],
bootstrap: [AppComponent] bootstrap: [AppComponent],
}) })
export class AppModule {} export class AppModule {}
.imgAux {
display: block;
max-width: 230px;
max-height: 95px;
width: auto;
height: auto;
}
<div class="container mt-5">
<div class="row">
<div class="col-md-12 d-flex align-items-center justify-content-center">
<div class="d-flex flex-column align-items-center">
<a
class="fs-4 badge btn btn-outline-dark bg-verde-tienda text-white border-white rounded-circle mx-auto"
>
1
</a>
<label for="Productos" class=""> Productos</label>
</div>
<div class="col-md-4">
<hr class="m-4" />
</div>
<div class="d-flex flex-column align-items-center">
<a
disabled
class="fs-4 badge btn btn-outline-dark text-dark rounded-circle mx-auto"
>2</a
>
<label for="envio" class=""> Envío</label>
</div>
<div class="col-md-4">
<hr class="m-4" />
</div>
<div class="d-flex flex-column align-items-center">
<a
class="fs-4 badge btn btn-outline-dark text-dark rounded-circle mx-auto"
>3</a
>
<label for="pago" class=""> Pago</label>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-12">
<h4 class="verde-tienda fw-bold mt-5 ms-5 me-3 mb-4">
Mi cesta de la compra
</h4>
</div>
</div>
<div class="row">
<div class="col-md-9 col-12 d-flex flex-column">
<div
class="pt-3 pb-3 border d-flex border-bottom-0 justify-content-between align-items-center"
>
<h5 class="ms-3">Fecha prevista de entrega</h5>
<h6 class="me-3">{{ fechaEntregaPrevista }}</h6>
</div>
<!-- Zona de carga de productos de la cesta de compra -->
<div *ngIf="cesta.productos.length > 0">
<div class="border" *ngFor="let e of cesta.productos">
<app-item-cesta [entradaCesta]="e"></app-item-cesta>
</div>
</div>
<!-- Fin zona carga productos -->
<div
class="pt-3 pb-3 border d-flex align-items-center"
*ngIf="cesta.productos.length === 0"
>
<h6 class="ms-3">
¡Aún no tienes productos en la cesta! Habrá que ponerle remedio...
</h6>
<a class="fucsia ms-3" routerLink="/tienda/tienda"
><h6>Ir a la tienda</h6></a
>
</div>
<div class="mt-2 row align-items-center">
<div class="col-12 d-flex justify-content-end">
<label for=""
>¿Tienes algún problema?<i class="me-3 ms-3 pi pi-caret-right"></i
></label>
<a routerLink="/contacto" class="fucsia">Contacta con nosotros</a>
</div>
</div>
</div>
<!-- Zona de datos de envio y resumen de costes -->
<div class="col-md-3 col-sm-12" *ngIf="cesta.productos.length != 0">
<div class="row">
<h4 class="mt-3">Resumen de costes</h4>
</div>
<div class="row">
<div class="d-flex flex-column">
<div
class="p-3 border d-flex border-bottom-0 justify-content-between align-items-center"
>
<h6>Coste productos</h6>
<h6 class="verde-tienda">
{{ sumaPreciosProductos.toFixed(2) }} €
</h6>
</div>
<div
class="p-3 border d-flex border-bottom-0 justify-content-between align-items-center"
>
<h6>Gastos de envío</h6>
<h6 class="verde-tienda">{{ gastosDeEnvio }} €</h6>
</div>
<div
class="p-3 border d-flex border justify-content-between align-items-center"
>
<h6>Total (IVA Incluido)</h6>
<h6 class="fucsia text-decoration-underline">
{{ (sumaPreciosProductos + gastosDeEnvio).toFixed(2) }}
</h6>
</div>
<button
class="mt-2 mb-5 btn btn-primary border-white bg-fucsia"
(click)="iniciarPedido()"
[disabled]="cesta.productos.length === 0"
>
Continuar
</button>
</div>
</div>
</div>
</div>
</div>
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Subscription } from 'rxjs';
import { Cesta } from 'src/app/shared/clases/cesta';
import { CestaCompraService } from 'src/app/shared/servicios/cesta-compra.service';
@Component({
selector: 'app-cesta-compra',
templateUrl: './cesta.component.html',
styleUrls: ['./cesta.component.css'],
})
export class CestaCompraComponent implements OnInit, OnDestroy {
fechaEntregaPrevista: string; /* Fecha calculada en la que sse prevee la entrega del pedido */
diasTipicosParaUnEnvio = 4; /* Dias a sumar a la fecha actual para saber cuando esta previsto entregar un pedido */
cestaSubscription: Subscription; /* Subscripcion a la cesta mantenida por el CestaCompraService */
cesta: Cesta = null; /* Cesta local del componente */
sumaPreciosProductos = 0; /* Suma total d elos precios de los productos multiplicados por las unidades */
gastosDeEnvio = 0; /* Costes del envio */
constructor(
private cestaService: CestaCompraService,
private router: Router
) {}
/* Al inicar el componente se compone con los productos que hay actualmente en la cesta y se calculan los costes */
ngOnInit(): void {
this.cestaSubscription = this.cestaService.cestaBS.subscribe(
(cesta) => {
this.cesta = cesta;
this.sumaPreciosProductos = 0;
this.cesta.productos.forEach((p) => {
this.sumaPreciosProductos += p.producto.precio * p.unidades;
});
},
() => {}
);
this.gastosDeEnvio = this.cestaService.getGastosDeEnvio();
this.fechaEntregaPrevista =
this.cestaService.getFechaEntregaPrevistaPedido();
}
ngOnDestroy(): void {
this.cestaSubscription.unsubscribe();
}
/* Permite iniciar el pedido y redirige al usuario a otra vista */
iniciarPedido(): void {
this.cestaService.crearPedidoInicial();
this.router.navigate(['/realizarPedido']);
}
}
.imgAux {
display: block;
max-width: 230px;
max-height: 95px;
width: auto;
height: auto;
}
<div class="row">
<div class="container">
<div class="col-12">
<div class="pt-3 pb-3 border d-flex">
<div class="col-4 d-flex flex-column align-items-center h-100">
<a
[routerLink]="[
'/tienda/producto',
entradaCesta.producto.productoID
]"
><img [src]="imagen | async" class="imgAux ms-3 h-100"
/></a>
</div>
<div class="col-8 d-flex flex-column">
<a
[routerLink]="[
'/tienda/producto',
entradaCesta.producto.productoID
]"
class="text-dark text-decoration-none"
><h6>{{ entradaCesta.producto.nombre }}</h6></a
>
<h6 class="mt-2">
<label for="" class="verde-tienda"
>{{ entradaCesta.producto.precio }} €</label
>
<label for="" class="ms-2">/ Unidad</label>
</h6>
<label for="unidades"
>Unidades en la cesta <i class="pi pi-shopping-bag ms-2"></i
></label>
<input
type="number"
[name]="entradaCesta.producto.productoID"
min="1"
[max]="entradaCesta.producto.stockEnAlmacen"
class="ms-2"
style="max-width: 4rem"
(change)="mostrarBotonCambiarUnidades()"
[(ngModel)]="entradaCesta.unidades"
/>
<button
class="btn btn-primary bg-fucsia border-white w-50"
*ngIf="botonCambiarUnidades"
(click)="modificarCantidad()"
>
Modificar cantidad <i class="pi pi-check-circle ms-2"></i>
</button>
<a class="mt-1 text-dark fs-6" (click)="eliminarProducto()"
>Eliminar producto <i class="pi pi-trash ms-2"></i
></a>
</div>
</div>
</div>
</div>
</div>
import { Component, Input, OnInit } from '@angular/core';
import { AngularFireStorage } from '@angular/fire/compat/storage';
import { Producto } from 'src/app/shared/clases/producto';
import { CestaCompraService } from 'src/app/shared/servicios/cesta-compra.service';
import { DatabaseService } from 'src/app/shared/servicios/database.service';
@Component({
selector: 'app-item-cesta',
templateUrl: './item-cesta.component.html',
styleUrls: ['./item-cesta.component.css'],
providers: [DatabaseService],
})
export class ItemCestaComponent implements OnInit {
@Input('entradaCesta') entradaCesta: { producto: Producto; unidades: number };
imagen; /* Imagen principal del producto a mostrar */
rutaProducto: string; /* La ruta del producto en el storage */
botonCambiarUnidades: boolean =
false; /* Boolean que habilita o deshabilita el boton de modificar cantidad */
nuevasUnidades: number = 0; /* Nueva cantidad de producto que el usuari0o desea tener en la cesta. */
constructor(
private databaseService: DatabaseService,
private cestaService: CestaCompraService
) {}
ngOnInit(): void {
this.imagen = this.databaseService.getDownloadURLFromStorage(
this.entradaCesta.producto.imagenIconoPath
);
this.rutaProducto =
'/tienda/producto' + this.entradaCesta.producto.productoID;
}
/* Elimina el producto que contiene este componente de la cesta de la compra */
eliminarProducto(): void {
this.cestaService.deleteProducto(this.entradaCesta.producto.productoID);
}
/* Habilita el boton de modificar cantidad */
mostrarBotonCambiarUnidades(): void {
this.botonCambiarUnidades = true;
}
/* Permite modificar la cantidad del producto mostrado en la cesta de la compra */
modificarCantidad(): void {
this.botonCambiarUnidades = false;
this.cestaService.modificarCantidadProducto({
producto: this.entradaCesta.producto,
unidades: this.entradaCesta.unidades,
});
}
}
<!-- Steper de la parte superior -->
<div class="container mt-5">
<div class="row">
<div class="col-md-12 d-flex align-items-center justify-content-center">
<div class="d-flex flex-column align-items-center">
<a
routerLink="/cesta"
class="fs-4 badge btn btn-outline-dark text-dark rounded-circle mx-auto"
>
1
</a>
<label for="Productos" class=""> Productos</label>
</div>
<div class="col-md-4">
<hr class="m-4" />
</div>
<div class="d-flex flex-column align-items-center">
<a
routerLink="/realizarPedido"
class="fs-4 badge btn btn-outline-dark text-dark rounded-circle mx-auto"
>2</a
>
<label for="envio" class=""> Envío</label>
</div>
<div class="col-md-4">
<hr class="m-4" />
</div>
<div class="d-flex flex-column align-items-center">
<a
class="fs-4 badge btn btn-outline-dark bg-verde-tienda text-white border-white rounded-circle mx-auto"
>3</a
>
<label for="pago" class=""> Pago</label>
</div>
</div>
</div>
</div>
<!-- Fin steper -->
<!-- Zona de entrada de datos de facturación -->
<div class="container">
<div class="row">
<h4 class="verde-tienda fw-bold mt-5 ms-5 me-3 mb-4">Pago</h4>
</div>
<div class="row">
<div class="col-12 col-md-9 d-flex-flex-column">
<form #formPago="ngForm">
<div class="border p-4">
<h4 for="" class="mb-3 ms-1">Tus datos de facturación:</h4>
<div class="form-floating mb-3">
<input
type="text"
class="form-control"
id="floatingInput"
placeholder="nombre"
name="nombre"
required
[(ngModel)]="user.direccionFacturacion.nombre"
/>
<label for="nombre y apellidos">Nombre</label>
</div>
<div class="form-floating mb-3">
<input
type="text"
class="form-control"
id="floatingInput"
placeholder=" apellidos"
name="apellidos"
required
[(ngModel)]="user.direccionFacturacion.apellidos"
/>
<label for="nombre y apellidos">Apellidos</label>
</div>
<div class="form-floating mb-3">
<input
type="text"
class="form-control"
id="floatingInput"
placeholder="direccion"
name="direccion"
required
[(ngModel)]="user.direccionFacturacion.direccion"
/>
<label for="nombre y apellidos">Direccion</label>
</div>
<div class="form-floating mb-3">
<input
type="text"
class="form-control"
id="floatingInput"
placeholder="poblacion"
name="poblacion"
required
[(ngModel)]="user.direccionFacturacion.poblacion"
/>
<label for="nombre y apellidos">Población</label>
</div>
<div class="form-floating mb-3">
<input
type="text"
class="form-control"
id="floatingInput"
placeholder="codigo postal"
name="codigoPostal"
required
[(ngModel)]="user.direccionFacturacion.codigoPostal"
/>
<label for="nombre y apellidos">Codigo postal</label>
</div>
<div class="form-floating mb-3">
<input
type="text"
class="form-control"
id="floatingInput"
placeholder="Provincia"
name="provincia"
required
[(ngModel)]="user.direccionFacturacion.provincia"
/>
<label for="nombre y apellidos">Provincia</label>
</div>
<div class="form-floating mb-3">
<input
disabled
type="text"
class="form-control"
id="floatingInput"
placeholder="pais"
/>
<label for="pais">España</label>
</div>
</div>
<!-- Zona de elección del método de pago SIN FUNCIONALIDAD ACTUALMENTE-->
<div class="border p-4 mt-4">
<h4 for="" class="mb-3 ms-1">Método de pago:</h4>
<div class="row">
<button
(click)="pagarConTarjeta()"
class="btn btn-outline-dark d-flex justify-content-center align-items-center"
>
Pagar con tarjeta bancaria
<i class="fs-4 ps-3 pi pi-credit-card"></i>
</button>
</div>
<div class="row mt-3">
<button
disabled
class="btn btn-outline-primary d-flex justify-content-center align-items-center"
>
Pagar con PayPal
<i class="fs-4 ps-3 pi pi-paypal"></i>
</button>
</div>
<div class="row mt-3">
<button
disabled
class="btn btn-outline-success d-flex justify-content-center align-items-center"
>
Pagar con Google Pay
<i class="fs-4 ps-3 pi pi-google"></i>
</button>
</div>
</div>
</form>
</div>
<!-- Columna lateral derecha con resumen-->
<div class="col-12 col-md-3">
<h4>Resumen del pedido</h4>
<div class="d-flex flex-column">
<div
class="p-3 border d-flex justify-content-between align-items-center"
>
<h6>Coste productos</h6>
<h6 class="verde-tienda">{{ pedido.costeProductos.toFixed(2) }} €</h6>
</div>
<div
class="p-3 border d-flex border-end justify-content-between align-items-center"
>
<h6>Gastos envío</h6>
<h6 class="verde-tienda">{{ pedido.costesEnvio }} €</h6>
</div>
<div
class="p-3 border d-flex border-end justify-content-between align-items-center"
>
<h6>Total (IVA incluido)</h6>
<h6 class="fucsia text-decoration-underline">
{{ (pedido.costeProductos + pedido.costesEnvio).toFixed(2) }} €
</h6>
</div>
</div>
</div>
</div>
</div>
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { Pedido } from 'src/app/shared/clases/pedido';
import { Usuario } from 'src/app/shared/clases/usuario';
import { AuthService } from 'src/app/shared/servicios/auth.service';
import { CestaCompraService } from 'src/app/shared/servicios/cesta-compra.service';
import { DatabaseService } from 'src/app/shared/servicios/database.service';
@Component({
selector: 'app-completar-pedido-pago',
templateUrl: './completar-pedido-pago.component.html',
styleUrls: ['./completar-pedido-pago.component.css'],
providers: [DatabaseService],
})
export class CompletarPedidoPagoComponent implements OnInit, OnDestroy {
user: Usuario; /* Usuario local del componente */
userSubscription: Subscription; /* Subscipcion al usuarior del auth service+*/
pedido: Pedido; /* Pedido local del componente */
pedidoSubscription: Subscription; /* subscripcion al pedido del Cesta compra service */
constructor(
private authService: AuthService,
private cestaService: CestaCompraService,
private databaseService: DatabaseService
) {}
ngOnInit(): void {
this.userSubscription = this.authService.userBS.subscribe((user) => {
this.user = user;
});
this.pedidoSubscription = this.cestaService.pedidoBS.subscribe((pedido) => {
this.pedido = pedido;
});
}
ngOnDestroy(): void {
this.userSubscription.unsubscribe();
this.pedidoSubscription.unsubscribe();
}
/* Funcionalidad simulada. Al inciar el proceso de pago re redirigiria al usuario a la pagina de pagos y,
al completarse este, se crearia el pedido en la base de datos. Por ahora se crea aquí para simular que todo ese
proceso ha sido correcto. */
pagarConTarjeta(): void {
this.pedido.direccionFacturacion = this.user.direccionFacturacion;
this.databaseService.createPedidoInDatabase(
this.pedido,
this.authService.credential.user.uid
);
this.cestaService.clearCestas();
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment