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

Añadida funcionalidad a los pedidos. Autocarga de la cesta del cliente...

Añadida funcionalidad a los pedidos. Autocarga de la cesta del cliente proveniente de la base de datos. Implementado el mostrar detalles de un pedido. Iniciados los trabajos para el auto login con el local storage
parent e443bfc1
No related branches found
No related tags found
No related merge requests found
Showing
with 412 additions and 34 deletions
......@@ -20,6 +20,9 @@ import { GridProductosComponent } from './tienda/modulo-productos/grid-productos
import { CategoriasComponent } from './tienda/modulo-productos/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/services/auth-guard.service';
import { CerrarSesionComponent } from './mi-cuenta/perfil-cuenta/cerrar-sesion/cerrar-sesion.component';
import { PedidoPerfilComponent } from './mi-cuenta/perfil-cuenta/pedidos/pedido-perfil/pedido-perfil.component';
const appRoutes: Routes = [
{ path: '', redirectTo: '/homepage', pathMatch: 'full' },
......@@ -40,11 +43,14 @@ const appRoutes: Routes = [
{
path: 'perfil',
component: PerfilCuentaComponent,
canActivate: [AuthGuardService],
children: [
{ path: 'datosPersonales', component: DatosPersonalesComponent },
{ path: 'pedidos', component: PedidosComponent },
{ path: 'pedidos/:numeroPedido', component: PedidoPerfilComponent },
{ path: 'direcciones', component: DireccionesComponent },
{ path: 'datosPago', component: DatosPagoComponent },
{ path: 'cerrarSesion', component: CerrarSesionComponent },
],
},
{
......
import { Component } from '@angular/core';
import { PrimeNGConfig } from 'primeng/api';
import { OnInit } from '@angular/core';
import { AuthService } from './shared/services/auth.service';
@Component({
selector: 'app-root',
......@@ -10,9 +11,13 @@ import { OnInit } from '@angular/core';
export class AppComponent implements OnInit {
title = 'tiendaChocolatesVeganos';
constructor(private primengConfig: PrimeNGConfig) {}
constructor(
private primengConfig: PrimeNGConfig,
private authService: AuthService
) {}
ngOnInit() {
this.primengConfig.ripple = true;
this.authService.autoLogin();
}
}
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Subscription } from 'rxjs';
import { Pedido } from 'src/app/shared/interfaces/pedido.model';
import { Usuario } from 'src/app/shared/interfaces/usuario';
......@@ -20,7 +21,8 @@ export class CompletarPedidoPagoComponent implements OnInit, OnDestroy {
constructor(
private authService: AuthService,
private cestaService: CestaCompraService,
private databaseService: DatabaseService
private databaseService: DatabaseService,
private router: Router
) {}
ngOnInit(): void {
......@@ -40,10 +42,9 @@ export class CompletarPedidoPagoComponent implements OnInit, OnDestroy {
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. */
this.pedido.direccionFacturacion = this.user.direccionFacturacion;
this.databaseService
.createPedidoInDatabase(this.pedido, this.authService.credential.user.uid)
.then((doc) => {
console.log('Pedido: ' + doc.id);
});
this.databaseService.createPedidoInDatabase(
this.pedido,
this.authService.credential.user.uid
);
}
}
......@@ -31,6 +31,7 @@ export class HeaderComponent implements OnInit, OnDestroy {
this.rutaCuenta = '/auth';
} else {
this.rutaCuenta = '/perfil';
console.log('el header tiene user');
}
},
() => {}
......
......@@ -16,6 +16,9 @@ import { AppRoutingModule } from '../app-routing.module';
import { RegistroCompletoComponent } from './registro-completo/registro-completo.component';
import { AnimatedIconsModule } from '../shared/animated-icons/animated-icons.module';
import { PedidoResumenPerfilComponent } from './perfil-cuenta/pedidos/pedido-resumen-perfil/pedido-resumen-perfil.component';
import { CerrarSesionComponent } from './perfil-cuenta/cerrar-sesion/cerrar-sesion.component';
import { PedidoPerfilComponent } from './perfil-cuenta/pedidos/pedido-perfil/pedido-perfil.component';
import { PedidoPerfilItemComponent } from './perfil-cuenta/pedidos/pedido-perfil/pedido-perfil-item/pedido-perfil-item.component';
@NgModule({
imports: [
......@@ -36,6 +39,9 @@ import { PedidoResumenPerfilComponent } from './perfil-cuenta/pedidos/pedido-res
ResumenPedidoComponent,
RegistroCompletoComponent,
PedidoResumenPerfilComponent,
CerrarSesionComponent,
PedidoPerfilComponent,
PedidoPerfilItemComponent,
],
exports: [],
})
......
<div class="container">
<h4>Cerrando Sesion</h4>
<app-ring-spinner></app-ring-spinner>
</div>
import { Component, OnInit } from '@angular/core';
import { AuthService } from 'src/app/shared/services/auth.service';
@Component({
selector: 'app-cerrar-sesion',
templateUrl: './cerrar-sesion.component.html',
styleUrls: ['./cerrar-sesion.component.css'],
})
export class CerrarSesionComponent implements OnInit {
constructor(private authService: AuthService) {}
ngOnInit(): void {
setTimeout(() => {
this.authService.logOut();
}, 2000);
}
}
<div
class="pt-3 pb-3 border d-flex border-dark border-top-0 align-items-center"
>
<div class="col-4 d-flex justify-content-center">
<a
[routerLink]="['/tienda/producto', producto.productoID]"
class="w-50 h-25"
><img [src]="imagen | async" class="ms-3 w-75 h-50" alt=""
/></a>
</div>
<div class="ms-3 col-8">
<h6>{{ producto.nombre }}</h6>
<h6 class="">
<label for="" class="verde-tienda">{{ producto.precio }} €</label>
<label for="" class="ms-2">/ Unidad</label>
</h6>
<h6>
<label for="">Unidades:</label>
<label for="" class="ms-2">{{ productoUnidades.unidades }}</label>
</h6>
<h6 class="">
<label for="" class="">Coste productos</label>
<label for="" class="ms-2 fw-bold"
>: {{ producto.precio * productoUnidades.unidades }} €</label
>
</h6>
</div>
</div>
import { Component, Input, OnInit } from '@angular/core';
import { AngularFireStorage } from '@angular/fire/compat/storage';
import { Observable, take } from 'rxjs';
import { Producto } from 'src/app/shared/interfaces/producto.model';
import { DatabaseService } from 'src/app/shared/services/database.service';
@Component({
selector: 'app-pedido-perfil-item',
templateUrl: './pedido-perfil-item.component.html',
styleUrls: ['./pedido-perfil-item.component.css'],
})
export class PedidoPerfilItemComponent implements OnInit {
@Input('productoUnidades') productoUnidades: {
productoID: string;
unidades: number;
};
public producto: Producto;
imagen: Observable<any>;
constructor(
private storage: AngularFireStorage,
private databaseService: DatabaseService
) {}
ngOnInit(): void {
this.databaseService
.getProductoFromDatabase(this.productoUnidades.productoID)
.pipe()
.subscribe(
(producto: Producto) => {
this.producto = producto;
this.imagen = this.getImage(this.producto.imagenIconoPath);
},
(error) => {
console.log(error);
}
);
}
getImage(imagePath: string) {
const ref = this.storage.ref(imagePath);
return ref.getDownloadURL();
}
}
<div class="container">
<div class="row mt-4">
<div class="col-sm-12">
<h4 class="mt-3 verde-tienda fw-bold">Resumen del pedido :</h4>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<div class="row">
<div
class="pt-3 pb-3 border d-flex border-dark border-bottom-0 justify-content-between"
>
<h5>Fecha de pedido</h5>
<h5>{{ pedido.fechaPedido }}</h5>
</div>
<div
class="pt-3 pb-3 border d-flex border-dark justify-content-between"
>
<h5>Estado del pedido</h5>
<h5>{{ pedido.estado }}</h5>
</div>
<!-- Zona de carga de productos del pedido -->
<div *ngFor="let p of pedido.productos">
<app-pedido-perfil-item
[productoUnidades]="p"
></app-pedido-perfil-item>
</div>
<!-- Fin zona carga productos -->
</div>
</div>
<!-- Zona de datos de envio y resumen de costes -->
<div class="col-sm-12">
<div class="row ms-3">
<h5 class="mt-3">Resumen de costes</h5>
</div>
<div class="row ms-3 me-3">
<div class="d-flex flex-column">
<div
class="p-3 border d-flex border-dark border-bottom-0 justify-content-between align-items-center"
>
<h6>Coste productos</h6>
<h5>{{ pedido.costeProductos }} €</h5>
</div>
<div
class="p-3 border d-flex border-dark border-bottom-0 justify-content-between align-items-center"
>
<h6>Gastos de envío</h6>
<h5>{{ pedido.costesEnvio }} €</h5>
</div>
<div
class="p-3 border d-flex border-dark border justify-content-between align-items-center"
>
<h6>Total (IVA Incluido)</h6>
<h5>{{ pedido.costesEnvio + pedido.costeProductos }} €</h5>
</div>
</div>
</div>
<div class="row ms-3">
<h5 class="mt-3">Dirección de envío</h5>
</div>
<div class="row ms-3 me-3">
<div class="d-flex flex-column">
<div
class="p-3 border d-flex border-dark border-bottom-0 justify-content-between align-items-center"
>
<h6>{{ pedido.direccionEnvio.nombre }}o</h6>
</div>
<div
class="p-3 border d-flex border-dark border-bottom-0 justify-content-between align-items-center"
>
<h6>{{ pedido.direccionEnvio.apellidos }}</h6>
</div>
<div
class="p-3 border d-flex border-dark border-bottom-0 justify-content-between align-items-center"
>
<h6>{{ pedido.direccionEnvio.direccion }}</h6>
</div>
<div
class="p-3 border d-flex flex-column border-dark border justify-content-start"
>
<h6>{{ pedido.direccionEnvio.poblacion }}</h6>
<h6>{{ pedido.direccionEnvio.provincia }}</h6>
<h6>{{ pedido.direccionEnvio.codigoPostal }}</h6>
<h6>{{ pedido.direccionEnvio.pais }}</h6>
</div>
<div class="mt-3 d-flex justify-content-end">
<button
class="btn btn-primary bg-fucsia border-white"
(click)="cancelarPedido()"
[disabled]="pedido.estado === 'Cancelado'"
>
Cancelar pedido
</button>
</div>
</div>
</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 href="" class="fucsia">Contacta con nosotros</a>
</div>
</div>
</div>
</div>
</div>
import { Component, OnDestroy, OnInit } from '@angular/core';
import { AngularFireStorage } from '@angular/fire/compat/storage';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { Observable, Subscription, take } from 'rxjs';
import { Pedido } from 'src/app/shared/interfaces/pedido.model';
import { Producto } from 'src/app/shared/interfaces/producto.model';
import { DatabaseService } from 'src/app/shared/services/database.service';
@Component({
selector: 'app-pedido-perfil',
templateUrl: './pedido-perfil.component.html',
styleUrls: ['./pedido-perfil.component.css'],
})
export class PedidoPerfilComponent implements OnInit, OnDestroy {
private paramsSubscription: Subscription;
public pedido: Pedido;
public numeroPedido: string;
public imagen;
constructor(
private route: ActivatedRoute,
private databaseService: DatabaseService,
private router: Router
) {}
ngOnInit(): void {
this.paramsSubscription = this.route.params.subscribe((params: Params) => {
this.databaseService
.getPedidoFromDatabase(params['numeroPedido'])
.pipe(take(1))
.subscribe((p: Pedido) => {
this.numeroPedido = params['numeroPedido'];
this.pedido = p;
console.log(p);
});
});
}
ngOnDestroy() {
this.paramsSubscription.unsubscribe();
}
cancelarPedido() {
this.databaseService
.cancelarPedidoInDatabase(this.pedido, this.numeroPedido)
.then(
() => {
this.router.navigate['/perfil/pedidos'];
},
() => {
this.router.navigate['/perfil/pedidos'];
}
)
.finally(() => {
this.router.navigate['/perfil/pedidos'];
});
}
}
......@@ -32,7 +32,10 @@
</div>
<div class="row mb-2">
<div class="col d-flex justify-content-end">
<button class="btn btn-primary bg-fucsia border-white">
<button
class="btn btn-primary bg-fucsia border-white"
[routerLink]="numeroPedido"
>
Detalles del pedido
</button>
</div>
......
......@@ -23,11 +23,19 @@
>Mis direcciones</a
>
</div>
<div routerLinkActive="bg-verde-tienda" class="border border-dark p-2">
<div
routerLinkActive="bg-verde-tienda"
class="border border-dark border-bottom-0 p-2"
>
<a routerLink="datosPago" class="ps-4 p-2 text-dark"
>Mis datos de pago</a
>
</div>
<div class="border border-dark p-2">
<a routerLink="cerrarSesion" class="ps-4 p-2 text-dark"
>Cerrar Sesión</a
>
</div>
</div>
<div class="col-md-8 col-sm-12">
<router-outlet></router-outlet>
......
import { Component, OnInit } from '@angular/core';
import { AuthService } from 'src/app/shared/services/auth.service';
@Component({
selector: 'app-perfil-cuenta',
templateUrl: './perfil-cuenta.component.html',
styleUrls: ['./perfil-cuenta.component.css']
styleUrls: ['./perfil-cuenta.component.css'],
})
export class PerfilCuentaComponent implements OnInit {
constructor() {}
ngOnInit(): void {
}
ngOnInit(): void {}
}
......@@ -25,8 +25,7 @@ export class Usuario {
pais: string;
};
metodosPago: MetodoPago[];
cesta: Cesta;
cesta: { productoID: string; unidades: number }[];
constructor() {
this.nombre = '';
this.apellidos = '';
......
import { Injectable } from '@angular/core';
import {
ActivatedRouteSnapshot,
CanActivate,
CanDeactivate,
Router,
RouterStateSnapshot,
UrlTree,
} from '@angular/router';
import { map, Observable } from 'rxjs';
import { InicioSesionRegistroComponent } from 'src/app/mi-cuenta/inicio-sesion-registro/inicio-sesion-registro.component';
import { AuthService } from './auth.service';
@Injectable({
providedIn: 'root',
})
export class AuthGuardService
implements CanActivate, CanDeactivate<InicioSesionRegistroComponent>
{
constructor(private authService: AuthService, private router: Router) {}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
):
| boolean
| UrlTree
| Observable<boolean | UrlTree>
| Promise<boolean | UrlTree> {
return this.authService.userBS.pipe(
map((user) => {
const isAuth = !!user;
if (isAuth) {
return true;
}
return this.router.createUrlTree(['/auth']);
})
);
}
// Consider using this interface for all CanDeactivate guards,
// and have your components implement this interface, too.
//
// e.g. export class CanDeactivateGuard implements CanDeactivate<CanComponentDeactivate> {
//
// export interface CanComponentDeactivate {
// canDeactivate: () => any;
// }
canDeactivate(
component: InicioSesionRegistroComponent,
currentRoute: ActivatedRouteSnapshot,
currentState: RouterStateSnapshot
): Observable<boolean> | Promise<boolean> | boolean {
return this.authService.userBS.pipe(
map((user) => {
const isAuth = !!user;
if (isAuth) {
return true;
}
return false;
})
);
}
}
......@@ -4,23 +4,37 @@ import {
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
UserCredential,
signOut,
getIdToken,
} from '@angular/fire/auth';
import { Usuario } from '../interfaces/usuario';
import { BehaviorSubject, from, Observable } from 'rxjs';
import { BehaviorSubject, from, Observable, take } from 'rxjs';
import { DatabaseService } from './database.service';
import { Router } from '@angular/router';
import { MetodoPago } from '../interfaces/metodoPago.model';
@Injectable()
export class AuthService {
isUserLogged = false;
credential!: UserCredential;
userBS = new BehaviorSubject<Usuario>(null);
public user!: Usuario;
private password = '';
constructor(private auth: Auth, private databaseService: DatabaseService) {}
constructor(
private auth: Auth,
private databaseService: DatabaseService,
private router: Router
) {}
public isLoggedIn(): boolean {
return this.isUserLogged;
public autoLogin() {
const userLogged: Usuario = JSON.parse(localStorage.getItem('userLogged'));
const userCredential: UserCredential = JSON.parse(
localStorage.getItem('userCredential')
);
if (!userLogged) {
return;
}
console.log(userLogged);
}
public loginUserWithEmail(
......@@ -28,17 +42,34 @@ export class AuthService {
password: string
): Observable<UserCredential> {
const loginPromise = signInWithEmailAndPassword(this.auth, email, password);
this.password = '';
const loginObs = from(loginPromise);
loginObs.subscribe((user) => {
this.credential = user;
loginObs.pipe(take(1)).subscribe((userAuth) => {
this.credential = userAuth;
this.databaseService
.getUserFromDatabase(user.user.uid)
.subscribe((user) => this.userBS.next(user));
.getUserFromDatabase(userAuth.user.uid)
.pipe(take(1))
.subscribe((userDB: Usuario) => {
this.userBS.next(userDB);
localStorage.setItem('userCredential', JSON.stringify(userAuth));
localStorage.setItem('userLogged', JSON.stringify(userDB));
localStorage.setItem(
'authExpirationTime',
JSON.stringify(new Date().getTime() + 3600000)
);
});
/* to do - recuperar los productos en la cesta del usuario */
});
return from(loginPromise);
}
public logOut() {
signOut(this.auth);
this.userBS.next(null);
localStorage.clear();
this.router.navigate(['/auth']);
}
public createUserWithEmail(
email: string,
......@@ -53,16 +84,10 @@ export class AuthService {
}
public updateUserRegistro(user: Usuario): void {
this.user = { ...user };
this.userBS.next({ ...user });
}
public changeLogState() {
this.isUserLogged = !this.isUserLogged;
}
public getAuthUser() {
return this.auth.currentUser;
}
public logOut(): Observable<any> {
return from(this.auth.signOut());
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment