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="windowNoTitle">true</item>
|
||||
<item name="android:background">@null</item>
|
||||
<item name="android:navigationBarColor">#FFFFFF</item>
|
||||
<item name="android:windowLightNavigationBar">true</item>
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ const routes: Routes = [
|
||||
{ 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: '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: '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] },
|
||||
|
||||
@@ -11,6 +11,24 @@
|
||||
<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 ccontract of ccontracts; let i = index">
|
||||
<ion-card *ngIf="ccontract.status==1">
|
||||
<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-card>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</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 { EventService } from '../../../services/event.service';
|
||||
import { EnvService } from 'src/app/services/env.service';
|
||||
@@ -15,11 +15,12 @@ import { AlertController } from '@ionic/angular';
|
||||
styleUrls: ['./contracted.page.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class ContractedPage implements OnInit {
|
||||
export class ContractedPage {
|
||||
|
||||
ccontracts: any[] = [];
|
||||
ccontracts_dates: any[] = [];
|
||||
lang: boolean = false;
|
||||
loading = true;
|
||||
|
||||
constructor(
|
||||
private modalController: ModalController,
|
||||
@@ -33,32 +34,29 @@ export class ContractedPage implements OnInit {
|
||||
private translateService: TranslateService,
|
||||
private languageService: LanguageService,
|
||||
private env: EnvService,
|
||||
private cdr: ChangeDetectorRef,
|
||||
) {
|
||||
this.events.subscribe('refreshccontracts', (data) => {
|
||||
this.getccontracts();
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
ionViewWillEnter() {
|
||||
this.lang = this.languageService.getDefaultLanguage() === 'es';
|
||||
this.loading = true;
|
||||
this.getccontracts();
|
||||
if (this.languageService.getDefaultLanguage() == 'es') {
|
||||
this.lang = true;
|
||||
} else {
|
||||
this.lang = false
|
||||
}
|
||||
}
|
||||
|
||||
refresh(event: any) {
|
||||
this.ichambaService.getCurrentcontracts().subscribe(
|
||||
data => {
|
||||
this.ccontracts = data;
|
||||
this.ccontracts_dates = [];
|
||||
for (var i of this.ccontracts) {
|
||||
if (this.languageService.getDefaultLanguage() == 'es') {
|
||||
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'}));
|
||||
} 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'}));
|
||||
}
|
||||
const locale = this.lang ? 'es-US' : 'en-US';
|
||||
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' }));
|
||||
}
|
||||
this.cdr.detectChanges();
|
||||
event.target.complete();
|
||||
}, error => {
|
||||
this.alertService.presentToast(this.translateService.instant('alerts.error') + error['status']);
|
||||
@@ -70,14 +68,15 @@ export class ContractedPage implements OnInit {
|
||||
this.ichambaService.getCurrentcontracts().subscribe(
|
||||
data => {
|
||||
this.ccontracts = data;
|
||||
this.ccontracts_dates = [];
|
||||
for (var i of this.ccontracts) {
|
||||
if (this.languageService.getDefaultLanguage() == 'es') {
|
||||
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'}));
|
||||
} 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'}));
|
||||
}
|
||||
const locale = this.lang ? 'es-US' : 'en-US';
|
||||
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' }));
|
||||
}
|
||||
this.loading = false;
|
||||
this.cdr.detectChanges();
|
||||
}, error => {
|
||||
this.loading = false;
|
||||
this.alertService.presentToast(this.translateService.instant('alerts.error') + error['status']);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -33,6 +33,10 @@ const routes: Routes = [
|
||||
{
|
||||
path: 'finished',
|
||||
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-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-tabs>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<ion-buttons slot="start">
|
||||
<ion-menu-button></ion-menu-button>
|
||||
</ion-buttons>
|
||||
<ion-title>{{'contract.header' | translate}}</ion-title>
|
||||
<ion-title>{{'contracts.header' | translate}}</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content class="ion-padding">
|
||||
@@ -11,6 +11,24 @@
|
||||
<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 fcontract of fcontracts; let i = index">
|
||||
<ion-card>
|
||||
<ion-item style="--border-color: #fff">
|
||||
@@ -35,4 +53,5 @@
|
||||
</ion-row>
|
||||
</ion-card>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</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 { ModalController, MenuController, NavController } from '@ionic/angular';
|
||||
import { EventService } from '../../../services/event.service';
|
||||
@@ -17,11 +17,12 @@ import { AlertController } from '@ionic/angular';
|
||||
styleUrls: ['./finished.page.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class FinishedPage implements OnInit {
|
||||
export class FinishedPage {
|
||||
|
||||
fcontracts: any[] = [];
|
||||
fcontracts_dates: any[] = [];
|
||||
lang: boolean = false;
|
||||
loading = true;
|
||||
|
||||
constructor(
|
||||
private modalController: ModalController,
|
||||
@@ -37,32 +38,29 @@ export class FinishedPage implements OnInit {
|
||||
private translateService: TranslateService,
|
||||
private languageService: LanguageService,
|
||||
private env: EnvService,
|
||||
private cdr: ChangeDetectorRef,
|
||||
) {
|
||||
this.events.subscribe('refreshccontracts', (data) => {
|
||||
this.getfcontracts();
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
ionViewWillEnter() {
|
||||
this.lang = this.languageService.getDefaultLanguage() === 'es';
|
||||
this.loading = true;
|
||||
this.getfcontracts();
|
||||
if (this.languageService.getDefaultLanguage() == 'es') {
|
||||
this.lang = true;
|
||||
} else {
|
||||
this.lang = false
|
||||
}
|
||||
}
|
||||
|
||||
refresh(event: any) {
|
||||
this.ichambaService.getFinishedcontracts().subscribe(
|
||||
data => {
|
||||
this.fcontracts = data;
|
||||
this.fcontracts_dates = [];
|
||||
for (var i of this.fcontracts) {
|
||||
if (this.languageService.getDefaultLanguage() == 'es') {
|
||||
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'}));
|
||||
} 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'}));
|
||||
}
|
||||
const locale = this.lang ? 'es-US' : 'en-US';
|
||||
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' }));
|
||||
}
|
||||
this.cdr.detectChanges();
|
||||
event.target.complete();
|
||||
}, error => {
|
||||
this.alertService.presentToast(this.translateService.instant('alerts.error') + error['status']);
|
||||
@@ -74,14 +72,15 @@ export class FinishedPage implements OnInit {
|
||||
this.ichambaService.getFinishedcontracts().subscribe(
|
||||
data => {
|
||||
this.fcontracts = data;
|
||||
this.fcontracts_dates = [];
|
||||
for (var i of this.fcontracts) {
|
||||
if (this.languageService.getDefaultLanguage() == 'es') {
|
||||
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'}));
|
||||
} 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'}));
|
||||
}
|
||||
const locale = this.lang ? 'es-US' : 'en-US';
|
||||
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' }));
|
||||
}
|
||||
this.loading = false;
|
||||
this.cdr.detectChanges();
|
||||
}, error => {
|
||||
this.loading = false;
|
||||
this.alertService.presentToast(this.translateService.instant('alerts.error') + error['status']);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -11,6 +11,24 @@
|
||||
<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">
|
||||
<ion-card *ngFor="let pcontract of pcontracts; let i = index">
|
||||
<ion-item>
|
||||
<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-item>
|
||||
</ion-card>
|
||||
</ng-container>
|
||||
</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 { EventService } from '../../../services/event.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'],
|
||||
standalone: false
|
||||
})
|
||||
export class PendingPage implements OnInit {
|
||||
export class PendingPage {
|
||||
|
||||
pcontracts: any[] = [];
|
||||
pcontracts_dates: any[] = [];
|
||||
lang: boolean = false;
|
||||
loading = true;
|
||||
|
||||
constructor(
|
||||
private modalController: ModalController,
|
||||
@@ -31,32 +32,29 @@ export class PendingPage implements OnInit {
|
||||
private translateService: TranslateService,
|
||||
private languageService: LanguageService,
|
||||
private env: EnvService,
|
||||
private cdr: ChangeDetectorRef,
|
||||
) {
|
||||
this.events.subscribe('refreshpcontracts', (data) => {
|
||||
this.getpcontracts();
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
ionViewWillEnter() {
|
||||
this.lang = this.languageService.getDefaultLanguage() === 'es';
|
||||
this.loading = true;
|
||||
this.getpcontracts();
|
||||
if (this.languageService.getDefaultLanguage() == 'es') {
|
||||
this.lang = true;
|
||||
} else {
|
||||
this.lang = false
|
||||
}
|
||||
}
|
||||
|
||||
refresh (event: any) {
|
||||
refresh(event: any) {
|
||||
this.ichambaService.getPendingcontracts().subscribe(
|
||||
data => {
|
||||
this.pcontracts = data;
|
||||
this.pcontracts_dates = [];
|
||||
for (var i of this.pcontracts) {
|
||||
if (this.languageService.getDefaultLanguage() == 'es') {
|
||||
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'}));
|
||||
} 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'}));
|
||||
}
|
||||
const locale = this.lang ? 'es-US' : 'en-US';
|
||||
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' }));
|
||||
}
|
||||
this.cdr.detectChanges();
|
||||
event.target.complete();
|
||||
}, error => {
|
||||
this.alertService.presentToast(this.translateService.instant('alerts.error') + error['status']);
|
||||
@@ -68,14 +66,15 @@ export class PendingPage implements OnInit {
|
||||
this.ichambaService.getPendingcontracts().subscribe(
|
||||
data => {
|
||||
this.pcontracts = data;
|
||||
this.pcontracts_dates = [];
|
||||
for (var i of this.pcontracts) {
|
||||
if (this.languageService.getDefaultLanguage() == 'es') {
|
||||
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'}));
|
||||
} 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'}));
|
||||
}
|
||||
const locale = this.lang ? 'es-US' : 'en-US';
|
||||
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' }));
|
||||
}
|
||||
this.loading = false;
|
||||
this.cdr.detectChanges();
|
||||
}, error => {
|
||||
this.loading = false;
|
||||
this.alertService.presentToast(this.translateService.instant('alerts.error') + error['status']);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -11,19 +11,38 @@
|
||||
<ion-refresher slot="fixed" (ionRefresh)="refresh($event)">
|
||||
<ion-refresher-content></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<ng-container *ngFor="let postulation of postulations; let i = index">
|
||||
<ion-card>
|
||||
<ion-item>
|
||||
|
||||
<ng-container *ngIf="loading">
|
||||
<ion-card *ngFor="let _ of [1,2]">
|
||||
<ion-item style="--border-color: #fff">
|
||||
<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-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">
|
||||
<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>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Component, ChangeDetectorRef } from '@angular/core';
|
||||
import { MenuController, NavController } from '@ionic/angular';
|
||||
import { EventService } from '../../../services/event.service';
|
||||
import { EnvService } from 'src/app/services/env.service';
|
||||
@@ -13,10 +13,11 @@ import { Browser } from '@capacitor/browser';
|
||||
styleUrls: ['./already.page.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class AlreadyPage implements OnInit {
|
||||
export class AlreadyPage {
|
||||
|
||||
postulations: any[] = [];
|
||||
postulations_dates: any[] = [];
|
||||
loading = true;
|
||||
|
||||
constructor(
|
||||
private menu: MenuController,
|
||||
@@ -26,13 +27,15 @@ export class AlreadyPage implements OnInit {
|
||||
private alertService: AlertService,
|
||||
private ichambaService: IchambaService,
|
||||
private env: EnvService,
|
||||
private cdr: ChangeDetectorRef,
|
||||
) {
|
||||
this.events.subscribe('refreshpostulations', (data) => {
|
||||
this.getpostulations();
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
ionViewWillEnter() {
|
||||
this.loading = true;
|
||||
this.getpostulations();
|
||||
}
|
||||
|
||||
@@ -40,9 +43,11 @@ export class AlreadyPage implements OnInit {
|
||||
this.ichambaService.getContractedPostulation().subscribe(
|
||||
data => {
|
||||
this.postulations = data;
|
||||
this.postulations_dates = [];
|
||||
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();
|
||||
}, error => {
|
||||
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(
|
||||
data => {
|
||||
this.postulations = data;
|
||||
this.postulations_dates = [];
|
||||
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 => {
|
||||
this.loading = false;
|
||||
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-content></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<ng-container *ngFor="let postulation of postulations; let i = index">
|
||||
<ion-card *ngIf="!postulation.already_post">
|
||||
<ion-item>
|
||||
|
||||
<ng-container *ngIf="loading">
|
||||
<ion-card *ngFor="let _ of [1,2]">
|
||||
<ion-item style="--border-color: #fff">
|
||||
<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-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: 75%"></ion-skeleton-text>
|
||||
<ion-skeleton-text [animated]="true" style="width: 80%"></ion-skeleton-text>
|
||||
<ion-skeleton-text [animated]="true" style="width: 45%"></ion-skeleton-text>
|
||||
</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-card>
|
||||
</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>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Component, ChangeDetectorRef } from '@angular/core';
|
||||
import { MenuController, NavController } from '@ionic/angular';
|
||||
import { EventService } from '../../../services/event.service';
|
||||
import { EnvService } from 'src/app/services/env.service';
|
||||
@@ -13,10 +13,11 @@ import { Browser } from '@capacitor/browser';
|
||||
styleUrls: ['./current.page.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class CurrentPage implements OnInit {
|
||||
export class CurrentPage {
|
||||
|
||||
postulations: any[] = [];
|
||||
postulations_dates: any[] = [];
|
||||
loading = true;
|
||||
|
||||
constructor(
|
||||
private menu: MenuController,
|
||||
@@ -26,13 +27,15 @@ export class CurrentPage implements OnInit {
|
||||
private alertService: AlertService,
|
||||
private ichambaService: IchambaService,
|
||||
private env: EnvService,
|
||||
private cdr: ChangeDetectorRef,
|
||||
) {
|
||||
this.events.subscribe('refreshpostulations', (data) => {
|
||||
this.getpostulations();
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
ionViewWillEnter() {
|
||||
this.loading = true;
|
||||
this.getpostulations();
|
||||
}
|
||||
|
||||
@@ -40,9 +43,11 @@ export class CurrentPage implements OnInit {
|
||||
this.ichambaService.getPostulation().subscribe(
|
||||
data => {
|
||||
this.postulations = data;
|
||||
this.postulations_dates = [];
|
||||
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();
|
||||
}, error => {
|
||||
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(
|
||||
data => {
|
||||
this.postulations = data;
|
||||
this.postulations_dates = [];
|
||||
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 => {
|
||||
this.loading = false;
|
||||
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-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: 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">
|
||||
<ion-card>
|
||||
<ion-item>
|
||||
@@ -24,4 +42,5 @@
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</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 { EventService } from '../../../services/event.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'],
|
||||
standalone: false
|
||||
})
|
||||
export class EndedPage implements OnInit {
|
||||
export class EndedPage {
|
||||
|
||||
postulations: any[] = [];
|
||||
postulations_dates: any[] = [];
|
||||
loading = true;
|
||||
|
||||
constructor(
|
||||
private modalController: ModalController,
|
||||
@@ -26,13 +27,15 @@ export class EndedPage implements OnInit {
|
||||
private alertService: AlertService,
|
||||
private ichambaService: IchambaService,
|
||||
private env: EnvService,
|
||||
private cdr: ChangeDetectorRef,
|
||||
) {
|
||||
this.events.subscribe('refreshpostulations', (data) => {
|
||||
this.getfinishedpostulations();
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
ionViewWillEnter() {
|
||||
this.loading = true;
|
||||
this.getfinishedpostulations();
|
||||
}
|
||||
|
||||
@@ -40,9 +43,11 @@ export class EndedPage implements OnInit {
|
||||
this.ichambaService.getFinishedPostulation().subscribe(
|
||||
data => {
|
||||
this.postulations = data;
|
||||
this.postulations_dates = [];
|
||||
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();
|
||||
}, error => {
|
||||
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(
|
||||
data => {
|
||||
this.postulations = data;
|
||||
this.postulations_dates = [];
|
||||
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 => {
|
||||
this.loading = false;
|
||||
this.alertService.presentToast("Por favor contacte a soporte técnico, Estatus:" + error['status']);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -28,6 +28,10 @@ const routes: Routes = [
|
||||
{
|
||||
path: 'ended',
|
||||
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-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-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 { IonicModule } from '@ionic/angular';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
import { ReportsPage } from './reports.page';
|
||||
import { ReportDiscussionPageModule } from '../report-discussion/report-discussion.module';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
@@ -19,7 +21,9 @@ const routes: Routes = [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
RouterModule.forChild(routes)
|
||||
RouterModule.forChild(routes),
|
||||
TranslateModule,
|
||||
ReportDiscussionPageModule
|
||||
],
|
||||
declarations: [ReportsPage]
|
||||
})
|
||||
|
||||
@@ -1,9 +1,53 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>reports</ion-title>
|
||||
<ion-toolbar color="primary">
|
||||
<ion-buttons slot="start">
|
||||
<ion-menu-button></ion-menu-button>
|
||||
</ion-buttons>
|
||||
<ion-title>{{'contracts.header' | translate}}</ion-title>
|
||||
</ion-toolbar>
|
||||
</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>
|
||||
|
||||
@@ -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({
|
||||
selector: 'app-reports',
|
||||
@@ -6,11 +12,80 @@ import { Component, OnInit } from '@angular/core';
|
||||
styleUrls: ['./reports.page.scss'],
|
||||
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;
|
||||
userName: string = '';
|
||||
userRole: number = 0;
|
||||
userId: any = null;
|
||||
role: any;
|
||||
token: any;
|
||||
userInfo: any;
|
||||
@@ -140,6 +141,7 @@ export class AuthService {
|
||||
}
|
||||
this.userName = user['name'] ?? '';
|
||||
this.userRole = user['role_id'] ?? 0;
|
||||
this.userId = user['id'] ?? null;
|
||||
this.events.publish('set_role', user['role_id']);
|
||||
console.log("after login:", user);
|
||||
})
|
||||
|
||||
@@ -181,6 +181,34 @@ export class IchambaService {
|
||||
{ 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() {
|
||||
const headers = new HttpHeaders({
|
||||
'Authorization': this.authService.token["token_type"]+" "+this.authService.token["access_token"]
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"dashboard": {
|
||||
"header": "Find services",
|
||||
"searchbox_placeholder": "Enter the service you are looking for",
|
||||
"slogan": "Everything begins with a search",
|
||||
"slogan": "It all starts with a search",
|
||||
"welcome": "Welcome"
|
||||
},
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
"header_1": "Postulated",
|
||||
"header_2": "Confirmed",
|
||||
"header_3": "Finished",
|
||||
"header_4": "Reported",
|
||||
"parent": "Extra charge from service: ",
|
||||
"status": "Status",
|
||||
"rate": "Rate",
|
||||
@@ -73,7 +74,7 @@
|
||||
"validate": "Validate",
|
||||
"hire_info_1": "You are about to hire",
|
||||
"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",
|
||||
"coupon": "Coupon",
|
||||
"no_home": "Not at home",
|
||||
@@ -178,6 +179,12 @@
|
||||
"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": {
|
||||
"login": "Logged In",
|
||||
"login_error": "Wrong email or password",
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
"header_1": "Postulados",
|
||||
"header_2": "Confirmados",
|
||||
"header_3": "Finalizados",
|
||||
"header_4": "Reportados",
|
||||
"parent": "Fondo extra del servicio: ",
|
||||
"status": "Estado",
|
||||
"rate": "Calificar",
|
||||
@@ -178,6 +179,12 @@
|
||||
"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": {
|
||||
"login": "Sesión iniciada",
|
||||
"login_error": "Email o contraseña incorrectos",
|
||||
|
||||
Reference in New Issue
Block a user