feat: Reportes, chat de discusión y mejoras de navegación
- Tab "Reportados" en Contratos (cliente) y tab "Reportadas" en Postulaciones (proveedor) con skeleton loading e ionViewWillEnter
- Modal de chat para discusión de reportes: burbujas por rol (propio/otro/moderador), skeleton, input con cámara y envío
- Endpoints GET/POST contracts/reports/{id}/comments en ichamba.service
- userId guardado en AuthService desde auth/user para identificar mensajes propios
- Botón "Postularse" corregido con slot=end en ion-item
- Todas las secciones de tabs migradas de ngOnInit a ionViewWillEnter + ChangeDetectorRef.detectChanges()
- Android navigation bar reactiva al tema del sistema vía values/values-night styles.xml
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
12
android/app/src/main/res/values-night/styles.xml
Normal file
12
android/app/src/main/res/values-night/styles.xml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<style name="AppTheme.NoActionBar" parent="Theme.AppCompat.DayNight.NoActionBar">
|
||||||
|
<item name="windowActionBar">false</item>
|
||||||
|
<item name="windowNoTitle">true</item>
|
||||||
|
<item name="android:background">@null</item>
|
||||||
|
<item name="android:navigationBarColor">#000000</item>
|
||||||
|
<item name="android:windowLightNavigationBar">false</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</resources>
|
||||||
@@ -13,6 +13,8 @@
|
|||||||
<item name="windowActionBar">false</item>
|
<item name="windowActionBar">false</item>
|
||||||
<item name="windowNoTitle">true</item>
|
<item name="windowNoTitle">true</item>
|
||||||
<item name="android:background">@null</item>
|
<item name="android:background">@null</item>
|
||||||
|
<item name="android:navigationBarColor">#FFFFFF</item>
|
||||||
|
<item name="android:windowLightNavigationBar">true</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ const routes: Routes = [
|
|||||||
{ path: 'start', loadChildren: () => import('./pages/contracts/start/start.module').then(m => m.StartPageModule), canActivate: [AuthGuard]},
|
{ path: 'start', loadChildren: () => import('./pages/contracts/start/start.module').then(m => m.StartPageModule), canActivate: [AuthGuard]},
|
||||||
{ path: 'review/:contract_id', loadChildren: () => import('./pages/contracts/review/review.module').then(m => m.ReviewPageModule), canActivate: [AuthGuard] },
|
{ path: 'review/:contract_id', loadChildren: () => import('./pages/contracts/review/review.module').then(m => m.ReviewPageModule), canActivate: [AuthGuard] },
|
||||||
{ path: 'report/:contract_id', loadChildren: () => import('./pages/contracts/report/report.module').then(m => m.ReportPageModule), canActivate: [AuthGuard] },
|
{ path: 'report/:contract_id', loadChildren: () => import('./pages/contracts/report/report.module').then(m => m.ReportPageModule), canActivate: [AuthGuard] },
|
||||||
{ path: 'reports', loadChildren: () => import('./pages/reports/reports.module').then(m => m.ReportsPageModule), canActivate: [AuthGuard]},
|
|
||||||
{ path: 'nohome/:contract_id', loadChildren: () => import('./pages/contracts/nohome/nohome.module').then(m => m.NohomePageModule), canActivate: [AuthGuard] },
|
{ path: 'nohome/:contract_id', loadChildren: () => import('./pages/contracts/nohome/nohome.module').then(m => m.NohomePageModule), canActivate: [AuthGuard] },
|
||||||
{ path: 'extra', loadChildren: () => import('./pages/contracts/extra/extra.module').then(m => m.ExtraPageModule), canActivate: [AuthGuard] },
|
{ path: 'extra', loadChildren: () => import('./pages/contracts/extra/extra.module').then(m => m.ExtraPageModule), canActivate: [AuthGuard] },
|
||||||
{ path: 'ended', loadChildren: () => import('./pages/postulations/ended/ended.module').then(m => m.EndedPageModule), canActivate: [AuthGuard] },
|
{ path: 'ended', loadChildren: () => import('./pages/postulations/ended/ended.module').then(m => m.EndedPageModule), canActivate: [AuthGuard] },
|
||||||
|
|||||||
@@ -11,6 +11,24 @@
|
|||||||
<ion-refresher slot="fixed" (ionRefresh)="refresh($event)">
|
<ion-refresher slot="fixed" (ionRefresh)="refresh($event)">
|
||||||
<ion-refresher-content></ion-refresher-content>
|
<ion-refresher-content></ion-refresher-content>
|
||||||
</ion-refresher>
|
</ion-refresher>
|
||||||
|
|
||||||
|
<ng-container *ngIf="loading">
|
||||||
|
<ion-card *ngFor="let _ of [1,2]">
|
||||||
|
<ion-item style="--border-color: #fff">
|
||||||
|
<ion-label>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 55%; height: 18px; margin-bottom: 8px"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 85%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 70%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 50%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 40%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 35%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 65%; height: 16px; margin-top: 6px"></ion-skeleton-text>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</ion-card>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="!loading">
|
||||||
<ng-container *ngFor="let ccontract of ccontracts; let i = index">
|
<ng-container *ngFor="let ccontract of ccontracts; let i = index">
|
||||||
<ion-card *ngIf="ccontract.status==1">
|
<ion-card *ngIf="ccontract.status==1">
|
||||||
<ion-item style="--border-color: #fff">
|
<ion-item style="--border-color: #fff">
|
||||||
@@ -29,4 +47,5 @@
|
|||||||
<ion-button *ngIf="ccontract.past_due < 0" style="height: 4.0em; padding-right: 1.0em; padding-bottom:1.0em; float: right" color="danger" (click)="cancelContract(ccontract.id, ccontract.date)">{{'contracts.cancel_1.1' | translate}}<br>{{'contracts.cancel_1.2' | translate}}</ion-button>
|
<ion-button *ngIf="ccontract.past_due < 0" style="height: 4.0em; padding-right: 1.0em; padding-bottom:1.0em; float: right" color="danger" (click)="cancelContract(ccontract.id, ccontract.date)">{{'contracts.cancel_1.1' | translate}}<br>{{'contracts.cancel_1.2' | translate}}</ion-button>
|
||||||
</ion-card>
|
</ion-card>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, ChangeDetectorRef } from '@angular/core';
|
||||||
import { ModalController, MenuController, NavController } from '@ionic/angular';
|
import { ModalController, MenuController, NavController } from '@ionic/angular';
|
||||||
import { EventService } from '../../../services/event.service';
|
import { EventService } from '../../../services/event.service';
|
||||||
import { EnvService } from 'src/app/services/env.service';
|
import { EnvService } from 'src/app/services/env.service';
|
||||||
@@ -15,11 +15,12 @@ import { AlertController } from '@ionic/angular';
|
|||||||
styleUrls: ['./contracted.page.scss'],
|
styleUrls: ['./contracted.page.scss'],
|
||||||
standalone: false
|
standalone: false
|
||||||
})
|
})
|
||||||
export class ContractedPage implements OnInit {
|
export class ContractedPage {
|
||||||
|
|
||||||
ccontracts: any[] = [];
|
ccontracts: any[] = [];
|
||||||
ccontracts_dates: any[] = [];
|
ccontracts_dates: any[] = [];
|
||||||
lang: boolean = false;
|
lang: boolean = false;
|
||||||
|
loading = true;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private modalController: ModalController,
|
private modalController: ModalController,
|
||||||
@@ -33,32 +34,29 @@ export class ContractedPage implements OnInit {
|
|||||||
private translateService: TranslateService,
|
private translateService: TranslateService,
|
||||||
private languageService: LanguageService,
|
private languageService: LanguageService,
|
||||||
private env: EnvService,
|
private env: EnvService,
|
||||||
|
private cdr: ChangeDetectorRef,
|
||||||
) {
|
) {
|
||||||
this.events.subscribe('refreshccontracts', (data) => {
|
this.events.subscribe('refreshccontracts', (data) => {
|
||||||
this.getccontracts();
|
this.getccontracts();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ionViewWillEnter() {
|
||||||
|
this.lang = this.languageService.getDefaultLanguage() === 'es';
|
||||||
|
this.loading = true;
|
||||||
this.getccontracts();
|
this.getccontracts();
|
||||||
if (this.languageService.getDefaultLanguage() == 'es') {
|
|
||||||
this.lang = true;
|
|
||||||
} else {
|
|
||||||
this.lang = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
refresh(event: any) {
|
refresh(event: any) {
|
||||||
this.ichambaService.getCurrentcontracts().subscribe(
|
this.ichambaService.getCurrentcontracts().subscribe(
|
||||||
data => {
|
data => {
|
||||||
this.ccontracts = data;
|
this.ccontracts = data;
|
||||||
|
this.ccontracts_dates = [];
|
||||||
for (var i of this.ccontracts) {
|
for (var i of this.ccontracts) {
|
||||||
if (this.languageService.getDefaultLanguage() == 'es') {
|
const locale = this.lang ? 'es-US' : 'en-US';
|
||||||
this.ccontracts_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace("," ,"")).toLocaleDateString('es-US', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute:'numeric', timeZoneName: 'long'}));
|
this.ccontracts_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace(',', '')).toLocaleDateString(locale, { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric', timeZoneName: 'long' }));
|
||||||
} else {
|
|
||||||
this.ccontracts_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace("," ,"")).toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute:'numeric', timeZoneName: 'long'}));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
this.cdr.detectChanges();
|
||||||
event.target.complete();
|
event.target.complete();
|
||||||
}, error => {
|
}, error => {
|
||||||
this.alertService.presentToast(this.translateService.instant('alerts.error') + error['status']);
|
this.alertService.presentToast(this.translateService.instant('alerts.error') + error['status']);
|
||||||
@@ -70,14 +68,15 @@ export class ContractedPage implements OnInit {
|
|||||||
this.ichambaService.getCurrentcontracts().subscribe(
|
this.ichambaService.getCurrentcontracts().subscribe(
|
||||||
data => {
|
data => {
|
||||||
this.ccontracts = data;
|
this.ccontracts = data;
|
||||||
|
this.ccontracts_dates = [];
|
||||||
for (var i of this.ccontracts) {
|
for (var i of this.ccontracts) {
|
||||||
if (this.languageService.getDefaultLanguage() == 'es') {
|
const locale = this.lang ? 'es-US' : 'en-US';
|
||||||
this.ccontracts_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace("," ,"")).toLocaleDateString('es-US', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute:'numeric', timeZoneName: 'long'}));
|
this.ccontracts_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace(',', '')).toLocaleDateString(locale, { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric', timeZoneName: 'long' }));
|
||||||
} else {
|
|
||||||
this.ccontracts_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace("," ,"")).toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute:'numeric', timeZoneName: 'long'}));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
this.loading = false;
|
||||||
|
this.cdr.detectChanges();
|
||||||
}, error => {
|
}, error => {
|
||||||
|
this.loading = false;
|
||||||
this.alertService.presentToast(this.translateService.instant('alerts.error') + error['status']);
|
this.alertService.presentToast(this.translateService.instant('alerts.error') + error['status']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ const routes: Routes = [
|
|||||||
{
|
{
|
||||||
path: 'finished',
|
path: 'finished',
|
||||||
loadChildren: () => import('./finished/finished.module').then(m => m.FinishedPageModule)
|
loadChildren: () => import('./finished/finished.module').then(m => m.FinishedPageModule)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'reported',
|
||||||
|
loadChildren: () => import('../reports/reports.module').then(m => m.ReportsPageModule)
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,5 +24,10 @@
|
|||||||
<ion-label>{{'contracts.header_3' | translate}}</ion-label>
|
<ion-label>{{'contracts.header_3' | translate}}</ion-label>
|
||||||
</ion-tab-button>
|
</ion-tab-button>
|
||||||
|
|
||||||
|
<ion-tab-button tab="reported">
|
||||||
|
<ion-icon name="flag"></ion-icon>
|
||||||
|
<ion-label>{{'contracts.header_4' | translate}}</ion-label>
|
||||||
|
</ion-tab-button>
|
||||||
|
|
||||||
</ion-tab-bar>
|
</ion-tab-bar>
|
||||||
</ion-tabs>
|
</ion-tabs>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<ion-buttons slot="start">
|
<ion-buttons slot="start">
|
||||||
<ion-menu-button></ion-menu-button>
|
<ion-menu-button></ion-menu-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
<ion-title>{{'contract.header' | translate}}</ion-title>
|
<ion-title>{{'contracts.header' | translate}}</ion-title>
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
<ion-content class="ion-padding">
|
<ion-content class="ion-padding">
|
||||||
@@ -11,6 +11,24 @@
|
|||||||
<ion-refresher slot="fixed" (ionRefresh)="refresh($event)">
|
<ion-refresher slot="fixed" (ionRefresh)="refresh($event)">
|
||||||
<ion-refresher-content></ion-refresher-content>
|
<ion-refresher-content></ion-refresher-content>
|
||||||
</ion-refresher>
|
</ion-refresher>
|
||||||
|
|
||||||
|
<ng-container *ngIf="loading">
|
||||||
|
<ion-card *ngFor="let _ of [1,2]">
|
||||||
|
<ion-item style="--border-color: #fff">
|
||||||
|
<ion-label>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 55%; height: 18px; margin-bottom: 8px"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 85%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 70%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 50%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 40%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 35%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 65%; height: 16px; margin-top: 6px"></ion-skeleton-text>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</ion-card>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="!loading">
|
||||||
<ng-container *ngFor="let fcontract of fcontracts; let i = index">
|
<ng-container *ngFor="let fcontract of fcontracts; let i = index">
|
||||||
<ion-card>
|
<ion-card>
|
||||||
<ion-item style="--border-color: #fff">
|
<ion-item style="--border-color: #fff">
|
||||||
@@ -35,4 +53,5 @@
|
|||||||
</ion-row>
|
</ion-row>
|
||||||
</ion-card>
|
</ion-card>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, ChangeDetectorRef } from '@angular/core';
|
||||||
import { ReviewPage } from '../review/review.page';
|
import { ReviewPage } from '../review/review.page';
|
||||||
import { ModalController, MenuController, NavController } from '@ionic/angular';
|
import { ModalController, MenuController, NavController } from '@ionic/angular';
|
||||||
import { EventService } from '../../../services/event.service';
|
import { EventService } from '../../../services/event.service';
|
||||||
@@ -17,11 +17,12 @@ import { AlertController } from '@ionic/angular';
|
|||||||
styleUrls: ['./finished.page.scss'],
|
styleUrls: ['./finished.page.scss'],
|
||||||
standalone: false
|
standalone: false
|
||||||
})
|
})
|
||||||
export class FinishedPage implements OnInit {
|
export class FinishedPage {
|
||||||
|
|
||||||
fcontracts: any[] = [];
|
fcontracts: any[] = [];
|
||||||
fcontracts_dates: any[] = [];
|
fcontracts_dates: any[] = [];
|
||||||
lang: boolean = false;
|
lang: boolean = false;
|
||||||
|
loading = true;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private modalController: ModalController,
|
private modalController: ModalController,
|
||||||
@@ -37,32 +38,29 @@ export class FinishedPage implements OnInit {
|
|||||||
private translateService: TranslateService,
|
private translateService: TranslateService,
|
||||||
private languageService: LanguageService,
|
private languageService: LanguageService,
|
||||||
private env: EnvService,
|
private env: EnvService,
|
||||||
|
private cdr: ChangeDetectorRef,
|
||||||
) {
|
) {
|
||||||
this.events.subscribe('refreshccontracts', (data) => {
|
this.events.subscribe('refreshccontracts', (data) => {
|
||||||
this.getfcontracts();
|
this.getfcontracts();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ionViewWillEnter() {
|
||||||
|
this.lang = this.languageService.getDefaultLanguage() === 'es';
|
||||||
|
this.loading = true;
|
||||||
this.getfcontracts();
|
this.getfcontracts();
|
||||||
if (this.languageService.getDefaultLanguage() == 'es') {
|
|
||||||
this.lang = true;
|
|
||||||
} else {
|
|
||||||
this.lang = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
refresh(event: any) {
|
refresh(event: any) {
|
||||||
this.ichambaService.getFinishedcontracts().subscribe(
|
this.ichambaService.getFinishedcontracts().subscribe(
|
||||||
data => {
|
data => {
|
||||||
this.fcontracts = data;
|
this.fcontracts = data;
|
||||||
|
this.fcontracts_dates = [];
|
||||||
for (var i of this.fcontracts) {
|
for (var i of this.fcontracts) {
|
||||||
if (this.languageService.getDefaultLanguage() == 'es') {
|
const locale = this.lang ? 'es-US' : 'en-US';
|
||||||
this.fcontracts_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace("," ,"")).toLocaleDateString('es-US', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute:'numeric', timeZoneName: 'long'}));
|
this.fcontracts_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace(',', '')).toLocaleDateString(locale, { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric', timeZoneName: 'long' }));
|
||||||
} else {
|
|
||||||
this.fcontracts_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace("," ,"")).toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute:'numeric', timeZoneName: 'long'}));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
this.cdr.detectChanges();
|
||||||
event.target.complete();
|
event.target.complete();
|
||||||
}, error => {
|
}, error => {
|
||||||
this.alertService.presentToast(this.translateService.instant('alerts.error') + error['status']);
|
this.alertService.presentToast(this.translateService.instant('alerts.error') + error['status']);
|
||||||
@@ -74,14 +72,15 @@ export class FinishedPage implements OnInit {
|
|||||||
this.ichambaService.getFinishedcontracts().subscribe(
|
this.ichambaService.getFinishedcontracts().subscribe(
|
||||||
data => {
|
data => {
|
||||||
this.fcontracts = data;
|
this.fcontracts = data;
|
||||||
|
this.fcontracts_dates = [];
|
||||||
for (var i of this.fcontracts) {
|
for (var i of this.fcontracts) {
|
||||||
if (this.languageService.getDefaultLanguage() == 'es') {
|
const locale = this.lang ? 'es-US' : 'en-US';
|
||||||
this.fcontracts_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace("," ,"")).toLocaleDateString('es-US', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute:'numeric', timeZoneName: 'long'}));
|
this.fcontracts_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace(',', '')).toLocaleDateString(locale, { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric', timeZoneName: 'long' }));
|
||||||
} else {
|
|
||||||
this.fcontracts_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace("," ,"")).toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute:'numeric', timeZoneName: 'long'}));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
this.loading = false;
|
||||||
|
this.cdr.detectChanges();
|
||||||
}, error => {
|
}, error => {
|
||||||
|
this.loading = false;
|
||||||
this.alertService.presentToast(this.translateService.instant('alerts.error') + error['status']);
|
this.alertService.presentToast(this.translateService.instant('alerts.error') + error['status']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,24 @@
|
|||||||
<ion-refresher slot="fixed" (ionRefresh)="refresh($event)">
|
<ion-refresher slot="fixed" (ionRefresh)="refresh($event)">
|
||||||
<ion-refresher-content></ion-refresher-content>
|
<ion-refresher-content></ion-refresher-content>
|
||||||
</ion-refresher>
|
</ion-refresher>
|
||||||
|
|
||||||
|
<ng-container *ngIf="loading">
|
||||||
|
<ion-card *ngFor="let _ of [1,2]">
|
||||||
|
<ion-item style="--border-color: #fff">
|
||||||
|
<ion-label>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 55%; height: 18px; margin-bottom: 8px"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 85%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 70%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 50%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 40%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 35%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 65%; height: 16px; margin-top: 6px"></ion-skeleton-text>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</ion-card>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="!loading">
|
||||||
<ion-card *ngFor="let pcontract of pcontracts; let i = index">
|
<ion-card *ngFor="let pcontract of pcontracts; let i = index">
|
||||||
<ion-item>
|
<ion-item>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
@@ -22,4 +40,5 @@
|
|||||||
<ion-button style="height: 3em; padding-left: 0.5em;" color="secondary" (click)="viewsuppliers(pcontract.id)">{{'contracts.viewsuppliers_1.1' | translate}}<br>{{'contracts.viewsuppliers_1.2' | translate}}</ion-button>
|
<ion-button style="height: 3em; padding-left: 0.5em;" color="secondary" (click)="viewsuppliers(pcontract.id)">{{'contracts.viewsuppliers_1.1' | translate}}<br>{{'contracts.viewsuppliers_1.2' | translate}}</ion-button>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</ion-card>
|
</ion-card>
|
||||||
|
</ng-container>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, ChangeDetectorRef } from '@angular/core';
|
||||||
import { ModalController, MenuController, NavController } from '@ionic/angular';
|
import { ModalController, MenuController, NavController } from '@ionic/angular';
|
||||||
import { EventService } from '../../../services/event.service';
|
import { EventService } from '../../../services/event.service';
|
||||||
import { EnvService } from 'src/app/services/env.service';
|
import { EnvService } from 'src/app/services/env.service';
|
||||||
@@ -14,11 +14,12 @@ import { AlertService } from 'src/app/services/alert.service';
|
|||||||
styleUrls: ['./pending.page.scss'],
|
styleUrls: ['./pending.page.scss'],
|
||||||
standalone: false
|
standalone: false
|
||||||
})
|
})
|
||||||
export class PendingPage implements OnInit {
|
export class PendingPage {
|
||||||
|
|
||||||
pcontracts: any[] = [];
|
pcontracts: any[] = [];
|
||||||
pcontracts_dates: any[] = [];
|
pcontracts_dates: any[] = [];
|
||||||
lang: boolean = false;
|
lang: boolean = false;
|
||||||
|
loading = true;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private modalController: ModalController,
|
private modalController: ModalController,
|
||||||
@@ -31,32 +32,29 @@ export class PendingPage implements OnInit {
|
|||||||
private translateService: TranslateService,
|
private translateService: TranslateService,
|
||||||
private languageService: LanguageService,
|
private languageService: LanguageService,
|
||||||
private env: EnvService,
|
private env: EnvService,
|
||||||
|
private cdr: ChangeDetectorRef,
|
||||||
) {
|
) {
|
||||||
this.events.subscribe('refreshpcontracts', (data) => {
|
this.events.subscribe('refreshpcontracts', (data) => {
|
||||||
this.getpcontracts();
|
this.getpcontracts();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ionViewWillEnter() {
|
||||||
|
this.lang = this.languageService.getDefaultLanguage() === 'es';
|
||||||
|
this.loading = true;
|
||||||
this.getpcontracts();
|
this.getpcontracts();
|
||||||
if (this.languageService.getDefaultLanguage() == 'es') {
|
|
||||||
this.lang = true;
|
|
||||||
} else {
|
|
||||||
this.lang = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
refresh (event: any) {
|
refresh(event: any) {
|
||||||
this.ichambaService.getPendingcontracts().subscribe(
|
this.ichambaService.getPendingcontracts().subscribe(
|
||||||
data => {
|
data => {
|
||||||
this.pcontracts = data;
|
this.pcontracts = data;
|
||||||
|
this.pcontracts_dates = [];
|
||||||
for (var i of this.pcontracts) {
|
for (var i of this.pcontracts) {
|
||||||
if (this.languageService.getDefaultLanguage() == 'es') {
|
const locale = this.lang ? 'es-US' : 'en-US';
|
||||||
this.pcontracts_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace("," ,"")).toLocaleDateString('es-US', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute:'numeric', timeZoneName: 'long'}));
|
this.pcontracts_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace(',', '')).toLocaleDateString(locale, { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric', timeZoneName: 'long' }));
|
||||||
} else {
|
|
||||||
this.pcontracts_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace("," ,"")).toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute:'numeric', timeZoneName: 'long'}));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
this.cdr.detectChanges();
|
||||||
event.target.complete();
|
event.target.complete();
|
||||||
}, error => {
|
}, error => {
|
||||||
this.alertService.presentToast(this.translateService.instant('alerts.error') + error['status']);
|
this.alertService.presentToast(this.translateService.instant('alerts.error') + error['status']);
|
||||||
@@ -68,14 +66,15 @@ export class PendingPage implements OnInit {
|
|||||||
this.ichambaService.getPendingcontracts().subscribe(
|
this.ichambaService.getPendingcontracts().subscribe(
|
||||||
data => {
|
data => {
|
||||||
this.pcontracts = data;
|
this.pcontracts = data;
|
||||||
|
this.pcontracts_dates = [];
|
||||||
for (var i of this.pcontracts) {
|
for (var i of this.pcontracts) {
|
||||||
if (this.languageService.getDefaultLanguage() == 'es') {
|
const locale = this.lang ? 'es-US' : 'en-US';
|
||||||
this.pcontracts_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace("," ,"")).toLocaleDateString('es-US', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute:'numeric', timeZoneName: 'long'}));
|
this.pcontracts_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace(',', '')).toLocaleDateString(locale, { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric', timeZoneName: 'long' }));
|
||||||
} else {
|
|
||||||
this.pcontracts_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace("," ,"")).toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute:'numeric', timeZoneName: 'long'}));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
this.loading = false;
|
||||||
|
this.cdr.detectChanges();
|
||||||
}, error => {
|
}, error => {
|
||||||
|
this.loading = false;
|
||||||
this.alertService.presentToast(this.translateService.instant('alerts.error') + error['status']);
|
this.alertService.presentToast(this.translateService.instant('alerts.error') + error['status']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,19 +11,38 @@
|
|||||||
<ion-refresher slot="fixed" (ionRefresh)="refresh($event)">
|
<ion-refresher slot="fixed" (ionRefresh)="refresh($event)">
|
||||||
<ion-refresher-content></ion-refresher-content>
|
<ion-refresher-content></ion-refresher-content>
|
||||||
</ion-refresher>
|
</ion-refresher>
|
||||||
<ng-container *ngFor="let postulation of postulations; let i = index">
|
|
||||||
<ion-card>
|
<ng-container *ngIf="loading">
|
||||||
<ion-item>
|
<ion-card *ngFor="let _ of [1,2]">
|
||||||
|
<ion-item style="--border-color: #fff">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2 class="ion-text-capitalize">{{ postulation.category }}</h2>
|
<ion-skeleton-text [animated]="true" style="width: 55%; height: 18px; margin-bottom: 8px"></ion-skeleton-text>
|
||||||
<ion-text color="primary"><p class="ion-text-wrap" (click)="openMaps(postulation.lat, postulation.lng)"><b><u>{{postulation.address}}</u></b></p></ion-text>
|
<ion-skeleton-text [animated]="true" style="width: 85%"></ion-skeleton-text>
|
||||||
<p class="ion-text-wrap">Télefono: <a href="tel:{{ postulation.phone }}">{{ postulation.phone }}</a></p>
|
<ion-skeleton-text [animated]="true" style="width: 40%"></ion-skeleton-text>
|
||||||
<p class="ion-text-wrap">Referencias: {{postulation.references}}</p>
|
<ion-skeleton-text [animated]="true" style="width: 70%"></ion-skeleton-text>
|
||||||
<p class="ion-text-wrap ion-text-capitalize">{{postulations_dates[i]}}</p>
|
<ion-skeleton-text [animated]="true" style="width: 75%"></ion-skeleton-text>
|
||||||
<p class="ion-text-wrap">Monto: {{postulation.amount}}</p>
|
<ion-skeleton-text [animated]="true" style="width: 35%"></ion-skeleton-text>
|
||||||
<p class="ion-text-wrap">Detalles: {{postulation.details}}</p>
|
<ion-skeleton-text [animated]="true" style="width: 80%"></ion-skeleton-text>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</ion-card>
|
</ion-card>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="!loading">
|
||||||
|
<ng-container *ngFor="let postulation of postulations; let i = index">
|
||||||
|
<ion-card>
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>
|
||||||
|
<h2 class="ion-text-capitalize">{{ postulation.category }}</h2>
|
||||||
|
<ion-text color="primary"><p class="ion-text-wrap" (click)="openMaps(postulation.lat, postulation.lng)"><b><u>{{postulation.address}}</u></b></p></ion-text>
|
||||||
|
<p class="ion-text-wrap">Télefono: <a href="tel:{{ postulation.phone }}">{{ postulation.phone }}</a></p>
|
||||||
|
<p class="ion-text-wrap">Referencias: {{postulation.references}}</p>
|
||||||
|
<p class="ion-text-wrap ion-text-capitalize">{{postulations_dates[i]}}</p>
|
||||||
|
<p class="ion-text-wrap">Monto: {{postulation.amount}}</p>
|
||||||
|
<p class="ion-text-wrap">Detalles: {{postulation.details}}</p>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</ion-card>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, ChangeDetectorRef } from '@angular/core';
|
||||||
import { MenuController, NavController } from '@ionic/angular';
|
import { MenuController, NavController } from '@ionic/angular';
|
||||||
import { EventService } from '../../../services/event.service';
|
import { EventService } from '../../../services/event.service';
|
||||||
import { EnvService } from 'src/app/services/env.service';
|
import { EnvService } from 'src/app/services/env.service';
|
||||||
@@ -13,10 +13,11 @@ import { Browser } from '@capacitor/browser';
|
|||||||
styleUrls: ['./already.page.scss'],
|
styleUrls: ['./already.page.scss'],
|
||||||
standalone: false
|
standalone: false
|
||||||
})
|
})
|
||||||
export class AlreadyPage implements OnInit {
|
export class AlreadyPage {
|
||||||
|
|
||||||
postulations: any[] = [];
|
postulations: any[] = [];
|
||||||
postulations_dates: any[] = [];
|
postulations_dates: any[] = [];
|
||||||
|
loading = true;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private menu: MenuController,
|
private menu: MenuController,
|
||||||
@@ -26,13 +27,15 @@ export class AlreadyPage implements OnInit {
|
|||||||
private alertService: AlertService,
|
private alertService: AlertService,
|
||||||
private ichambaService: IchambaService,
|
private ichambaService: IchambaService,
|
||||||
private env: EnvService,
|
private env: EnvService,
|
||||||
|
private cdr: ChangeDetectorRef,
|
||||||
) {
|
) {
|
||||||
this.events.subscribe('refreshpostulations', (data) => {
|
this.events.subscribe('refreshpostulations', (data) => {
|
||||||
this.getpostulations();
|
this.getpostulations();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ionViewWillEnter() {
|
||||||
|
this.loading = true;
|
||||||
this.getpostulations();
|
this.getpostulations();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,9 +43,11 @@ export class AlreadyPage implements OnInit {
|
|||||||
this.ichambaService.getContractedPostulation().subscribe(
|
this.ichambaService.getContractedPostulation().subscribe(
|
||||||
data => {
|
data => {
|
||||||
this.postulations = data;
|
this.postulations = data;
|
||||||
|
this.postulations_dates = [];
|
||||||
for (var i of this.postulations) {
|
for (var i of this.postulations) {
|
||||||
this.postulations_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace("," ,"")).toLocaleDateString('es-US', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute:'numeric', timeZoneName: 'long'}));
|
this.postulations_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace(',', '')).toLocaleDateString('es-US', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric', timeZoneName: 'long' }));
|
||||||
}
|
}
|
||||||
|
this.cdr.detectChanges();
|
||||||
event.target.complete();
|
event.target.complete();
|
||||||
}, error => {
|
}, error => {
|
||||||
this.alertService.presentToast("Por favor contacte a soporte técnico, Estatus:" + error['status']);
|
this.alertService.presentToast("Por favor contacte a soporte técnico, Estatus:" + error['status']);
|
||||||
@@ -54,10 +59,14 @@ export class AlreadyPage implements OnInit {
|
|||||||
this.ichambaService.getContractedPostulation().subscribe(
|
this.ichambaService.getContractedPostulation().subscribe(
|
||||||
data => {
|
data => {
|
||||||
this.postulations = data;
|
this.postulations = data;
|
||||||
|
this.postulations_dates = [];
|
||||||
for (var i of this.postulations) {
|
for (var i of this.postulations) {
|
||||||
this.postulations_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace("," ,"")).toLocaleDateString('es-US', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute:'numeric', timeZoneName: 'long'}));
|
this.postulations_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace(',', '')).toLocaleDateString('es-US', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric', timeZoneName: 'long' }));
|
||||||
}
|
}
|
||||||
|
this.loading = false;
|
||||||
|
this.cdr.detectChanges();
|
||||||
}, error => {
|
}, error => {
|
||||||
|
this.loading = false;
|
||||||
this.alertService.presentToast("Por favor contacte a soporte técnico, Estatus:" + error['status']);
|
this.alertService.presentToast("Por favor contacte a soporte técnico, Estatus:" + error['status']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,19 +11,38 @@
|
|||||||
<ion-refresher slot="fixed" (ionRefresh)="refresh($event)">
|
<ion-refresher slot="fixed" (ionRefresh)="refresh($event)">
|
||||||
<ion-refresher-content></ion-refresher-content>
|
<ion-refresher-content></ion-refresher-content>
|
||||||
</ion-refresher>
|
</ion-refresher>
|
||||||
<ng-container *ngFor="let postulation of postulations; let i = index">
|
|
||||||
<ion-card *ngIf="!postulation.already_post">
|
<ng-container *ngIf="loading">
|
||||||
<ion-item>
|
<ion-card *ngFor="let _ of [1,2]">
|
||||||
|
<ion-item style="--border-color: #fff">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2 class="ion-text-capitalize">{{ postulation.category }}</h2>
|
<ion-skeleton-text [animated]="true" style="width: 55%; height: 18px; margin-bottom: 8px"></ion-skeleton-text>
|
||||||
<ion-text color="primary"><p class="ion-text-wrap" (click)="openMaps(postulation.lat, postulation.lng)"><b><u>{{postulation.address}}</u></b></p></ion-text>
|
<ion-skeleton-text [animated]="true" style="width: 85%"></ion-skeleton-text>
|
||||||
<p class="ion-text-wrap">Referencias: {{postulation.references}}</p>
|
<ion-skeleton-text [animated]="true" style="width: 70%"></ion-skeleton-text>
|
||||||
<p class="ion-text-wrap ion-text-capitalize">{{postulations_dates[i]}}</p>
|
<ion-skeleton-text [animated]="true" style="width: 75%"></ion-skeleton-text>
|
||||||
<p class="ion-text-wrap">Detalles: {{postulation.details}}</p>
|
<ion-skeleton-text [animated]="true" style="width: 80%"></ion-skeleton-text>
|
||||||
<p class="ion-text-wrap">Tiempo restante: {{postulation.time_limit}} minutos</p>
|
<ion-skeleton-text [animated]="true" style="width: 45%"></ion-skeleton-text>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
<ion-button style="height: 3em; padding-left: 0.5em;" color="secondary" (click)="addpostulation(postulation.id)">Postularse</ion-button>
|
<ion-skeleton-text slot="end" [animated]="true" style="width: 72px; height: 36px; border-radius: 4px"></ion-skeleton-text>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</ion-card>
|
</ion-card>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="!loading">
|
||||||
|
<ng-container *ngFor="let postulation of postulations; let i = index">
|
||||||
|
<ion-card *ngIf="!postulation.already_post">
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>
|
||||||
|
<h2 class="ion-text-capitalize">{{ postulation.category }}</h2>
|
||||||
|
<ion-text color="primary"><p class="ion-text-wrap" (click)="openMaps(postulation.lat, postulation.lng)"><b><u>{{postulation.address}}</u></b></p></ion-text>
|
||||||
|
<p class="ion-text-wrap">Referencias: {{postulation.references}}</p>
|
||||||
|
<p class="ion-text-wrap ion-text-capitalize">{{postulations_dates[i]}}</p>
|
||||||
|
<p class="ion-text-wrap">Detalles: {{postulation.details}}</p>
|
||||||
|
<p class="ion-text-wrap">Tiempo restante: {{postulation.time_limit}} minutos</p>
|
||||||
|
</ion-label>
|
||||||
|
<ion-button slot="end" style="height: 3em;" color="secondary" (click)="addpostulation(postulation.id)">Postularse</ion-button>
|
||||||
|
</ion-item>
|
||||||
|
</ion-card>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, ChangeDetectorRef } from '@angular/core';
|
||||||
import { MenuController, NavController } from '@ionic/angular';
|
import { MenuController, NavController } from '@ionic/angular';
|
||||||
import { EventService } from '../../../services/event.service';
|
import { EventService } from '../../../services/event.service';
|
||||||
import { EnvService } from 'src/app/services/env.service';
|
import { EnvService } from 'src/app/services/env.service';
|
||||||
@@ -13,10 +13,11 @@ import { Browser } from '@capacitor/browser';
|
|||||||
styleUrls: ['./current.page.scss'],
|
styleUrls: ['./current.page.scss'],
|
||||||
standalone: false
|
standalone: false
|
||||||
})
|
})
|
||||||
export class CurrentPage implements OnInit {
|
export class CurrentPage {
|
||||||
|
|
||||||
postulations: any[] = [];
|
postulations: any[] = [];
|
||||||
postulations_dates: any[] = [];
|
postulations_dates: any[] = [];
|
||||||
|
loading = true;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private menu: MenuController,
|
private menu: MenuController,
|
||||||
@@ -26,13 +27,15 @@ export class CurrentPage implements OnInit {
|
|||||||
private alertService: AlertService,
|
private alertService: AlertService,
|
||||||
private ichambaService: IchambaService,
|
private ichambaService: IchambaService,
|
||||||
private env: EnvService,
|
private env: EnvService,
|
||||||
|
private cdr: ChangeDetectorRef,
|
||||||
) {
|
) {
|
||||||
this.events.subscribe('refreshpostulations', (data) => {
|
this.events.subscribe('refreshpostulations', (data) => {
|
||||||
this.getpostulations();
|
this.getpostulations();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ionViewWillEnter() {
|
||||||
|
this.loading = true;
|
||||||
this.getpostulations();
|
this.getpostulations();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,9 +43,11 @@ export class CurrentPage implements OnInit {
|
|||||||
this.ichambaService.getPostulation().subscribe(
|
this.ichambaService.getPostulation().subscribe(
|
||||||
data => {
|
data => {
|
||||||
this.postulations = data;
|
this.postulations = data;
|
||||||
|
this.postulations_dates = [];
|
||||||
for (var i of this.postulations) {
|
for (var i of this.postulations) {
|
||||||
this.postulations_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace("," ,"")).toLocaleDateString('es-US', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute:'numeric', timeZoneName: 'long'}));
|
this.postulations_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace(',', '')).toLocaleDateString('es-US', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric', timeZoneName: 'long' }));
|
||||||
}
|
}
|
||||||
|
this.cdr.detectChanges();
|
||||||
event.target.complete();
|
event.target.complete();
|
||||||
}, error => {
|
}, error => {
|
||||||
this.alertService.presentToast("Por favor contacte a soporte técnico, Estatus:" + error['status']);
|
this.alertService.presentToast("Por favor contacte a soporte técnico, Estatus:" + error['status']);
|
||||||
@@ -54,10 +59,14 @@ export class CurrentPage implements OnInit {
|
|||||||
this.ichambaService.getPostulation().subscribe(
|
this.ichambaService.getPostulation().subscribe(
|
||||||
data => {
|
data => {
|
||||||
this.postulations = data;
|
this.postulations = data;
|
||||||
|
this.postulations_dates = [];
|
||||||
for (var i of this.postulations) {
|
for (var i of this.postulations) {
|
||||||
this.postulations_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace("," ,"")).toLocaleDateString('es-US', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute:'numeric', timeZoneName: 'long'}));
|
this.postulations_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace(',', '')).toLocaleDateString('es-US', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric', timeZoneName: 'long' }));
|
||||||
}
|
}
|
||||||
|
this.loading = false;
|
||||||
|
this.cdr.detectChanges();
|
||||||
}, error => {
|
}, error => {
|
||||||
|
this.loading = false;
|
||||||
this.alertService.presentToast("Por favor contacte a soporte técnico, Estatus:" + error['status']);
|
this.alertService.presentToast("Por favor contacte a soporte técnico, Estatus:" + error['status']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,24 @@
|
|||||||
<ion-refresher slot="fixed" (ionRefresh)="refresh($event)">
|
<ion-refresher slot="fixed" (ionRefresh)="refresh($event)">
|
||||||
<ion-refresher-content></ion-refresher-content>
|
<ion-refresher-content></ion-refresher-content>
|
||||||
</ion-refresher>
|
</ion-refresher>
|
||||||
|
|
||||||
|
<ng-container *ngIf="loading">
|
||||||
|
<ion-card *ngFor="let _ of [1,2]">
|
||||||
|
<ion-item style="--border-color: #fff">
|
||||||
|
<ion-label>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 55%; height: 18px; margin-bottom: 8px"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 85%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 40%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 70%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 75%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 35%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 80%"></ion-skeleton-text>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</ion-card>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="!loading">
|
||||||
<ng-container *ngFor="let postulation of postulations; let i = index">
|
<ng-container *ngFor="let postulation of postulations; let i = index">
|
||||||
<ion-card>
|
<ion-card>
|
||||||
<ion-item>
|
<ion-item>
|
||||||
@@ -24,4 +42,5 @@
|
|||||||
</ion-item>
|
</ion-item>
|
||||||
</ion-card>
|
</ion-card>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, ChangeDetectorRef } from '@angular/core';
|
||||||
import { ModalController, MenuController, NavController } from '@ionic/angular';
|
import { ModalController, MenuController, NavController } from '@ionic/angular';
|
||||||
import { EventService } from '../../../services/event.service';
|
import { EventService } from '../../../services/event.service';
|
||||||
import { EnvService } from 'src/app/services/env.service';
|
import { EnvService } from 'src/app/services/env.service';
|
||||||
@@ -12,10 +12,11 @@ import { AlertService } from 'src/app/services/alert.service';
|
|||||||
styleUrls: ['./ended.page.scss'],
|
styleUrls: ['./ended.page.scss'],
|
||||||
standalone: false
|
standalone: false
|
||||||
})
|
})
|
||||||
export class EndedPage implements OnInit {
|
export class EndedPage {
|
||||||
|
|
||||||
postulations: any[] = [];
|
postulations: any[] = [];
|
||||||
postulations_dates: any[] = [];
|
postulations_dates: any[] = [];
|
||||||
|
loading = true;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private modalController: ModalController,
|
private modalController: ModalController,
|
||||||
@@ -26,13 +27,15 @@ export class EndedPage implements OnInit {
|
|||||||
private alertService: AlertService,
|
private alertService: AlertService,
|
||||||
private ichambaService: IchambaService,
|
private ichambaService: IchambaService,
|
||||||
private env: EnvService,
|
private env: EnvService,
|
||||||
|
private cdr: ChangeDetectorRef,
|
||||||
) {
|
) {
|
||||||
this.events.subscribe('refreshpostulations', (data) => {
|
this.events.subscribe('refreshpostulations', (data) => {
|
||||||
this.getfinishedpostulations();
|
this.getfinishedpostulations();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ionViewWillEnter() {
|
||||||
|
this.loading = true;
|
||||||
this.getfinishedpostulations();
|
this.getfinishedpostulations();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,9 +43,11 @@ export class EndedPage implements OnInit {
|
|||||||
this.ichambaService.getFinishedPostulation().subscribe(
|
this.ichambaService.getFinishedPostulation().subscribe(
|
||||||
data => {
|
data => {
|
||||||
this.postulations = data;
|
this.postulations = data;
|
||||||
|
this.postulations_dates = [];
|
||||||
for (var i of this.postulations) {
|
for (var i of this.postulations) {
|
||||||
this.postulations_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace("," ,"")).toLocaleDateString('es-US', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute:'numeric', timeZoneName: 'long'}));
|
this.postulations_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace(',', '')).toLocaleDateString('es-US', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric', timeZoneName: 'long' }));
|
||||||
}
|
}
|
||||||
|
this.cdr.detectChanges();
|
||||||
event.target.complete();
|
event.target.complete();
|
||||||
}, error => {
|
}, error => {
|
||||||
this.alertService.presentToast("Por favor contacte a soporte técnico, Estatus:" + error['status']);
|
this.alertService.presentToast("Por favor contacte a soporte técnico, Estatus:" + error['status']);
|
||||||
@@ -54,10 +59,14 @@ export class EndedPage implements OnInit {
|
|||||||
this.ichambaService.getFinishedPostulation().subscribe(
|
this.ichambaService.getFinishedPostulation().subscribe(
|
||||||
data => {
|
data => {
|
||||||
this.postulations = data;
|
this.postulations = data;
|
||||||
|
this.postulations_dates = [];
|
||||||
for (var i of this.postulations) {
|
for (var i of this.postulations) {
|
||||||
this.postulations_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace("," ,"")).toLocaleDateString('es-US', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute:'numeric', timeZoneName: 'long'}));
|
this.postulations_dates.push(new Date((new Date(i.date).toLocaleString('en-US') + ' UTC').replace(',', '')).toLocaleDateString('es-US', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric', timeZoneName: 'long' }));
|
||||||
}
|
}
|
||||||
|
this.loading = false;
|
||||||
|
this.cdr.detectChanges();
|
||||||
}, error => {
|
}, error => {
|
||||||
|
this.loading = false;
|
||||||
this.alertService.presentToast("Por favor contacte a soporte técnico, Estatus:" + error['status']);
|
this.alertService.presentToast("Por favor contacte a soporte técnico, Estatus:" + error['status']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ const routes: Routes = [
|
|||||||
{
|
{
|
||||||
path: 'ended',
|
path: 'ended',
|
||||||
loadChildren: () => import('./ended/ended.module').then(m => m.EndedPageModule)
|
loadChildren: () => import('./ended/ended.module').then(m => m.EndedPageModule)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'reported',
|
||||||
|
loadChildren: () => import('./reported/reported.module').then(m => m.PostulationReportedPageModule)
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,5 +24,10 @@
|
|||||||
<ion-label>Finalizadas</ion-label>
|
<ion-label>Finalizadas</ion-label>
|
||||||
</ion-tab-button>
|
</ion-tab-button>
|
||||||
|
|
||||||
|
<ion-tab-button tab="reported">
|
||||||
|
<ion-icon name="flag"></ion-icon>
|
||||||
|
<ion-label>Reportadas</ion-label>
|
||||||
|
</ion-tab-button>
|
||||||
|
|
||||||
</ion-tab-bar>
|
</ion-tab-bar>
|
||||||
</ion-tabs>
|
</ion-tabs>
|
||||||
|
|||||||
26
src/app/pages/postulations/reported/reported.module.ts
Normal file
26
src/app/pages/postulations/reported/reported.module.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
import { IonicModule } from '@ionic/angular';
|
||||||
|
import { PostulationReportedPage } from './reported.page';
|
||||||
|
import { ReportDiscussionPageModule } from '../../report-discussion/report-discussion.module';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: PostulationReportedPage
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
FormsModule,
|
||||||
|
IonicModule,
|
||||||
|
RouterModule.forChild(routes),
|
||||||
|
ReportDiscussionPageModule
|
||||||
|
],
|
||||||
|
declarations: [PostulationReportedPage]
|
||||||
|
})
|
||||||
|
export class PostulationReportedPageModule {}
|
||||||
53
src/app/pages/postulations/reported/reported.page.html
Normal file
53
src/app/pages/postulations/reported/reported.page.html
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<ion-header>
|
||||||
|
<ion-toolbar color="primary">
|
||||||
|
<ion-buttons slot="start">
|
||||||
|
<ion-menu-button></ion-menu-button>
|
||||||
|
</ion-buttons>
|
||||||
|
<ion-title>Postulaciones</ion-title>
|
||||||
|
</ion-toolbar>
|
||||||
|
</ion-header>
|
||||||
|
|
||||||
|
<ion-content class="ion-padding">
|
||||||
|
<h2 class="ion-text-capitalize" style="padding-bottom: 0.5em">Reportadas</h2>
|
||||||
|
|
||||||
|
<ion-refresher slot="fixed" (ionRefresh)="refresh($event)">
|
||||||
|
<ion-refresher-content></ion-refresher-content>
|
||||||
|
</ion-refresher>
|
||||||
|
|
||||||
|
<ng-container *ngIf="loading">
|
||||||
|
<ion-card *ngFor="let _ of [1,2]">
|
||||||
|
<ion-item style="--border-color: #fff">
|
||||||
|
<ion-label>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 55%; height: 18px; margin-bottom: 8px"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 50%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 85%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 70%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 35%"></ion-skeleton-text>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</ion-card>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="!loading">
|
||||||
|
<p *ngIf="reports.length === 0" class="ion-text-center ion-padding-top">
|
||||||
|
No tienes postulaciones reportadas
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ng-container *ngFor="let report of reports; let i = index">
|
||||||
|
<ion-card>
|
||||||
|
<ion-item style="--border-color: #fff">
|
||||||
|
<ion-label>
|
||||||
|
<h2 class="ion-text-capitalize">{{ report.category }}</h2>
|
||||||
|
<p class="ion-text-wrap ion-text-capitalize">Cliente: {{ report.client }}</p>
|
||||||
|
<p class="ion-text-wrap">{{ report.address }}</p>
|
||||||
|
<p class="ion-text-wrap ion-text-capitalize">{{ reports_dates[i] }}</p>
|
||||||
|
<p>Monto: ${{ report.amount }}</p>
|
||||||
|
</ion-label>
|
||||||
|
<ion-button color="secondary" fill="outline" slot="end" (click)="viewDiscussion(report.id)">
|
||||||
|
<ion-icon slot="icon-only" name="chatbubbles-outline"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
|
</ion-item>
|
||||||
|
</ion-card>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
</ion-content>
|
||||||
77
src/app/pages/postulations/reported/reported.page.ts
Normal file
77
src/app/pages/postulations/reported/reported.page.ts
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
import { Component, ChangeDetectorRef } from '@angular/core';
|
||||||
|
import { ModalController } from '@ionic/angular';
|
||||||
|
import { IchambaService } from 'src/app/services/ichamba.service';
|
||||||
|
import { AlertService } from 'src/app/services/alert.service';
|
||||||
|
import { ReportDiscussionPage } from '../../report-discussion/report-discussion.page';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-postulation-reported',
|
||||||
|
templateUrl: './reported.page.html',
|
||||||
|
styleUrls: ['./reported.page.scss'],
|
||||||
|
standalone: false
|
||||||
|
})
|
||||||
|
export class PostulationReportedPage {
|
||||||
|
|
||||||
|
reports: any[] = [];
|
||||||
|
reports_dates: string[] = [];
|
||||||
|
loading = true;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private alertService: AlertService,
|
||||||
|
private ichambaService: IchambaService,
|
||||||
|
private cdr: ChangeDetectorRef,
|
||||||
|
private modalCtrl: ModalController,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
ionViewWillEnter() {
|
||||||
|
this.loading = true;
|
||||||
|
this.loadReports();
|
||||||
|
}
|
||||||
|
|
||||||
|
refresh(event: any) {
|
||||||
|
this.ichambaService.getPostulationReports().subscribe({
|
||||||
|
next: data => {
|
||||||
|
this.reports = data;
|
||||||
|
this.buildDates();
|
||||||
|
this.cdr.detectChanges();
|
||||||
|
event.target.complete();
|
||||||
|
},
|
||||||
|
error: error => {
|
||||||
|
this.alertService.presentToast('Por favor contacte a soporte técnico, Estatus:' + error['status']);
|
||||||
|
event.target.complete();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
loadReports() {
|
||||||
|
this.ichambaService.getPostulationReports().subscribe({
|
||||||
|
next: data => {
|
||||||
|
this.reports = data;
|
||||||
|
this.buildDates();
|
||||||
|
this.loading = false;
|
||||||
|
this.cdr.detectChanges();
|
||||||
|
},
|
||||||
|
error: error => {
|
||||||
|
this.loading = false;
|
||||||
|
this.alertService.presentToast('Por favor contacte a soporte técnico, Estatus:' + error['status']);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async viewDiscussion(reportId: any) {
|
||||||
|
const modal = await this.modalCtrl.create({
|
||||||
|
component: ReportDiscussionPage,
|
||||||
|
componentProps: { reportId },
|
||||||
|
});
|
||||||
|
await modal.present();
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildDates() {
|
||||||
|
this.reports_dates = this.reports.map(r =>
|
||||||
|
new Date((new Date(r.appointment).toLocaleString('en-US') + ' UTC').replace(',', '')).toLocaleDateString('es-US', {
|
||||||
|
weekday: 'long', year: 'numeric', month: 'short', day: 'numeric',
|
||||||
|
hour: 'numeric', minute: 'numeric', timeZoneName: 'long'
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/app/pages/report-discussion/report-discussion.module.ts
Normal file
16
src/app/pages/report-discussion/report-discussion.module.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { IonicModule } from '@ionic/angular';
|
||||||
|
import { ReportDiscussionPage } from './report-discussion.page';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
FormsModule,
|
||||||
|
IonicModule,
|
||||||
|
],
|
||||||
|
declarations: [ReportDiscussionPage],
|
||||||
|
exports: [ReportDiscussionPage]
|
||||||
|
})
|
||||||
|
export class ReportDiscussionPageModule {}
|
||||||
94
src/app/pages/report-discussion/report-discussion.page.html
Normal file
94
src/app/pages/report-discussion/report-discussion.page.html
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
<ion-header>
|
||||||
|
<ion-toolbar color="primary">
|
||||||
|
<ion-buttons slot="start">
|
||||||
|
<ion-button (click)="dismiss()">
|
||||||
|
<ion-icon slot="icon-only" name="arrow-back"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
|
</ion-buttons>
|
||||||
|
<ion-title>Discusión del Reporte</ion-title>
|
||||||
|
</ion-toolbar>
|
||||||
|
</ion-header>
|
||||||
|
|
||||||
|
<ion-content #content>
|
||||||
|
<div class="messages-container">
|
||||||
|
|
||||||
|
<ng-container *ngIf="loading">
|
||||||
|
<div class="message-wrapper left">
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 55%; height: 54px; border-radius: 18px;"></ion-skeleton-text>
|
||||||
|
</div>
|
||||||
|
<div class="message-wrapper right">
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 42%; height: 40px; border-radius: 18px;"></ion-skeleton-text>
|
||||||
|
</div>
|
||||||
|
<div class="message-wrapper center">
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 64%; height: 48px; border-radius: 10px;"></ion-skeleton-text>
|
||||||
|
</div>
|
||||||
|
<div class="message-wrapper left">
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 50%; height: 36px; border-radius: 18px;"></ion-skeleton-text>
|
||||||
|
</div>
|
||||||
|
<div class="message-wrapper right">
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 60%; height: 60px; border-radius: 18px;"></ion-skeleton-text>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<div class="empty-state" *ngIf="!loading && messages.length === 0">
|
||||||
|
<ion-icon name="chatbubbles-outline" style="font-size: 48px; margin-bottom: 12px;"></ion-icon>
|
||||||
|
<p>No hay mensajes aún.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ng-container *ngIf="!loading">
|
||||||
|
<ng-container *ngFor="let msg of messages">
|
||||||
|
|
||||||
|
<!-- Moderador — centrado -->
|
||||||
|
<div class="message-wrapper center" *ngIf="msg.sender_type === 'moderator'">
|
||||||
|
<div class="message-bubble moderator">
|
||||||
|
<span class="sender-name">Moderador</span>
|
||||||
|
<p>{{ msg.comment }}</p>
|
||||||
|
<span class="timestamp">{{ msg.created_at | date:'d MMM, HH:mm' }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Mensaje propio — derecha -->
|
||||||
|
<div class="message-wrapper right"
|
||||||
|
*ngIf="msg.sender_type !== 'moderator' && msg.sender_id === currentUserId">
|
||||||
|
<div class="message-bubble mine">
|
||||||
|
<p>{{ msg.comment }}</p>
|
||||||
|
<span class="timestamp">{{ msg.created_at | date:'d MMM, HH:mm' }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Mensaje del otro — izquierda -->
|
||||||
|
<div class="message-wrapper left"
|
||||||
|
*ngIf="msg.sender_type !== 'moderator' && msg.sender_id !== currentUserId">
|
||||||
|
<div class="message-bubble other">
|
||||||
|
<span class="sender-name">{{ msg.sender_name }}</span>
|
||||||
|
<p>{{ msg.comment }}</p>
|
||||||
|
<span class="timestamp">{{ msg.created_at | date:'d MMM, HH:mm' }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</ion-content>
|
||||||
|
|
||||||
|
<ion-footer>
|
||||||
|
<div class="input-bar">
|
||||||
|
<ion-button fill="clear" color="medium" (click)="attachPhoto()">
|
||||||
|
<ion-icon slot="icon-only" name="camera-outline"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
|
<ion-textarea
|
||||||
|
[(ngModel)]="newMessage"
|
||||||
|
placeholder="Escribe un comentario..."
|
||||||
|
rows="1"
|
||||||
|
autoGrow="true"
|
||||||
|
></ion-textarea>
|
||||||
|
<ion-button
|
||||||
|
fill="clear"
|
||||||
|
color="primary"
|
||||||
|
[disabled]="!newMessage.trim() || sending"
|
||||||
|
(click)="sendMessage()">
|
||||||
|
<ion-icon slot="icon-only" name="send"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
|
</div>
|
||||||
|
</ion-footer>
|
||||||
117
src/app/pages/report-discussion/report-discussion.page.scss
Normal file
117
src/app/pages/report-discussion/report-discussion.page.scss
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
.messages-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 16px;
|
||||||
|
min-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-wrapper {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
&.right { justify-content: flex-end; }
|
||||||
|
&.left { justify-content: flex-start; }
|
||||||
|
&.center { justify-content: center; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-bubble {
|
||||||
|
max-width: 72%;
|
||||||
|
padding: 10px 14px;
|
||||||
|
border-radius: 18px;
|
||||||
|
word-break: break-word;
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0 0 4px 0;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sender-name {
|
||||||
|
display: block;
|
||||||
|
font-size: 0.72rem;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
opacity: 0.75;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timestamp {
|
||||||
|
display: block;
|
||||||
|
font-size: 0.68rem;
|
||||||
|
margin-top: 4px;
|
||||||
|
opacity: 0.65;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.mine {
|
||||||
|
background: var(--ion-color-primary);
|
||||||
|
color: #fff;
|
||||||
|
border-bottom-right-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.other {
|
||||||
|
background: var(--ion-color-light);
|
||||||
|
color: var(--ion-color-dark);
|
||||||
|
border-bottom-left-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.moderator {
|
||||||
|
background: var(--ion-color-medium);
|
||||||
|
color: #fff;
|
||||||
|
max-width: 80%;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 10px;
|
||||||
|
font-style: italic;
|
||||||
|
|
||||||
|
.sender-name {
|
||||||
|
text-align: center;
|
||||||
|
font-weight: 700;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timestamp {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-state {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 60px 16px;
|
||||||
|
color: var(--ion-color-medium);
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-bar {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
padding: 6px 6px;
|
||||||
|
gap: 2px;
|
||||||
|
background: var(--ion-background-color, #fff);
|
||||||
|
border-top: 1px solid var(--ion-color-light-shade);
|
||||||
|
|
||||||
|
ion-textarea {
|
||||||
|
flex: 1;
|
||||||
|
--padding-start: 14px;
|
||||||
|
--padding-end: 14px;
|
||||||
|
--padding-top: 8px;
|
||||||
|
--padding-bottom: 8px;
|
||||||
|
background: var(--ion-color-light);
|
||||||
|
border-radius: 20px;
|
||||||
|
margin: 0;
|
||||||
|
max-height: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-button {
|
||||||
|
--padding-start: 6px;
|
||||||
|
--padding-end: 6px;
|
||||||
|
min-height: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
80
src/app/pages/report-discussion/report-discussion.page.ts
Normal file
80
src/app/pages/report-discussion/report-discussion.page.ts
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
import { Component, Input, OnInit, ViewChild, ChangeDetectorRef } from '@angular/core';
|
||||||
|
import { IonContent, ModalController } from '@ionic/angular';
|
||||||
|
import { IchambaService } from 'src/app/services/ichamba.service';
|
||||||
|
import { AuthService } from 'src/app/services/auth.service';
|
||||||
|
import { AlertService } from 'src/app/services/alert.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-report-discussion',
|
||||||
|
templateUrl: './report-discussion.page.html',
|
||||||
|
styleUrls: ['./report-discussion.page.scss'],
|
||||||
|
standalone: false
|
||||||
|
})
|
||||||
|
export class ReportDiscussionPage implements OnInit {
|
||||||
|
|
||||||
|
@Input() reportId: any;
|
||||||
|
|
||||||
|
@ViewChild('content') content!: IonContent;
|
||||||
|
|
||||||
|
messages: any[] = [];
|
||||||
|
newMessage: string = '';
|
||||||
|
currentUserId: any;
|
||||||
|
loading = true;
|
||||||
|
sending = false;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private modalCtrl: ModalController,
|
||||||
|
private ichambaService: IchambaService,
|
||||||
|
private authService: AuthService,
|
||||||
|
private alertService: AlertService,
|
||||||
|
private cdr: ChangeDetectorRef,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.currentUserId = this.authService.userId;
|
||||||
|
this.loadMessages();
|
||||||
|
}
|
||||||
|
|
||||||
|
loadMessages() {
|
||||||
|
this.loading = true;
|
||||||
|
this.ichambaService.getReportDiscussion(this.reportId).subscribe({
|
||||||
|
next: data => {
|
||||||
|
this.messages = data;
|
||||||
|
this.loading = false;
|
||||||
|
this.cdr.detectChanges();
|
||||||
|
setTimeout(() => this.content.scrollToBottom(300), 100);
|
||||||
|
},
|
||||||
|
error: () => {
|
||||||
|
this.loading = false;
|
||||||
|
this.cdr.detectChanges();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
sendMessage() {
|
||||||
|
const text = this.newMessage.trim();
|
||||||
|
if (!text || this.sending) return;
|
||||||
|
this.newMessage = '';
|
||||||
|
this.sending = true;
|
||||||
|
this.ichambaService.sendReportMessage(this.reportId, text).subscribe({
|
||||||
|
next: (msg: any) => {
|
||||||
|
this.messages.push(msg);
|
||||||
|
this.sending = false;
|
||||||
|
this.cdr.detectChanges();
|
||||||
|
setTimeout(() => this.content.scrollToBottom(300), 100);
|
||||||
|
},
|
||||||
|
error: () => {
|
||||||
|
this.sending = false;
|
||||||
|
this.alertService.presentToast('No se pudo enviar el mensaje.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
attachPhoto() {
|
||||||
|
// TODO: implementar captura y envío de foto
|
||||||
|
}
|
||||||
|
|
||||||
|
dismiss() {
|
||||||
|
this.modalCtrl.dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,8 +4,10 @@ import { FormsModule } from '@angular/forms';
|
|||||||
import { Routes, RouterModule } from '@angular/router';
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
|
||||||
import { IonicModule } from '@ionic/angular';
|
import { IonicModule } from '@ionic/angular';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { ReportsPage } from './reports.page';
|
import { ReportsPage } from './reports.page';
|
||||||
|
import { ReportDiscussionPageModule } from '../report-discussion/report-discussion.module';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
@@ -19,7 +21,9 @@ const routes: Routes = [
|
|||||||
CommonModule,
|
CommonModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
IonicModule,
|
IonicModule,
|
||||||
RouterModule.forChild(routes)
|
RouterModule.forChild(routes),
|
||||||
|
TranslateModule,
|
||||||
|
ReportDiscussionPageModule
|
||||||
],
|
],
|
||||||
declarations: [ReportsPage]
|
declarations: [ReportsPage]
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,9 +1,53 @@
|
|||||||
<ion-header>
|
<ion-header>
|
||||||
<ion-toolbar>
|
<ion-toolbar color="primary">
|
||||||
<ion-title>reports</ion-title>
|
<ion-buttons slot="start">
|
||||||
|
<ion-menu-button></ion-menu-button>
|
||||||
|
</ion-buttons>
|
||||||
|
<ion-title>{{'contracts.header' | translate}}</ion-title>
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
|
|
||||||
<ion-content>
|
<ion-content class="ion-padding">
|
||||||
|
<h2 class="ion-text-capitalize" style="padding-bottom: 0.5em">{{'contracts.header_4' | translate}}</h2>
|
||||||
|
|
||||||
|
<ion-refresher slot="fixed" (ionRefresh)="refresh($event)">
|
||||||
|
<ion-refresher-content></ion-refresher-content>
|
||||||
|
</ion-refresher>
|
||||||
|
|
||||||
|
<ng-container *ngIf="loading">
|
||||||
|
<ion-card *ngFor="let _ of [1,2]">
|
||||||
|
<ion-item style="--border-color: #fff">
|
||||||
|
<ion-label>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 55%; height: 18px; margin-bottom: 8px"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 85%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 70%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 50%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 40%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 35%"></ion-skeleton-text>
|
||||||
|
<ion-skeleton-text [animated]="true" style="width: 65%; height: 16px; margin-top: 6px"></ion-skeleton-text>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</ion-card>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="!loading">
|
||||||
|
<ng-container *ngFor="let report of reports; let i = index">
|
||||||
|
<ion-card>
|
||||||
|
<ion-item style="--border-color: #fff">
|
||||||
|
<ion-label>
|
||||||
|
<h2 class="ion-text-capitalize" *ngIf="lang">{{ report.category }}</h2>
|
||||||
|
<h2 class="ion-text-capitalize" *ngIf="!lang">{{ report.en_category }}</h2>
|
||||||
|
<p class="ion-text-wrap ion-text-capitalize">{{'contracts.supplier' | translate}}: {{ report.supplier }}</p>
|
||||||
|
<p class="ion-text-wrap ion-text-capitalize" *ngIf="report.company">{{'reports.company' | translate}}: {{ report.company }}</p>
|
||||||
|
<p class="ion-text-wrap">{{ report.address }}</p>
|
||||||
|
<p class="ion-text-wrap ion-text-capitalize">{{ reports_dates[i] }}</p>
|
||||||
|
<p>{{'contracts.amount' | translate}}: ${{ report.amount }}</p>
|
||||||
|
</ion-label>
|
||||||
|
<ion-button color="secondary" fill="outline" slot="end" size="large" (click)="viewDiscussion(report.id)">
|
||||||
|
<ion-icon slot="icon-only" name="chatbubbles-outline"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
|
</ion-item>
|
||||||
|
</ion-card>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, ChangeDetectorRef } from '@angular/core';
|
||||||
|
import { ModalController } from '@ionic/angular';
|
||||||
|
import { IchambaService } from 'src/app/services/ichamba.service';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { LanguageService } from 'src/app/services/language.service';
|
||||||
|
import { AlertService } from 'src/app/services/alert.service';
|
||||||
|
import { ReportDiscussionPage } from '../report-discussion/report-discussion.page';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-reports',
|
selector: 'app-reports',
|
||||||
@@ -6,11 +12,80 @@ import { Component, OnInit } from '@angular/core';
|
|||||||
styleUrls: ['./reports.page.scss'],
|
styleUrls: ['./reports.page.scss'],
|
||||||
standalone: false
|
standalone: false
|
||||||
})
|
})
|
||||||
export class ReportsPage implements OnInit {
|
export class ReportsPage {
|
||||||
|
|
||||||
constructor() { }
|
reports: any[] = [];
|
||||||
|
reports_dates: string[] = [];
|
||||||
|
lang: boolean = false;
|
||||||
|
loading = true;
|
||||||
|
|
||||||
ngOnInit() {
|
constructor(
|
||||||
|
private alertService: AlertService,
|
||||||
|
private ichambaService: IchambaService,
|
||||||
|
private translateService: TranslateService,
|
||||||
|
private languageService: LanguageService,
|
||||||
|
private cdr: ChangeDetectorRef,
|
||||||
|
private modalCtrl: ModalController,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
ionViewWillEnter() {
|
||||||
|
this.lang = this.languageService.getDefaultLanguage() === 'es';
|
||||||
|
this.loading = true;
|
||||||
|
this.loadReports();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
refresh(event: any) {
|
||||||
|
this.reports = [];
|
||||||
|
this.reports_dates = [];
|
||||||
|
this.ichambaService.getReports().subscribe({
|
||||||
|
next: data => {
|
||||||
|
this.reports = data;
|
||||||
|
this.buildDates();
|
||||||
|
event.target.complete();
|
||||||
|
},
|
||||||
|
error: error => {
|
||||||
|
this.alertService.presentToast(this.translateService.instant('alerts.error') + error['status']);
|
||||||
|
event.target.complete();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
loadReports() {
|
||||||
|
this.ichambaService.getReports().subscribe({
|
||||||
|
next: data => {
|
||||||
|
this.reports = data;
|
||||||
|
this.buildDates();
|
||||||
|
this.loading = false;
|
||||||
|
this.cdr.detectChanges();
|
||||||
|
},
|
||||||
|
error: error => {
|
||||||
|
this.loading = false;
|
||||||
|
this.alertService.presentToast(this.translateService.instant('alerts.error') + error['status']);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async viewDiscussion(reportId: any) {
|
||||||
|
const modal = await this.modalCtrl.create({
|
||||||
|
component: ReportDiscussionPage,
|
||||||
|
componentProps: { reportId },
|
||||||
|
});
|
||||||
|
await modal.present();
|
||||||
|
}
|
||||||
|
|
||||||
|
getStatusColor(status: string): string {
|
||||||
|
if (status === 'resuelto') return 'success';
|
||||||
|
if (status === 'en revision' || status === 'en revisión') return 'primary';
|
||||||
|
return 'warning';
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildDates() {
|
||||||
|
const locale = this.lang ? 'es-US' : 'en-US';
|
||||||
|
this.reports_dates = this.reports.map(r =>
|
||||||
|
new Date((new Date(r.appointment).toLocaleString('en-US') + ' UTC').replace(',', '')).toLocaleDateString(locale, {
|
||||||
|
weekday: 'long', year: 'numeric', month: 'short', day: 'numeric',
|
||||||
|
hour: 'numeric', minute: 'numeric', timeZoneName: 'long'
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export class AuthService {
|
|||||||
isReported = false;
|
isReported = false;
|
||||||
userName: string = '';
|
userName: string = '';
|
||||||
userRole: number = 0;
|
userRole: number = 0;
|
||||||
|
userId: any = null;
|
||||||
role: any;
|
role: any;
|
||||||
token: any;
|
token: any;
|
||||||
userInfo: any;
|
userInfo: any;
|
||||||
@@ -140,6 +141,7 @@ export class AuthService {
|
|||||||
}
|
}
|
||||||
this.userName = user['name'] ?? '';
|
this.userName = user['name'] ?? '';
|
||||||
this.userRole = user['role_id'] ?? 0;
|
this.userRole = user['role_id'] ?? 0;
|
||||||
|
this.userId = user['id'] ?? null;
|
||||||
this.events.publish('set_role', user['role_id']);
|
this.events.publish('set_role', user['role_id']);
|
||||||
console.log("after login:", user);
|
console.log("after login:", user);
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -181,6 +181,34 @@ export class IchambaService {
|
|||||||
{ contract_id: contract_id, comment: comment }, { headers: headers });
|
{ contract_id: contract_id, comment: comment }, { headers: headers });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getReports() {
|
||||||
|
const headers = new HttpHeaders({
|
||||||
|
'Authorization': this.authService.token["token_type"]+" "+this.authService.token["access_token"]
|
||||||
|
});
|
||||||
|
return this.http.get<any[]>(this.env.API_URL + 'contracts/reports', { headers: headers });
|
||||||
|
}
|
||||||
|
|
||||||
|
getPostulationReports() {
|
||||||
|
const headers = new HttpHeaders({
|
||||||
|
'Authorization': this.authService.token["token_type"]+" "+this.authService.token["access_token"]
|
||||||
|
});
|
||||||
|
return this.http.get<any[]>(this.env.API_URL + 'postulations/reports', { headers: headers });
|
||||||
|
}
|
||||||
|
|
||||||
|
getReportDiscussion(reportId: any) {
|
||||||
|
const headers = new HttpHeaders({
|
||||||
|
'Authorization': this.authService.token["token_type"]+" "+this.authService.token["access_token"]
|
||||||
|
});
|
||||||
|
return this.http.get<any[]>(this.env.API_URL + 'contracts/reports/' + reportId + '/comments', { headers });
|
||||||
|
}
|
||||||
|
|
||||||
|
sendReportMessage(reportId: any, comment: string) {
|
||||||
|
const headers = new HttpHeaders({
|
||||||
|
'Authorization': this.authService.token["token_type"]+" "+this.authService.token["access_token"]
|
||||||
|
});
|
||||||
|
return this.http.post<any>(this.env.API_URL + 'contracts/reports/' + reportId + '/comments', { comment: comment }, { headers });
|
||||||
|
}
|
||||||
|
|
||||||
noHomeCheck() {
|
noHomeCheck() {
|
||||||
const headers = new HttpHeaders({
|
const headers = new HttpHeaders({
|
||||||
'Authorization': this.authService.token["token_type"]+" "+this.authService.token["access_token"]
|
'Authorization': this.authService.token["token_type"]+" "+this.authService.token["access_token"]
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
"dashboard": {
|
"dashboard": {
|
||||||
"header": "Find services",
|
"header": "Find services",
|
||||||
"searchbox_placeholder": "Enter the service you are looking for",
|
"searchbox_placeholder": "Enter the service you are looking for",
|
||||||
"slogan": "Everything begins with a search",
|
"slogan": "It all starts with a search",
|
||||||
"welcome": "Welcome"
|
"welcome": "Welcome"
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -62,6 +62,7 @@
|
|||||||
"header_1": "Postulated",
|
"header_1": "Postulated",
|
||||||
"header_2": "Confirmed",
|
"header_2": "Confirmed",
|
||||||
"header_3": "Finished",
|
"header_3": "Finished",
|
||||||
|
"header_4": "Reported",
|
||||||
"parent": "Extra charge from service: ",
|
"parent": "Extra charge from service: ",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"rate": "Rate",
|
"rate": "Rate",
|
||||||
@@ -73,7 +74,7 @@
|
|||||||
"validate": "Validate",
|
"validate": "Validate",
|
||||||
"hire_info_1": "You are about to hire",
|
"hire_info_1": "You are about to hire",
|
||||||
"hire_info_2": "to provide the service you have requested.",
|
"hire_info_2": "to provide the service you have requested.",
|
||||||
"hire_pay": "Please select with which card do you want to pay the service and enter the CVV of the card to continue.",
|
"hire_pay": "Please select which card do you want to pay the service with, and enter the CVV of the card to continue.",
|
||||||
"hire_confirm": "Hire service",
|
"hire_confirm": "Hire service",
|
||||||
"coupon": "Coupon",
|
"coupon": "Coupon",
|
||||||
"no_home": "Not at home",
|
"no_home": "Not at home",
|
||||||
@@ -178,6 +179,12 @@
|
|||||||
"faq_9.1": "Phone numbers so you can contact each other and the user names."
|
"faq_9.1": "Phone numbers so you can contact each other and the user names."
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"reports": {
|
||||||
|
"header": "My Reports",
|
||||||
|
"company": "Company",
|
||||||
|
"empty": "You have no reports registered"
|
||||||
|
},
|
||||||
|
|
||||||
"alerts": {
|
"alerts": {
|
||||||
"login": "Logged In",
|
"login": "Logged In",
|
||||||
"login_error": "Wrong email or password",
|
"login_error": "Wrong email or password",
|
||||||
|
|||||||
@@ -62,6 +62,7 @@
|
|||||||
"header_1": "Postulados",
|
"header_1": "Postulados",
|
||||||
"header_2": "Confirmados",
|
"header_2": "Confirmados",
|
||||||
"header_3": "Finalizados",
|
"header_3": "Finalizados",
|
||||||
|
"header_4": "Reportados",
|
||||||
"parent": "Fondo extra del servicio: ",
|
"parent": "Fondo extra del servicio: ",
|
||||||
"status": "Estado",
|
"status": "Estado",
|
||||||
"rate": "Calificar",
|
"rate": "Calificar",
|
||||||
@@ -178,6 +179,12 @@
|
|||||||
"faq_9.1": "El celular para que puedan contactarse y el nombre de usuario."
|
"faq_9.1": "El celular para que puedan contactarse y el nombre de usuario."
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"reports": {
|
||||||
|
"header": "Mis Reportes",
|
||||||
|
"company": "Empresa",
|
||||||
|
"empty": "No tienes reportes registrados"
|
||||||
|
},
|
||||||
|
|
||||||
"alerts": {
|
"alerts": {
|
||||||
"login": "Sesión iniciada",
|
"login": "Sesión iniciada",
|
||||||
"login_error": "Email o contraseña incorrectos",
|
"login_error": "Email o contraseña incorrectos",
|
||||||
|
|||||||
Reference in New Issue
Block a user