src/app/components/home/home.component.ts
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.
selector | app-home |
styleUrls | ./home.component.css |
templateUrl | ./home.component.html |
Properties |
Methods |
addpost | ||||||
addpost(form: NgForm)
|
||||||
Crear una nueva publicación.
Parameters :
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 :
Returns :
void
|
delet | |||||||||
delet(template: TemplateRef
|
|||||||||
Borrar una publicación
Parameters :
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 :
Returns :
any
|
getPosts |
getPosts()
|
Obtiene todas las publicaciones del usuario.
Returns :
void
|
modify | |||||||||
modify(template: TemplateRef
|
|||||||||
Modal para modificar una publicación.
Parameters :
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 :
Returns :
void
|
pay | |||||||||
pay(template: TemplateRef
|
|||||||||
Modal para realizar el pago.
Parameters :
Returns :
void
|
rateUser | ||||
rateUser(y)
|
||||
Califica a un usuario.
Parameters :
Returns :
void
|
unlocked | ||||||
unlocked(viewans: Answers)
|
||||||
Llama a opciones de pago para desbloquear una respuesta.
Parameters :
Returns :
void
|
update | ||||||
update(form: NgForm)
|
||||||
Actualiza una publicación existente.
Parameters :
Returns :
any
|
upload | ||||
upload(event)
|
||||
Sube la imagen al servicio de Firebase Storage y obtiene la url de la misma.
Parameters :
Returns :
void
|
valorate | ||||||
valorate(resp: Answers)
|
||||||
Califica la respuesta como útil y marca el post como resuelto.
Parameters :
Returns :
void
|
viewAnswer | |||||||||
viewAnswer(template: TemplateRef
|
|||||||||
Ver en detalle una respuesta individual.
Parameters :
Returns :
void
|
viewAnswers | |||||||||
viewAnswers(template: TemplateRef
|
|||||||||
Ver todas las respuestas de una publicación.
Parameters :
Returns :
void
|
aanswer |
Type : Answers[]
|
Defined in src/app/components/home/home.component.ts:39
|
Arreglo de respuestas. |
done |
Type : boolean
|
Default value : false
|
Flag para determinar si calificó al usuario. |
downloadURL |
Type : Observable<string>
|
Defined in src/app/components/home/home.component.ts:95
|
URL de descarga de la imagen. |
imageUrl |
Type : string
|
Default value : null
|
Defined in src/app/components/home/home.component.ts:75
|
URL para la imagen de la publicación a ser almacenada en Firebase Storage. |
oldimageUrl |
Type : string
|
Default value : null
|
Defined in src/app/components/home/home.component.ts:79
|
URL para la imagen de la publicación a ser eliminada. |
pposts |
Type : Posts[]
|
Defined in src/app/components/home/home.component.ts:35
|
Arreglo de publicaciones. |
ref |
Type : AngularFireStorageReference
|
Defined in src/app/components/home/home.component.ts:91
|
Referencia al Storage de Firebase. |
rrate |
Type : Rates[]
|
Defined in src/app/components/home/home.component.ts:47
|
Arreglo de calificaciones de usuario. |
selectedAnswer |
Type : Answers
|
Defined in src/app/components/home/home.component.ts:59
|
Respuesta seleccionada actualmente. |
selectedPost |
Type : Posts
|
Defined in src/app/components/home/home.component.ts:55
|
Publicación seleccionada actualmente. |
selectedRate |
Type : Rates
|
Defined in src/app/components/home/home.component.ts:63
|
Calificación de usuario seleccionada actualmente. |
uploadProgress |
Type : Observable<number>
|
Defined in src/app/components/home/home.component.ts:87
|
Porcentaje para la barra de progreso al subir imagen. |
uuser |
Type : Customers[]
|
Defined in src/app/components/home/home.component.ts:43
|
Arreglo de usuarios. |
y |
Type : number
|
Default value : 0
|
Defined in src/app/components/home/home.component.ts:99
|
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">
<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>
<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>
<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">×</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">×</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">×</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>
<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">×</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>
<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>
<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>
<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">×</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 ? '★' : '☆'}}
</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">×</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;
}