File

src/app/components/home/home.component.ts

Description

Muestra las publicaciones propias del usuario y gestiona su creación, modificación y eliminación. De igual manera, permite ver las respuestas asociadas a estas, así como, desbloquearlas y valorarlas.

Implements

OnInit

Metadata

selector app-home
styleUrls ./home.component.css
templateUrl ./home.component.html

Index

Properties
Methods

Methods

addpost
addpost(form: NgForm)

Crear una nueva publicación.

Parameters :
Name Type Optional
form NgForm No
Returns : any
cancelAdd
cancelAdd()

Cancela la creación de una publicación.

Returns : void
cancelEdit
cancelEdit()

Cancela la edición de una publicación.

Returns : void
comprobar
comprobar()

Comprueba si se hizo efectivo el pago por la respuesta.

Returns : void
create
create(template: TemplateRef)

Modal para crear una publicación.

Parameters :
Name Type Optional
template TemplateRef<any> No
Returns : void
delet
delet(template: TemplateRef, deletePost: Posts)

Borrar una publicación

Parameters :
Name Type Optional
template TemplateRef<any> No
deletePost Posts No
Returns : void
delete
delete()

Borra una publicación existente.

Returns : void
deleteImage
deleteImage(downloadUrl)

Borra una imagen de Firebase Storage a partir de una URL.

Parameters :
Name Optional
downloadUrl No
Returns : any
getPosts
getPosts()

Obtiene todas las publicaciones del usuario.

Returns : void
modify
modify(template: TemplateRef, editPost: Posts)

Modal para modificar una publicación.

Parameters :
Name Type Optional
template TemplateRef<any> No
editPost Posts No
Returns : void
ngOnInit
ngOnInit()

Obtiene todas las publicaciones del usuario al inicio

Returns : void
notvalorate
notvalorate(resp: Answers)

Califica la respuesta como no útil y marca el post como no resuelto.

Parameters :
Name Type Optional
resp Answers No
Returns : void
pay
pay(template: TemplateRef, ans: Answers)

Modal para realizar el pago.

Parameters :
Name Type Optional
template TemplateRef<any> No
ans Answers No
Returns : void
rateUser
rateUser(y)

Califica a un usuario.

Parameters :
Name Optional
y No
Returns : void
unlocked
unlocked(viewans: Answers)

Llama a opciones de pago para desbloquear una respuesta.

Parameters :
Name Type Optional
viewans Answers No
Returns : void
update
update(form: NgForm)

Actualiza una publicación existente.

Parameters :
Name Type Optional
form NgForm No
Returns : any
upload
upload(event)

Sube la imagen al servicio de Firebase Storage y obtiene la url de la misma.

Parameters :
Name Optional
event No
Returns : void
valorate
valorate(resp: Answers)

Califica la respuesta como útil y marca el post como resuelto.

Parameters :
Name Type Optional
resp Answers No
Returns : void
viewAnswer
viewAnswer(template: TemplateRef, viewans: Answers)

Ver en detalle una respuesta individual.

Parameters :
Name Type Optional
template TemplateRef<any> No
viewans Answers No
Returns : void
viewAnswers
viewAnswers(template: TemplateRef, viewans: Posts)

Ver todas las respuestas de una publicación.

Parameters :
Name Type Optional
template TemplateRef<any> No
viewans Posts No
Returns : void

Properties

aanswer
Type : Answers[]

Arreglo de respuestas.

done
Type : boolean
Default value : false

Flag para determinar si calificó al usuario.

downloadURL
Type : Observable<string>

URL de descarga de la imagen.

imageUrl
Type : string
Default value : null

URL para la imagen de la publicación a ser almacenada en Firebase Storage.

oldimageUrl
Type : string
Default value : null

URL para la imagen de la publicación a ser eliminada.

pposts
Type : Posts[]

Arreglo de publicaciones.

ref
Type : AngularFireStorageReference

Referencia al Storage de Firebase.

rrate
Type : Rates[]

Arreglo de calificaciones de usuario.

selectedAnswer
Type : Answers

Respuesta seleccionada actualmente.

selectedPost
Type : Posts

Publicación seleccionada actualmente.

selectedRate
Type : Rates

Calificación de usuario seleccionada actualmente.

uploadProgress
Type : Observable<number>

Porcentaje para la barra de progreso al subir imagen.

uuser
Type : Customers[]

Arreglo de usuarios.

y
Type : number
Default value : 0

Nro de estrellas predefinido para el rating de usuario.

import { Component, OnInit, AfterViewChecked, TemplateRef } from '@angular/core';
import { BsModalService, BsModalRef } from 'ngx-bootstrap/modal';
import {AuthenticationService} from '../../auth/authentication.service';
import { FormGroup,  FormBuilder,  Validators } from '@angular/forms';
import {PostsService} from '../../services/posts.service';
import {AnswersService} from '../../services/answers.service';
import {RatesService} from '../../services/rates.service';
import { AngularFireStorageReference, AngularFireStorage } from '@angular/fire/storage';
import { Observable } from 'rxjs';
import { finalize } from 'rxjs/operators';
import { NgForm } from '@angular/forms';
import { Router } from "@angular/router";
import { post } from 'selenium-webdriver/http';
import { Posts } from '../../../models/posts';
import { Answers } from '../../../models/answers';
import { Rates } from '../../../models/rates';
import { HttpClient } from '@angular/common/http';
import { Customers } from '../../../models/customers';
import { ToastrService } from 'ngx-toastr';

/**
*Muestra las publicaciones propias del usuario y gestiona su creación, modificación y eliminación.
*De igual manera, permite ver las respuestas asociadas a estas, así como, desbloquearlas y valorarlas.
*/
@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit 
{
  /**
  *Arreglo de publicaciones.
  */
  pposts: Posts[];
  /**
  *Arreglo de respuestas.
  */  
  aanswer: Answers[];
  /**
  *Arreglo de usuarios.
  */  
  uuser: Customers[];
  /**
  *Arreglo de calificaciones de usuario.
  */  
  rrate: Rates[];
  /**
  *@ignore
  */  
  newRate: Rates = new Rates();
  /**
  *Publicación seleccionada actualmente.
  */  
  selectedPost: Posts;
  /**
  *Respuesta seleccionada actualmente.
  */    
  selectedAnswer: Answers;
  /**
  *Calificación de usuario seleccionada actualmente.
  */    
  selectedRate: Rates;
  /**
  *@ignore
  */    
  nameValue;
  /**
  *@ignore
  */    
  descriptionValue;
  /**
  *URL para la imagen de la publicación a ser almacenada en Firebase Storage.
  */    
  imageUrl: string = null;
  /**
  *URL para la imagen de la publicación a ser eliminada.
  */      
  oldimageUrl: string = null;
  /**
  *@ignore
  */      
  newPost: Posts = new Posts();
  /**
  *Porcentaje para la barra de progreso al subir imagen.
  */      
  uploadProgress: Observable<number>;
  /**
  *Referencia al Storage de Firebase.
  */ 
  ref: AngularFireStorageReference;
  /**
  *URL de descarga de la imagen.
  */
  downloadURL: Observable<string>;
  /**
  *Nro de estrellas predefinido para el rating de usuario.
  */
  y: number = 0;
  /**
  *@ignore
  */
  x: number = 0;
  /**
  *Flag para determinar si calificó al usuario.
  */
  done: boolean = false;
  /**
  *@ignore
  */
  modalRef1: BsModalRef;
  /**
  *@ignore
  */  
  modalRef2: BsModalRef;
  /**
  *@ignore
  */  
  modalRef3: BsModalRef;
  /**
  *@ignore
  */  
  modalRef4: BsModalRef;
  /**
  *@ignore
  */  
  modalRef5: BsModalRef;
  /**
  *@ignore
  */  
  modalRef6: BsModalRef;

  /**
  *@ignore
  */
  constructor(private modalService: BsModalService, private router: Router, private answers: AnswersService, private rates: RatesService ,private posts: PostsService, private auth: AuthenticationService, private http: HttpClient, private storage: AngularFireStorage, private toastr: ToastrService) 
  { 

  }

  /**
  *Obtiene todas las publicaciones del usuario.
  */
  getPosts()
  {
    const id = this.auth.getUserDetails().id_user;
    this.posts.getpostsOwner(id).subscribe(pposts => this.pposts = pposts);
  }
 
  /**
  *Modal para crear una publicación.
  */
  create(template: TemplateRef<any>) 
  {
    this.newPost.id_post= 0;
    this.newPost.title="";
    this.newPost.description="";
    this.newPost.image="";
    this.newPost.id_owner= this.auth.getUserDetails().id_user;
    this.newPost.publish_date= new Date();
    this.newPost.resolved = false;
    this.newPost.categoria = "";
    
    this.modalRef1 = this.modalService.show(template);
    this.modalRef1.hide();
  }

  /**
  *Modal para modificar una publicación.
  */
  modify(template: TemplateRef<any>, editPost: Posts) 
  {
    this.selectedPost = editPost;
    this.nameValue= this.selectedPost.title;
    this.descriptionValue = this.selectedPost.description;
    this.modalRef2 = this.modalService.show(template);
    this.modalRef2.hide();
  }

  /**
  *Modal para realizar el pago.
  */
  pay(template: TemplateRef<any>, ans: Answers) 
  {
    this.selectedAnswer = ans;
    this.answers.saveAnswer(this.selectedAnswer);
    this.auth.getUsers(this.selectedAnswer.id_owner).subscribe(uuser => this.uuser = uuser);
    this.modalRef6 = this.modalService.show(template);
    this.modalRef6.hide();
  }

  /**
  *Califica la respuesta como útil y marca el post como resuelto.
  */
  valorate(resp :Answers)
  {
    this.selectedAnswer = resp;
    this.selectedAnswer.valorated = true;
    this.answers.valorateAnswer(this.selectedAnswer)
        .subscribe(() => {this.toastr.success('Esta respuesta resolvió tu problema');});

    this.selectedPost.resolved = true;    
    this.posts.updatePost(this.selectedPost).subscribe(() => {});
    console.log(this.selectedPost);
  }

  /**
  *Califica a un usuario.
  */
  rateUser(y)
  {
    console.log(y);
    this.newRate = {
      id_user1: this.selectedAnswer.id_owner,
      id_user2: this.auth.getUserDetails().id_user,
      value: y
    }

    this.x=y;
    console.log(this.newRate);

    this.rates.addrate(this.newRate).subscribe(
      () => {
        this.toastr.success('Has calificado al usuario exitosamente');
      },
      err => {
         this.toastr.warning('Usuario ya calificado con anterioridad');
      }
    );
    this.done = true;
  }

  /**
  *Califica la respuesta como no útil y marca el post como no resuelto.
  */
  notvalorate(resp :Answers)
  {
    this.selectedAnswer = resp;
    this.selectedAnswer.valorated = false;
    this.answers.valorateAnswer(this.selectedAnswer)
        .subscribe(() => {this.toastr.warning('Esta respuesta no resolvió tu problema');});

    this.selectedPost.resolved = false;    
    this.posts.updatePost(this.selectedPost).subscribe(() => {});
    console.log(this.selectedPost);        
  }  

  /**
  *Llama a opciones de pago para desbloquear una respuesta.
  */
  unlocked(viewans:Answers)
  {
    this.selectedAnswer = viewans;
    this.selectedAnswer.unlocked = true;
    this.answers.valorateAnswer(this.selectedAnswer)
        .subscribe(() =>  {
          this.toastr.success('Respuesta desbloqueada exitosamente');  
      });   
  }

  /**
  *Ver en detalle una respuesta individual.
  */
  viewAnswer(template: TemplateRef<any>, viewans:Answers)
  {
    this.selectedAnswer = viewans;
    //this.selectedRate=this.newRate;
    this.auth.getUsers(this.selectedAnswer.id_owner).subscribe(uuser => this.uuser = uuser);
    this.modalRef5 = this.modalService.show(template); 
    this.modalRef5.hide();   
  }

  /**
  *Ver todas las respuestas de una publicación.
  */
  viewAnswers(template: TemplateRef<any>, viewans:Posts)
  {
     this.selectedPost = viewans;
     this.answers.getanswerofpost(this.selectedPost.id_post).subscribe(aanswer => this.aanswer = aanswer);
     this.modalRef4 = this.modalService.show(template);
     this.modalRef4.hide();
  }

  /**
  *Borrar una publicación
  */
  delet(template: TemplateRef<any>, deletePost: Posts) 
  {
    this.selectedPost = deletePost;
    this.modalRef3 = this.modalService.show(template);
    this.modalRef3.hide();
  }

  /**
  *Crear una nueva publicación.
  */
  addpost(form: NgForm) 
  {

    if(form.value.title === "")
    {
      this.toastr.warning('Debe añadirse un título');
      return null;
    }
    else if(form.value.description === "")
    {
      this.toastr.warning('Debe añadirse una descripción');
      return null;
    }
    else if(form.value.categoria === "")
    {
      this.toastr.warning('Debe añadirse una categoría');
      return null;
    }
    else
    {
      var newPost = {
        id_post : 0,
        title : form.value.name,
        description : form.value.description,
        id_owner : this.auth.getUserDetails().id_user,
        publish_date : new Date(),
        resolved : false
      };
    }

    if(this.imageUrl!=null)
    {
      this.newPost.image = this.imageUrl;
    }

    this.imageUrl=null; 

    this.posts.addpost(this.newPost).subscribe(
      () => {
        this.toastr.success('Publicación creada exitosamente');
        this.ngOnInit();
      },
      err => {
        this.toastr.error('Error al crear publicación');
      }
    );
    this.modalRef1.hide();
  }

  /**
  *Actualiza una publicación existente.
  */
  update(form: NgForm) {

    if(form.value.name != "")
    {
      this.selectedPost.title = form.value.name;
    }
    else
    {
      this.toastr.warning('Debe añadirse un título');
      return null;      
    }

    if(form.value.descripcion != "")
    {
      this.selectedPost.description = form.value.descripcion;
    }
    else
    {
      this.toastr.warning('Debe añadirse una descripción');
      return null;        
    }

    if(this.imageUrl!=null)
    {
      this.oldimageUrl=this.selectedPost.image;
      if(this.oldimageUrl!="")
      {
        this.deleteImage(this.oldimageUrl);
      }
      this.selectedPost.image=this.imageUrl;
      this.imageUrl=null;
    }

    this.posts.updatePost(this.selectedPost)
      .subscribe(() => {
        this.toastr.success('Publicación editada exitosamente')
      },
      err =>
      {
        this.toastr.error('Error al editar la publicación');
      });
    this.modalRef2.hide();

  }

  /**
  *Borra una publicación existente.
  */
  delete() 
  {
    this.posts.deletePost(this.selectedPost).subscribe(
      () => {
        this.deleteImage(this.selectedPost.image);
        this.toastr.success('Publicación borrada exitosamente');
        this.ngOnInit();
      },
      err => {
        this.toastr.error('Error al borrar la publicación');
      }
    );
    this.modalRef3.hide();
  }

  /**
  *Borra una imagen de Firebase Storage a partir de una URL.
  */
  deleteImage(downloadUrl) 
  {
    return this.storage.storage.refFromURL(downloadUrl).delete();
  } 

  /**
  *Sube la imagen al servicio de Firebase Storage y obtiene la url de la misma.
  */
  upload(event) 
  {
    //Obtiene la imagen:
    const file = event.target.files[0];
    
    // Genera un ID random para la imagen:
    const randomId = Math.random().toString(36).substring(2);
    const filepath = `Posts_Images/${randomId}`;

    //Cargar imagen:
    const task = this.storage.upload(filepath, file);
    this.ref = this.storage.ref(filepath);

    //Observa los cambios en el % de la barra de progresos:
    this.uploadProgress = task.percentageChanges();

    //Notifica cuando la URL de descarga está disponible:
    task.snapshotChanges().pipe(
      finalize(() => {
        this.downloadURL = this.ref.getDownloadURL();  
        this.downloadURL.subscribe(url => {this.imageUrl = url} );
        console.log(this.imageUrl);
      })
    ).subscribe();
  }

  /**
  *Cancela la creación de una publicación.
  */
  cancelAdd()
  {
    if(this.imageUrl!=null)
    {
      this.deleteImage(this.imageUrl);
    }
    this.imageUrl=null;
    this.modalRef1.hide();
  }

  /**
  *Cancela la edición de una publicación.
  */
  cancelEdit()
  {
    if(this.imageUrl!=null)
    {
      this.deleteImage(this.imageUrl);
    }
    this.imageUrl=null;
    this.modalRef2.hide();
  }

  /**
  *Comprueba si se hizo efectivo el pago por la respuesta.
  */
  comprobar()
  {
    if(this.answers.getPay()==true)
    {
      this.unlocked(this.selectedAnswer);
    }
    else
    {
      this.toastr.warning('Todavía no se ha concretado el pago');
    }
    this.modalRef6.hide();
  }
  
  /**
  *Obtiene todas las publicaciones del usuario al inicio
  */
  ngOnInit() 
  {
    this.getPosts();
  }

}

<div class="container">
    <h1 class="text-center" style="color: white">Mis Publicaciones</h1>
    <br>

    <!--Agregue un nuevo post-->
    <div class="containet text-center">
       	<button type="button" class="btn btn-success btn-create" (click)="create(template1)"
        	tooltip="Agregar nueva publicación" placement="bottom">
      		<i class="fas fa-plus fa-2x"></i>
  		</button>
    </div>
    <hr>       

    <!--Visualización de tarjetas-->
    <div class="container-fluid" *ngFor="let post of pposts">     	
    	<div class="notice notice-info notice-lg">
        	<strong>{{post.title}}</strong>
        	<div class="text-right">
        		<small>
        			<br>
					<span *ngIf="!post.resolved" class="badge badge-danger float-right pull-right">
						No resuelto
					</span>
        			<span *ngIf="post.resolved" class="badge badge-success float-right pull-right">
        				Resuelto
        			</span>
        			<br>
        			<b>Publicado el {{post.publish_date}}</b>
        		</small>
        	</div>	
        	<hr>
        	<img *ngIf="post.image!=''" src="{{post.image}}" class="img-fluid text-center avatar">
        	<img *ngIf="post.image==''" src="/assets/images/no-image.png" class="img-fluid text-center avatar">
        	<br>
        	<p>{{ post.description }}</p>

        	<div class="text-right">
				&nbsp;
				<button type="button" class="btn btn-info btn-answer" 
					(click)="viewAnswers(template4, post)" tooltip="Ver respuestas" placement="bottom">
				   <i class="far fa-eye"></i>
			   </button>
			   &nbsp;
				<button type="button" class="btn btn-primary btn-modify" (click)="modify(template2, post)"
				   tooltip="Modificar la publicación" placement="bottom">
			      	<i class="fas fa-pencil-alt"></i>
			  	</button>
			  	&nbsp;
			  	<button type="button" class="btn btn-danger btn-delete" (click)="delet(template3, post)"
			  		tooltip="Eliminar la publicación" placement="bottom">
			      	<i class="fas fa-trash-alt"></i>
			  	</button>
        	</div>
    	</div>  	
	<br><br>    		
	</div>

</div>

<!--Modal para crear la publicación-->
<ng-template #template1>
	<div class="modal-header">
	    <h4 class="modal-title pull-left">Crear nueva publicación</h4>
	    <button type="button" class="close pull-right" aria-label="Close" (click)="modalRef1.hide()">
	      <span aria-hidden="true">&times;</span>
	    </button>
	</div>

	<div class="modal-body">
		<div class="container text-center">	
			<div class="tab-content">
				
				<div class="text-center">
					<img *ngIf="this.imageUrl==null" src="/assets/images/no-image.png" class="img-fluid img-circle img-thumbnail profile-pic img-content">
                    <img *ngIf="this.imageUrl!=null" src={{this.imageUrl}} class="img-fluid img-circle img-thumbnail profile-pic img-content">
					<h6>Seleccione la foto para el producto</h6>
					<br>
						
					<div class="container">

						<!--Barra de progreso-->
						<progressbar [value]="uploadProgress| async" type="primary" [striped]="true" [animate]="true"></progressbar>

						<!--Muestra el progreso de la barra-->
						<div class="item">
								Progress: {{ (uploadProgress | async) / 100 | percent }}
						</div>
						<br>
						<div *ngIf="downloadURL | async; let downloadSrc" class="alert alert-info" role="alert">
            			<p>La foto se cargó correctamente</p>
        				</div>

						<!--Se sube una nueva foto para el usuario-->
						<div class="item">

							<input #inputFile class="hidden" type="file" (change)="upload($event)" accept=".png,.jpg">
							<button type="button" class="btn btn-lg btn-success" (click)="inputFile.click()">
								Subir foto
							<i class="fas fa-upload"></i>
							</button>
						</div>
					</div>
				</div>
				<hr>
								
				<form #f="ngForm" novalidate="" method="POST">
					
					<div class="form-group">
						<div class="col-xs-6">
								<label for="name"><h4>Título</h4></label>
								<input type="text"  name="title" class="form-control"  placeholder="Nombre del Post" [(ngModel)]="newPost.title">
						</div>
					</div>
					<div class="form-group">
						<div class="col-xs-6">
								<label for="descripcion"><h4>Descripción</h4></label><br>
								<textarea type="text" name="description" placeholder="Descripcion del Post" class="form-control" [(ngModel)]="newPost.description"></textarea>
						</div>
					</div>

					<div class="form-group">
						<div class="col-xs-6">
								<label for="descripcion"><h4>Categoria</h4></label><br>
								<select class="browser-default custom-select" name="categoria" [(ngModel)]="newPost.categoria" >
									<option value="Telefono">Teléfono/Tableta</option>
									<option value="PC">PC/Laptop</option>
									<option value="Consola">Consolas</option>
									<option value="Otros">Otros</option>
								  </select>
						</div>
					</div>


					<hr>

					<div class="text-center">
						<button class="btn btn-primary" value="POST" (click)="addpost(f)" type="submit">Crear Publicación
							<i class="fas fa-pencil-alt"></i>
						</button>
						<br><br>
						<button class="btn btn-cancelar btn-danger" (click)="cancelAdd()">Cancelar
							<i class="far fa-times-circle"></i>
						</button>
					</div>
			</form>
	</div>

		</div>

	  </div>
</ng-template>

<!--Modal para modificar la publicación-->
<ng-template #template2>
	<div class="modal-header">
		<h4 class="modal-title pull-left">Modificar publicación</h4>
		<button type="button" class="close pull-right" aria-label="Close" (click)="modalRef2.hide()">
	  		<span aria-hidden="true">&times;</span>
		</button>
	</div>
	<div class="modal-body">
		<div class="container text-center">
			<div class="tab-content">
				
				<form #f="ngForm" class="form" id="ProductForm">
					<img *ngIf="selectedPost.image==''" src="/assets/images/no-image.png" class="img-fluid img-circle img-thumbnail profile-pic img-content">
                    <img *ngIf="selectedPost.image!=''" src={{selectedPost.image}} class="img-fluid img-circle img-thumbnail profile-pic img-content">
					<h6>Seleccione la foto para el producto</h6>
					<br>

					<div class="container">
						<!--Barra de progreso-->
						<progressbar [value]="uploadProgress| async" type="primary" [striped]="true" [animate]="true"></progressbar>

						<!--Muestra el progreso de la barra-->
						<div class="item">
								Progress: {{ (uploadProgress | async) / 100 | percent }}
						</div>
						<br>
						<div *ngIf="downloadURL | async; let downloadSrc" class="alert alert-info" role="alert">
            			<p>La foto se cargó correctamente</p>
        				</div>
						<!--Se sube una nueva foto para el usuario-->
						<div class="item">
								<!--Selecciona un archivo .png o .jpg-->
								<input #inputFile class="hidden" type="file" (change)="upload($event)" accept=".png,.jpg">
								<!--Botón para poner en funcionamiento el input-->
								<button type="button" class="btn btn-lg btn-success" (click)="inputFile.click()">
								Subir foto
								<i class="fas fa-upload"></i>
								</button>
						</div>
					</div>
					<hr>									
					<div class="form-group">
						<div class="col-xs-6">
								<label for="name"><h4>Título</h4></label>
								<input [(ngModel)]="nameValue" #name="ngModel" ngModel type="text" class="form-control" name="name" id="name" placeholder="{{selectedPost.title}}">
						</div>
					</div>
					<div class="form-group">
						<div class="col-xs-6">
							<label for="descripcion"><h4>Descripción</h4></label><br>
							<textarea [(ngModel)]="descriptionValue" #descripcion="ngModel"
							type="text" class="form-control" name="descripcion" id="descripcion" placeholder="{{selectedPost.description}}"></textarea>
						</div>
					</div>
					<hr>
					<div class="form-group text-center">
						<div class="col-xs-12">
							<br>
							<button class="btn btn-primary" (click)="update(f)" type="submit">Actualizar
											<i class="fas fa-sync-alt"></i>
							</button>
							<br><br>
							<button class="btn btn-cancelar btn-danger" (click)="cancelEdit()">Cancelar
											<i class="far fa-times-circle"></i>
							</button>
						</div>
					</div>
				</form>
			</div>
		</div>
	</div>
</ng-template>

<!--Modal para eliminar la publicación-->
<ng-template #template3>
	<div class="modal-header">
		<h4 class="modal-title pull-left">Eliminar publicación</h4>
	    <button type="button" class="close pull-right" aria-label="Close" (click)="modalRef3.hide()">
	      <span aria-hidden="true">&times;</span>
	    </button>
	</div>
	<div class="modal-body">
		¿Desea borrar de forma permanente la publicación seleccionada?
		<br><br>
		<div class="text-center">
			<button (click)="delete()" class="btn btn-success" type="button">Sí</button>
			&nbsp;
			<button (click)="modalRef3.hide()" class="btn btn-danger btn-cancelar" type="button">No</button>
		</div>
	</div>
</ng-template>

<!--Modal para ver respuestas-->
<ng-template #template4>
	<div class="modal-header">
		<h4 class="modal-title pull-left">Respuestas de la publicación</h4>
		<button type="button" class="close pull-right" aria-label="Close" (click)="modalRef4.hide()">
	  		<span aria-hidden="true">&times;</span>
		</button>
	</div>
	<div class="modal-body">

		<div *ngIf="aanswer<=0" class="container-fluid text-center">
			<strong>No existen respuestas para la publicación</strong>
			<br><br>
				<i class="fas fa-frown fa-5x"></i>
		</div>

		<div class="container-fluid" *ngFor="let answer of aanswer">
	    	<div class="notice notice-success notice-md">

				<!--Respuesta bloqueda (pago con Paypal)-->
				<div *ngIf="!answer.unlocked">
					<button class="btn btn-danger btn-unlock" 
						(click)="pay(template6, answer);">
						<i class="fas fa-lock"></i>&nbsp;
						<strong>
							No se puede acceder a la respuesta, por favor asegúrese de desbloquearla.
						</strong>
					</button>
				</div>
				<div *ngIf="answer.unlocked">
					<strong>{{answer.text | slice:0:20}} ...</strong>
					<div class="text-right">
						<button class="btn btn-success btn-answer" 
							(click)="viewAnswer(template5,answer)" tooltip="Ver en detalle" 
							placement="bottom">
							<i class="fas fa-eye"></i>
						</button>&nbsp;	
						<button class="btn btn-primary btn-answer" *ngIf="!answer.valorated"
							(click)="valorate(answer)" tooltip="¡Solucionó el problema!" 
							placement="bottom">
							<i class="fas fa-heart"></i>
						</button>&nbsp;
						<button class="btn btn-danger btn-answer" *ngIf="answer.valorated"
							(click)="notvalorate(answer)" tooltip="¡No me sirvió!" 
							placement="bottom">
							<i class="fas fa-heart-broken"></i>
						</button>						
					</div>
				</div>	
	    	</div>
	    	<hr>	
		</div>

	</div>
</ng-template>

<!--Modal para detallar respuestas-->
<ng-template #template5>
	<div class="modal-header">
		<h4 class="modal-title pull-left">Detalles de la publicación</h4>
		<button type="button" class="close pull-right" aria-label="Close" (click)="modalRef5.hide()">
	  		<span aria-hidden="true">&times;</span>
		</button>
	</div>
	<div class="modal-body">

	    	<div class="notice notice-success notice-md">
				<!--Respuesta desbloqueada (pago realizado)-->
				<div class="container-fluid text-center" *ngFor="let user of uuser">
					<img *ngIf="user.image==null" src="/assets/images/sin-perfil.png" class="img-fluid img-circle img-thumbnail profile-pic img-content-user">
					<img *ngIf="user.image!=null" src="{{user.image}}" class="img-fluid img-circle img-thumbnail profile-pic img-content-user">
					<strong>{{ user.username }}</strong>
					<hr>
					<p>{{ selectedAnswer.text }}</p>
					<hr>
					<strong>Precio pagado:</strong>
					<p>{{ selectedAnswer.price | currency: 'USD'}}</p>
					<hr>
					
					<div *ngIf="selectedAnswer.valorated">
						<alert type="success">Esta respuesta resolvió tu problema</alert>
						<br><br>

						<div *ngIf="!done">
							<p>¡Hazle saber a <b>{{ user.username }}</b> lo útil que te fue su respuesta!</p>
							<br>	
						  <rating [max]="5" [(ngModel)]="y" [customTemplate]="tt"></rating>
						  <ng-template #tt let-i="index" let-v="value">
						    <button class="btn btn-answer btn-{{i < v ? 'warning' : 'default'}}"
						    	(click)="rateUser(i+1)">
						      {{i < v ? '&#9733;' : '&#9734;'}}
						    </button>
						  </ng-template>
						</div>

						<div *ngIf="done">
						  <strong>¡Has calificado a {{user.username}} con {{x}} estrellas!</strong>
						</div>

					</div>
					<div *ngIf="!selectedAnswer.valorated">
						<alert type="danger">Esta respuesta NO resolvió tu problema</alert>
					</div>
				</div>									    	
	        	
	    	</div>	

	</div>
</ng-template>

<ng-template #template6>
	<div class="modal-header">
		<h4 class="modal-title pull-left">Detalles de la publicación</h4>
		<button type="button" class="close pull-right" aria-label="Close" (click)="modalRef6.hide()">
	  		<span aria-hidden="true">&times;</span>
		</button>
	</div>
	<div class="modal-body">

	    	<div class="notice notice-success notice-md">
				<!--Respuesta bloqueada, pago por realizar-->
				<div class="container-fluid text-center" *ngFor="let user of uuser">
					<img *ngIf="user.image==null" src="/assets/images/sin-perfil.png" class="img-fluid img-circle img-thumbnail profile-pic img-content-user">
					<img *ngIf="user.image!=null" src="{{user.image}}" class="img-fluid img-circle img-thumbnail profile-pic img-content-user">
					<strong>{{ user.username }}</strong>
					<hr>
					<strong>Respuestas Valoradas: {{ user.respuestas_valoradas }}</strong>
					<hr>
					<strong>Rating general:</strong>
					<br>
					<div class="text-center">
						<div *ngIf="user.rating==0 || user.rating==null">
							<i class="far fa-star"></i>
							<i class="far fa-star"></i>
							<i class="far fa-star"></i>
							<i class="far fa-star"></i>
							<i class="far fa-star"></i>
						</div>						
						<div *ngIf="user.rating==1">
							<i class="fas fa-star"></i>
							<i class="far fa-star"></i>
							<i class="far fa-star"></i>
							<i class="far fa-star"></i>
							<i class="far fa-star"></i>
						</div>
						<div *ngIf="user.rating==2">
							<i class="fas fa-star"></i>
							<i class="fas fa-star"></i>
							<i class="far fa-star"></i>
							<i class="far fa-star"></i>
							<i class="far fa-star"></i>
						</div>
						<div *ngIf="user.rating==3">
							<i class="fas fa-star"></i>
							<i class="fas fa-star"></i>
							<i class="fas fa-star"></i>
							<i class="far fa-star"></i>
							<i class="far fa-star"></i>
						</div>
						<div *ngIf="user.rating==4">
							<i class="fas fa-star"></i>
							<i class="fas fa-star"></i>
							<i class="fas fa-star"></i>
							<i class="fas fa-star"></i>
							<i class="far fa-star"></i>
						</div>
						<div *ngIf="user.rating==5">
							<i class="fas fa-star"></i>
							<i class="fas fa-star"></i>
							<i class="fas fa-star"></i>
							<i class="fas fa-star"></i>
							<i class="fas fa-star"></i>
						</div>							
					</div>
					<alert type="info">Guíese por los ratings y valoraciones antes de pagar una respuesta</alert>
					<hr>
					<p>{{ selectedAnswer.text |  slice:0:150}}...</p>
					<alert type="danger">Para ver el resto de la respuesta pagué el precio indicado abajo.</alert>
					<hr>
					<strong>Precio a pagar:</strong>
					<p>{{ selectedAnswer.price | currency: 'USD'}}</p>
					<hr>
					<app-pays></app-pays>
					<br><br>
					<button class="btn btn-primary btn-unlock" (click)="comprobar()" type="submit">Comprobar pago
						<i class="fas fa-sync-alt"></i>
					</button>

				</div>									    	
	        	
	    	</div>	

	</div>
</ng-template>


./home.component.css

.btn-create, .btn-modify, .btn-delete, .btn-answer, .btn-sad
{
	border-radius: 60%;
	-webkit-box-shadow: 0 5px 8px -6px rgba(0,0,0,.2);
    -moz-box-shadow: 0 5px 8px -6px rgba(0,0,0,.2);
    box-shadow: 0 5px 8px -6px rgba(0,0,0,.2);
}

.btn-unlock
{
    -webkit-box-shadow: 0 5px 8px -6px rgba(0,0,0,.2);
    -moz-box-shadow: 0 5px 8px -6px rgba(0,0,0,.2);
    box-shadow: 0 5px 8px -6px rgba(0,0,0,.2);    
}

.notice {
    padding: 15px;
    background-color: #fafafa;
    border-left: 6px solid #7f7f84;
    margin-bottom: 10px;
    -webkit-box-shadow: 0 5px 8px -6px rgba(0,0,0,.2);
       -moz-box-shadow: 0 5px 8px -6px rgba(0,0,0,.2);
            box-shadow: #202123;
}

.notice-lg {
    padding: 35px;
    font-size: large;
}

.notice-md {
    padding: 25px;
    font-size: medium;
}

.notice-success {
    border-color: #80D651;
}
.notice-success>strong {
    color: #80D651;
}
.notice-info {
    /*border-color: #45ABCD;*/
    border-color: #ac45cd;
}
.notice-info>strong {
    /*color: #45ABCD;*/
    color: #ac45cd;
}

.modal-header
{
    background: #834d9b;  /* fallback for old browsers */
    background: -webkit-linear-gradient(to right, #d04ed6, #834d9b);  /* Chrome 10-25, Safari 5.1-6 */
    background: linear-gradient(to right, #d04ed6, #834d9b);
    color: white;
}

.hidden 
{  
    display: none;
}

hr 
{
    background-color: azure;
}

.row 
{
    padding: 20px;
}

/*Prop. para imágenes*/

.img-content {
    display: block;
    width: 200px;
    height: 200px;
    margin-left: auto;
    margin-right: auto;
    border-radius: 50%;
}

.img-content-user {
    display: block;
    width: 100px;
    height: 100px;
    margin-left: auto;
    margin-right: auto;
    border-radius: 50%;
}

.avatar
{
    display: block;
    width: 500px;
    height: 480px;
    margin-left: auto;
    margin-right: auto;    
}

.modal-body
{
    color: #151515;
}

.info
{
    color: #80D651;   
}



Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""