avance interfaces e interceptor
-se simula login en el servicio
This commit is contained in:
parent
86b3417fc5
commit
8fdba09449
69
README.md
69
README.md
@ -1,6 +1,39 @@
|
||||
# CronogramasPrimeng
|
||||
# Cronogramas PrimeNG Application
|
||||
|
||||
This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 19.2.9.
|
||||
Este proyecto es una aplicación Angular 19 utilizando PrimeNG para la gestión de cronogramas.
|
||||
|
||||
## Estructura de Interfaces
|
||||
|
||||
Se han creado las siguientes interfaces para los modelos de datos:
|
||||
|
||||
- **Cronograma**: Modelo base para todos los cronogramas
|
||||
- **Empresa**: Modelo para empresas
|
||||
- **TipoCarga**: Modelo para tipos de carga
|
||||
- **EstadoAprobacion**: Modelo para estados de aprobación
|
||||
- **ActualizacionPd**: Modelo para actualizaciones de PD
|
||||
- **AjustePd**: Modelo para ajustes de PD
|
||||
- **UnidadInformacion**: Modelo para unidades de información
|
||||
|
||||
## Servicios
|
||||
|
||||
Los servicios implementados permiten conectarse a un backend mediante HTTP:
|
||||
|
||||
- **CronogramaService**: CRUD para cronogramas
|
||||
- **EmpresaService**: CRUD para empresas
|
||||
- **ActualizacionPdService**: CRUD para actualizaciones de PD
|
||||
- **AjustePdService**: CRUD para ajustes de PD
|
||||
- **UnidadInformacionService**: CRUD para unidades de información
|
||||
- **TipoCargaService**: Consulta de tipos de carga
|
||||
- **EstadoAprobacionService**: Consulta de estados de aprobación
|
||||
- **AuthService**: Autenticación y gestión de tokens
|
||||
|
||||
## Seguridad
|
||||
|
||||
La aplicación incluye:
|
||||
|
||||
- Interceptor HTTP para añadir tokens de autenticación
|
||||
- Guard para proteger rutas
|
||||
- Login y sistema de autenticación
|
||||
|
||||
## Development server
|
||||
|
||||
@ -12,20 +45,6 @@ ng serve
|
||||
|
||||
Once the server is running, open your browser and navigate to `http://localhost:4200/`. The application will automatically reload whenever you modify any of the source files.
|
||||
|
||||
## Code scaffolding
|
||||
|
||||
Angular CLI includes powerful code scaffolding tools. To generate a new component, run:
|
||||
|
||||
```bash
|
||||
ng generate component component-name
|
||||
```
|
||||
|
||||
For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:
|
||||
|
||||
```bash
|
||||
ng generate --help
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
To build the project run:
|
||||
@ -36,24 +55,6 @@ ng build
|
||||
|
||||
This will compile your project and store the build artifacts in the `dist/` directory. By default, the production build optimizes your application for performance and speed.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
To execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command:
|
||||
|
||||
```bash
|
||||
ng test
|
||||
```
|
||||
|
||||
## Running end-to-end tests
|
||||
|
||||
For end-to-end (e2e) testing, run:
|
||||
|
||||
```bash
|
||||
ng e2e
|
||||
```
|
||||
|
||||
Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
|
||||
|
||||
## Additional Resources
|
||||
|
||||
For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
|
||||
|
||||
@ -1,16 +1,19 @@
|
||||
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
|
||||
import { provideRouter } from '@angular/router';
|
||||
import { provideHttpClient, withFetch, withInterceptors } from '@angular/common/http';
|
||||
|
||||
import { routes } from './app.routes';
|
||||
import { provideAnimations } from '@angular/platform-browser/animations';
|
||||
import { providePrimeNG } from 'primeng/config';
|
||||
import Aura from '@primeng/themes/aura';
|
||||
import { authInterceptor } from './interceptors/auth.interceptor';
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [
|
||||
provideZoneChangeDetection({ eventCoalescing: true }),
|
||||
provideRouter(routes),
|
||||
provideAnimations(),
|
||||
provideHttpClient(withFetch(), withInterceptors([authInterceptor])),
|
||||
providePrimeNG({
|
||||
theme: {
|
||||
preset: Aura,
|
||||
@ -18,7 +21,6 @@ export const appConfig: ApplicationConfig = {
|
||||
darkModeSelector: false || 'none'
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
@ -8,6 +8,7 @@ import { ActualizacionPdComponent } from './pages/actualizacion-pd/actualizacion
|
||||
import { AjustePdComponent } from './pages/ajuste-pd/ajuste-pd.component';
|
||||
import { ResumenComponent } from './pages/resumen/resumen.component';
|
||||
import { UnidadInformacionComponent } from './pages/unidad-informacion/unidad-informacion.component';
|
||||
import { authGuard } from './guards/auth.guard';
|
||||
|
||||
export const routes: Routes = [
|
||||
{ path: 'login', component: LoginComponent },
|
||||
@ -15,6 +16,7 @@ export const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: LayoutComponent,
|
||||
canActivate: [authGuard],
|
||||
children: [
|
||||
{ path: '', redirectTo: 'inicio', pathMatch: 'full' },
|
||||
{ path: 'inicio', component: HomeComponent, data: { title: 'Inicio' } },
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
|
||||
</ul>
|
||||
<div class="navbar-right">
|
||||
<span class="user-name">Luis Muñoz</span>
|
||||
<span class="user-name">{{ userName }}</span>
|
||||
<button pButton icon="pi pi-sign-out" class="p-button-text p-button-rounded logout-button"
|
||||
(click)="confirmarAccion()"></button>
|
||||
</div>
|
||||
@ -22,8 +22,12 @@
|
||||
<div class="page-header">
|
||||
<div class="page-title tituloNavbar">{{ pageTitle }}</div>
|
||||
<div class="breadcrumb-container">
|
||||
<a routerLink="/dashboard" class="breadcrumb-link">Inicio</a>
|
||||
<a routerLink="/inicio" class="breadcrumb-link">Inicio</a>
|
||||
<span class="breadcrumb-separator">/</span>
|
||||
<span class="breadcrumb-current">{{ pageTitle }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Componentes para mensajes y diálogos -->
|
||||
<p-toast></p-toast>
|
||||
<p-confirmDialog [style]="{width: '450px'}"></p-confirmDialog>
|
||||
|
||||
@ -1,21 +1,40 @@
|
||||
import { Component, EventEmitter, Output } from '@angular/core';
|
||||
import { Component, EventEmitter, Output, OnInit } from '@angular/core';
|
||||
import { RouterLink } from '@angular/router';
|
||||
import { ButtonModule } from 'primeng/button';
|
||||
import { ConfirmationService } from 'primeng/api';
|
||||
import { ConfirmationService, MessageService } from 'primeng/api';
|
||||
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
|
||||
import { filter, map, mergeMap } from 'rxjs/operators';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ConfirmDialogModule } from 'primeng/confirmdialog';
|
||||
import { ToastModule } from 'primeng/toast';
|
||||
import { AuthService } from '../../services/auth.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-navbar',
|
||||
imports: [RouterLink, ButtonModule],
|
||||
imports: [
|
||||
CommonModule,
|
||||
RouterLink,
|
||||
ButtonModule,
|
||||
ConfirmDialogModule,
|
||||
ToastModule
|
||||
],
|
||||
providers: [ConfirmationService, MessageService],
|
||||
templateUrl: './navbar.component.html',
|
||||
styleUrl: './navbar.component.scss',
|
||||
standalone: true
|
||||
})
|
||||
export class NavbarComponent {
|
||||
export class NavbarComponent implements OnInit {
|
||||
@Output() sidebarToggle = new EventEmitter<void>();
|
||||
pageTitle: string = 'Starter Pages';
|
||||
constructor(private confirmationService: ConfirmationService,private router: Router, private activatedRoute: ActivatedRoute) {
|
||||
userName: string = '';
|
||||
|
||||
constructor(
|
||||
private confirmationService: ConfirmationService,
|
||||
private messageService: MessageService,
|
||||
private router: Router,
|
||||
private activatedRoute: ActivatedRoute,
|
||||
private authService: AuthService
|
||||
) {
|
||||
this.router.events.pipe(
|
||||
filter(event => event instanceof NavigationEnd),
|
||||
map(() => {
|
||||
@ -30,7 +49,17 @@ export class NavbarComponent {
|
||||
this.pageTitle = data['title'] || 'Sin título';
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
// Obtener nombre de usuario del usuario logueado
|
||||
this.authService.user$.subscribe(user => {
|
||||
if (user) {
|
||||
this.userName = user.name || user.username || 'Usuario';
|
||||
} else {
|
||||
this.userName = 'Usuario';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
toggleSidebar() {
|
||||
this.sidebarToggle.emit();
|
||||
@ -46,13 +75,21 @@ export class NavbarComponent {
|
||||
acceptButtonStyleClass: 'p-button-danger',
|
||||
rejectButtonStyleClass: 'p-button-secondary',
|
||||
accept: () => {
|
||||
console.log('Sesión cerrada');
|
||||
this.logout();
|
||||
},
|
||||
reject: () => {
|
||||
console.log('Canceló cierre de sesión');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
logout() {
|
||||
this.authService.logout();
|
||||
this.messageService.add({
|
||||
severity: 'success',
|
||||
summary: 'Sesión cerrada',
|
||||
detail: 'Has cerrado sesión exitosamente'
|
||||
});
|
||||
this.router.navigate(['/login']);
|
||||
}
|
||||
}
|
||||
|
||||
16
src/app/guards/auth.guard.ts
Normal file
16
src/app/guards/auth.guard.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { inject } from '@angular/core';
|
||||
import { CanActivateFn, Router } from '@angular/router';
|
||||
import { AuthService } from '../services/auth.service';
|
||||
|
||||
export const authGuard: CanActivateFn = () => {
|
||||
const authService = inject(AuthService);
|
||||
const router = inject(Router);
|
||||
|
||||
if (authService.isLoggedIn()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Redirect to login if not authenticated
|
||||
router.navigate(['/login']);
|
||||
return false;
|
||||
};
|
||||
46
src/app/interceptors/auth.interceptor.ts
Normal file
46
src/app/interceptors/auth.interceptor.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { inject } from '@angular/core';
|
||||
import {
|
||||
HttpRequest,
|
||||
HttpHandlerFn,
|
||||
HttpInterceptorFn,
|
||||
HttpErrorResponse
|
||||
} from '@angular/common/http';
|
||||
import { Observable, throwError } from 'rxjs';
|
||||
import { catchError } from 'rxjs/operators';
|
||||
import { AuthService } from '../services/auth.service';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
export const authInterceptor: HttpInterceptorFn = (
|
||||
request: HttpRequest<unknown>,
|
||||
next: HttpHandlerFn
|
||||
): Observable<any> => {
|
||||
const authService = inject(AuthService);
|
||||
const router = inject(Router);
|
||||
|
||||
// Get the auth token
|
||||
const token = authService.getToken();
|
||||
|
||||
// Clone the request and add the token if it exists
|
||||
if (token) {
|
||||
const authRequest = request.clone({
|
||||
setHeaders: {
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
});
|
||||
|
||||
// Handle the authenticated request
|
||||
return next(authRequest).pipe(
|
||||
catchError((error: HttpErrorResponse) => {
|
||||
// Handle 401 Unauthorized errors by logging out and redirecting to login
|
||||
if (error.status === 401) {
|
||||
authService.logout();
|
||||
router.navigate(['/login']);
|
||||
}
|
||||
return throwError(() => error);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// If no token, just pass the request through
|
||||
return next(request);
|
||||
};
|
||||
10
src/app/models/actualizacion-pd.model.ts
Normal file
10
src/app/models/actualizacion-pd.model.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { Cronograma } from './cronograma.model';
|
||||
|
||||
export interface ActualizacionPd extends Cronograma {
|
||||
dato9?: string;
|
||||
dato10?: string;
|
||||
dato11?: string;
|
||||
dato12?: string;
|
||||
dato13?: string;
|
||||
dato14?: string;
|
||||
}
|
||||
12
src/app/models/ajuste-pd.model.ts
Normal file
12
src/app/models/ajuste-pd.model.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { Cronograma } from './cronograma.model';
|
||||
|
||||
export interface AjustePd extends Cronograma {
|
||||
dato9?: string;
|
||||
dato10?: string;
|
||||
dato13?: string;
|
||||
dato14?: string;
|
||||
dato15?: string;
|
||||
dato16?: string;
|
||||
dato17?: string;
|
||||
dato18?: string;
|
||||
}
|
||||
11
src/app/models/cronograma.model.ts
Normal file
11
src/app/models/cronograma.model.ts
Normal file
@ -0,0 +1,11 @@
|
||||
export interface Cronograma {
|
||||
id?: number;
|
||||
empresa: string;
|
||||
codigoCronograma: string;
|
||||
codigoCronogramaAjuste: string;
|
||||
tipoCarga: string;
|
||||
estadoRevision?: string;
|
||||
analista?: string;
|
||||
fechaIngreso?: string;
|
||||
semaforo?: 'green' | 'yellow' | 'red';
|
||||
}
|
||||
4
src/app/models/empresa.model.ts
Normal file
4
src/app/models/empresa.model.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export interface Empresa {
|
||||
id?: number;
|
||||
name: string;
|
||||
}
|
||||
4
src/app/models/estado-aprobacion.model.ts
Normal file
4
src/app/models/estado-aprobacion.model.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export interface EstadoAprobacion {
|
||||
id?: number;
|
||||
name: string;
|
||||
}
|
||||
7
src/app/models/index.ts
Normal file
7
src/app/models/index.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export * from './cronograma.model';
|
||||
export * from './empresa.model';
|
||||
export * from './tipo-carga.model';
|
||||
export * from './estado-aprobacion.model';
|
||||
export * from './actualizacion-pd.model';
|
||||
export * from './ajuste-pd.model';
|
||||
export * from './unidad-informacion.model';
|
||||
4
src/app/models/tipo-carga.model.ts
Normal file
4
src/app/models/tipo-carga.model.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export interface TipoCarga {
|
||||
id?: number;
|
||||
name: string;
|
||||
}
|
||||
6
src/app/models/unidad-informacion.model.ts
Normal file
6
src/app/models/unidad-informacion.model.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { Cronograma } from './cronograma.model';
|
||||
|
||||
export interface UnidadInformacion extends Cronograma {
|
||||
dato5?: string;
|
||||
dato6?: string;
|
||||
}
|
||||
@ -1,5 +1,3 @@
|
||||
<!-- src/app/pages/home/home.component.html -->
|
||||
|
||||
|
||||
<div class="home-page">
|
||||
<!-- Simple Card -->
|
||||
|
||||
@ -12,10 +12,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Toast para mensajes -->
|
||||
<p-toast></p-toast>
|
||||
|
||||
|
||||
<!-- MAIN CONTENT -->
|
||||
<main class="main-content">
|
||||
<!-- MAIN CONTENT -->
|
||||
<main class="main-content">
|
||||
<div class="login-container">
|
||||
<div class="login-box">
|
||||
<div class="login-card">
|
||||
@ -34,6 +35,7 @@
|
||||
placeholder="Email"
|
||||
class="input-with-icon w-full mb-3"
|
||||
style="background-color: white; color: black;"
|
||||
required
|
||||
/>
|
||||
|
||||
<!-- Password -->
|
||||
@ -45,51 +47,45 @@
|
||||
placeholder="Password"
|
||||
class="input-with-lock w-full"
|
||||
style="background-color: white; color: black;"
|
||||
required
|
||||
/>
|
||||
|
||||
<!-- Mensaje de error -->
|
||||
<div *ngIf="errorMessage" class="error-message mt-2">
|
||||
<p-message severity="error" [text]="errorMessage"></p-message>
|
||||
</div>
|
||||
|
||||
<!-- Botón -->
|
||||
<div class="login-actions">
|
||||
<button
|
||||
pButton
|
||||
type="submit"
|
||||
label="Autenticar"
|
||||
[label]="loading ? 'Autenticando...' : 'Autenticar'"
|
||||
class="p-button-primary w-full"
|
||||
style="color: white">
|
||||
style="color: white"
|
||||
[disabled]="loading || !email || !password">
|
||||
<i *ngIf="loading" class="pi pi-spin pi-spinner mr-2"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
<!-- <form (ngSubmit)="onLogin()">
|
||||
<div class="p-inputgroup mb-3">
|
||||
<input type="email" pInputText [(ngModel)]="email" name="email" placeholder="Email" class="w-full">
|
||||
<span class="p-inputgroup-addon bg-red-600 text-white">@</span>
|
||||
<span class="p-inputgroup-addon">
|
||||
<i class="pi pi-envelope"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="p-inputgroup mb-4">
|
||||
<input type="password" pInputText [(ngModel)]="password" name="password" placeholder="Password" class="w-full">
|
||||
<span class="p-inputgroup-addon bg-red-600 text-white">***</span>
|
||||
<span class="p-inputgroup-addon">
|
||||
<i class="pi pi-lock"></i>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="login-actions">
|
||||
<button pButton type="submit" label="Autenticar" class="p-button-primary"></button>
|
||||
</div>
|
||||
</form> -->
|
||||
|
||||
<!-- Recuperar contraseña -->
|
||||
<div class="password-recovery">
|
||||
<a href="#">Recuperar Contraseña</a>
|
||||
</div>
|
||||
|
||||
<!-- Credenciales de prueba -->
|
||||
<div class="test-credentials mt-3 p-2" style="background-color: #f8f9fa; border-radius: 4px;">
|
||||
<p class="mb-1"><strong>Credenciales de prueba:</strong></p>
|
||||
<p class="mb-1">Email: admin@example.com</p>
|
||||
<p>Password: admin123</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- FOOTER -->
|
||||
<app-footer></app-footer>
|
||||
<!-- FOOTER -->
|
||||
<app-footer></app-footer>
|
||||
|
||||
@ -8,7 +8,12 @@ import { InputTextModule } from 'primeng/inputtext';
|
||||
import { ButtonModule } from 'primeng/button';
|
||||
import { PasswordModule } from 'primeng/password';
|
||||
import { DividerModule } from 'primeng/divider';
|
||||
import { MessagesModule } from 'primeng/messages';
|
||||
import { MessageModule } from 'primeng/message';
|
||||
import { ToastModule } from 'primeng/toast';
|
||||
import { MessageService } from 'primeng/api';
|
||||
import { FooterComponent } from "../../components/footer/footer.component";
|
||||
import { AuthService } from '../../services/auth.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-login',
|
||||
@ -20,20 +25,50 @@ import { FooterComponent } from "../../components/footer/footer.component";
|
||||
ButtonModule,
|
||||
PasswordModule,
|
||||
DividerModule,
|
||||
MessagesModule,
|
||||
MessageModule,
|
||||
ToastModule,
|
||||
FooterComponent
|
||||
],
|
||||
],
|
||||
providers: [MessageService],
|
||||
templateUrl: './login.component.html',
|
||||
styleUrl: './login.component.scss'
|
||||
})
|
||||
export class LoginComponent {
|
||||
email: string = '';
|
||||
password: string = '';
|
||||
loading: boolean = false;
|
||||
errorMessage: string = '';
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private authService: AuthService,
|
||||
private messageService: MessageService
|
||||
) { }
|
||||
|
||||
constructor(private router: Router) { }
|
||||
onLogin() {
|
||||
// Aquí iría la lógica de autenticación
|
||||
// Por ahora, solo navegamos a la página de inicio
|
||||
this.router.navigate(['/inicio']);
|
||||
this.loading = true;
|
||||
this.errorMessage = '';
|
||||
|
||||
// Llamar al servicio auth
|
||||
this.authService.login({ email: this.email, password: this.password })
|
||||
.subscribe({
|
||||
next: () => {
|
||||
console.log('Login exitoso');
|
||||
this.loading = false;
|
||||
this.router.navigate(['/inicio']);
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Error en login:', error);
|
||||
this.loading = false;
|
||||
this.errorMessage = 'Credenciales incorrectas';
|
||||
this.messageService.add({
|
||||
severity: 'error',
|
||||
summary: 'Error',
|
||||
detail: 'Credenciales incorrectas'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
41
src/app/services/actualizacion-pd.service.ts
Normal file
41
src/app/services/actualizacion-pd.service.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { ActualizacionPd } from '../models/actualizacion-pd.model';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ActualizacionPdService {
|
||||
private apiUrl = 'api/actualizaciones';
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
getActualizaciones(): Observable<ActualizacionPd[]> {
|
||||
return this.http.get<ActualizacionPd[]>(this.apiUrl);
|
||||
}
|
||||
|
||||
getActualizacionById(id: number): Observable<ActualizacionPd> {
|
||||
return this.http.get<ActualizacionPd>(`${this.apiUrl}/${id}`);
|
||||
}
|
||||
|
||||
createActualizacion(actualizacion: ActualizacionPd): Observable<ActualizacionPd> {
|
||||
return this.http.post<ActualizacionPd>(this.apiUrl, actualizacion);
|
||||
}
|
||||
|
||||
updateActualizacion(actualizacion: ActualizacionPd): Observable<ActualizacionPd> {
|
||||
return this.http.put<ActualizacionPd>(`${this.apiUrl}/${actualizacion.id}`, actualizacion);
|
||||
}
|
||||
|
||||
deleteActualizacion(id: number): Observable<void> {
|
||||
return this.http.delete<void>(`${this.apiUrl}/${id}`);
|
||||
}
|
||||
|
||||
aprobarActualizacion(id: number): Observable<ActualizacionPd> {
|
||||
return this.http.patch<ActualizacionPd>(`${this.apiUrl}/${id}/aprobar`, {});
|
||||
}
|
||||
|
||||
rechazarActualizacion(id: number, motivo: string): Observable<ActualizacionPd> {
|
||||
return this.http.patch<ActualizacionPd>(`${this.apiUrl}/${id}/rechazar`, { motivo });
|
||||
}
|
||||
}
|
||||
41
src/app/services/ajuste-pd.service.ts
Normal file
41
src/app/services/ajuste-pd.service.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { AjustePd } from '../models/ajuste-pd.model';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class AjustePdService {
|
||||
private apiUrl = 'api/ajustes';
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
getAjustes(): Observable<AjustePd[]> {
|
||||
return this.http.get<AjustePd[]>(this.apiUrl);
|
||||
}
|
||||
|
||||
getAjusteById(id: number): Observable<AjustePd> {
|
||||
return this.http.get<AjustePd>(`${this.apiUrl}/${id}`);
|
||||
}
|
||||
|
||||
createAjuste(ajuste: AjustePd): Observable<AjustePd> {
|
||||
return this.http.post<AjustePd>(this.apiUrl, ajuste);
|
||||
}
|
||||
|
||||
updateAjuste(ajuste: AjustePd): Observable<AjustePd> {
|
||||
return this.http.put<AjustePd>(`${this.apiUrl}/${ajuste.id}`, ajuste);
|
||||
}
|
||||
|
||||
deleteAjuste(id: number): Observable<void> {
|
||||
return this.http.delete<void>(`${this.apiUrl}/${id}`);
|
||||
}
|
||||
|
||||
aprobarAjuste(id: number): Observable<AjustePd> {
|
||||
return this.http.patch<AjustePd>(`${this.apiUrl}/${id}/aprobar`, {});
|
||||
}
|
||||
|
||||
rechazarAjuste(id: number, motivo: string): Observable<AjustePd> {
|
||||
return this.http.patch<AjustePd>(`${this.apiUrl}/${id}/rechazar`, { motivo });
|
||||
}
|
||||
}
|
||||
111
src/app/services/auth.service.ts
Normal file
111
src/app/services/auth.service.ts
Normal file
@ -0,0 +1,111 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable, BehaviorSubject, of, throwError } from 'rxjs';
|
||||
import { tap, delay } from 'rxjs/operators';
|
||||
|
||||
interface LoginCredentials {
|
||||
username?: string;
|
||||
password?: string;
|
||||
email?: string;
|
||||
}
|
||||
|
||||
interface AuthResponse {
|
||||
token: string;
|
||||
user: {
|
||||
id: number;
|
||||
username: string;
|
||||
name: string;
|
||||
role: string;
|
||||
email?: string;
|
||||
};
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class AuthService {
|
||||
private apiUrl = 'api/auth';
|
||||
private userSubject = new BehaviorSubject<any>(null);
|
||||
public user$ = this.userSubject.asObservable();
|
||||
|
||||
// Usuarios de prueba para simular login
|
||||
private mockUsers = [
|
||||
{
|
||||
email: 'admin@example.com',
|
||||
password: 'admin123',
|
||||
user: {
|
||||
id: 1,
|
||||
username: 'admin',
|
||||
name: 'Administrador',
|
||||
role: 'admin',
|
||||
email: 'admin@example.com'
|
||||
}
|
||||
},
|
||||
{
|
||||
email: 'user@example.com',
|
||||
password: 'user123',
|
||||
user: {
|
||||
id: 2,
|
||||
username: 'user',
|
||||
name: 'Usuario',
|
||||
role: 'user',
|
||||
email: 'user@example.com'
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
constructor(private http: HttpClient) {
|
||||
// Check if user is already logged in on service initialization
|
||||
const user = localStorage.getItem('user');
|
||||
if (user) {
|
||||
this.userSubject.next(JSON.parse(user));
|
||||
}
|
||||
}
|
||||
|
||||
login(credentials: LoginCredentials): Observable<AuthResponse> {
|
||||
// Simular login con usuarios de prueba
|
||||
const user = this.mockUsers.find(u =>
|
||||
u.email === credentials.email && u.password === credentials.password);
|
||||
|
||||
if (user) {
|
||||
// Generar token falso
|
||||
const mockResponse: AuthResponse = {
|
||||
token: 'mock-jwt-token-' + Math.random().toString(36).substring(2, 15),
|
||||
user: user.user
|
||||
};
|
||||
|
||||
return of(mockResponse).pipe(
|
||||
// Simular retraso de red
|
||||
delay(800),
|
||||
tap(response => {
|
||||
// Store token and user info
|
||||
localStorage.setItem('token', response.token);
|
||||
localStorage.setItem('user', JSON.stringify(response.user));
|
||||
this.userSubject.next(response.user);
|
||||
})
|
||||
);
|
||||
} else {
|
||||
// Simular error de credenciales inválidas
|
||||
return throwError(() => new Error('Credenciales incorrectas'));
|
||||
}
|
||||
}
|
||||
|
||||
logout(): void {
|
||||
// Clear storage and update subject
|
||||
localStorage.removeItem('token');
|
||||
localStorage.removeItem('user');
|
||||
this.userSubject.next(null);
|
||||
}
|
||||
|
||||
isLoggedIn(): boolean {
|
||||
return !!localStorage.getItem('token');
|
||||
}
|
||||
|
||||
getToken(): string | null {
|
||||
return localStorage.getItem('token');
|
||||
}
|
||||
|
||||
getCurrentUser(): any {
|
||||
return this.userSubject.value;
|
||||
}
|
||||
}
|
||||
33
src/app/services/cronograma.service.ts
Normal file
33
src/app/services/cronograma.service.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Cronograma } from '../models/cronograma.model';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class CronogramaService {
|
||||
private apiUrl = 'api/cronogramas';
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
getCronogramas(): Observable<Cronograma[]> {
|
||||
return this.http.get<Cronograma[]>(this.apiUrl);
|
||||
}
|
||||
|
||||
getCronogramaById(id: number): Observable<Cronograma> {
|
||||
return this.http.get<Cronograma>(`${this.apiUrl}/${id}`);
|
||||
}
|
||||
|
||||
createCronograma(cronograma: Cronograma): Observable<Cronograma> {
|
||||
return this.http.post<Cronograma>(this.apiUrl, cronograma);
|
||||
}
|
||||
|
||||
updateCronograma(cronograma: Cronograma): Observable<Cronograma> {
|
||||
return this.http.put<Cronograma>(`${this.apiUrl}/${cronograma.id}`, cronograma);
|
||||
}
|
||||
|
||||
deleteCronograma(id: number): Observable<void> {
|
||||
return this.http.delete<void>(`${this.apiUrl}/${id}`);
|
||||
}
|
||||
}
|
||||
33
src/app/services/empresa.service.ts
Normal file
33
src/app/services/empresa.service.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Empresa } from '../models/empresa.model';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class EmpresaService {
|
||||
private apiUrl = 'api/empresas';
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
getEmpresas(): Observable<Empresa[]> {
|
||||
return this.http.get<Empresa[]>(this.apiUrl);
|
||||
}
|
||||
|
||||
getEmpresaById(id: number): Observable<Empresa> {
|
||||
return this.http.get<Empresa>(`${this.apiUrl}/${id}`);
|
||||
}
|
||||
|
||||
createEmpresa(empresa: Empresa): Observable<Empresa> {
|
||||
return this.http.post<Empresa>(this.apiUrl, empresa);
|
||||
}
|
||||
|
||||
updateEmpresa(empresa: Empresa): Observable<Empresa> {
|
||||
return this.http.put<Empresa>(`${this.apiUrl}/${empresa.id}`, empresa);
|
||||
}
|
||||
|
||||
deleteEmpresa(id: number): Observable<void> {
|
||||
return this.http.delete<void>(`${this.apiUrl}/${id}`);
|
||||
}
|
||||
}
|
||||
17
src/app/services/estado-aprobacion.service.ts
Normal file
17
src/app/services/estado-aprobacion.service.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { EstadoAprobacion } from '../models/estado-aprobacion.model';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class EstadoAprobacionService {
|
||||
private apiUrl = 'api/estadosAprobacion';
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
getEstadosAprobacion(): Observable<EstadoAprobacion[]> {
|
||||
return this.http.get<EstadoAprobacion[]>(this.apiUrl);
|
||||
}
|
||||
}
|
||||
7
src/app/services/index.ts
Normal file
7
src/app/services/index.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export * from './cronograma.service';
|
||||
export * from './empresa.service';
|
||||
export * from './actualizacion-pd.service';
|
||||
export * from './ajuste-pd.service';
|
||||
export * from './unidad-informacion.service';
|
||||
export * from './tipo-carga.service';
|
||||
export * from './estado-aprobacion.service';
|
||||
17
src/app/services/tipo-carga.service.ts
Normal file
17
src/app/services/tipo-carga.service.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { TipoCarga } from '../models/tipo-carga.model';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class TipoCargaService {
|
||||
private apiUrl = 'api/tiposCarga';
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
getTiposCarga(): Observable<TipoCarga[]> {
|
||||
return this.http.get<TipoCarga[]>(this.apiUrl);
|
||||
}
|
||||
}
|
||||
33
src/app/services/unidad-informacion.service.ts
Normal file
33
src/app/services/unidad-informacion.service.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { UnidadInformacion } from '../models/unidad-informacion.model';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class UnidadInformacionService {
|
||||
private apiUrl = 'api/unidades';
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
getUnidades(): Observable<UnidadInformacion[]> {
|
||||
return this.http.get<UnidadInformacion[]>(this.apiUrl);
|
||||
}
|
||||
|
||||
getUnidadById(id: number): Observable<UnidadInformacion> {
|
||||
return this.http.get<UnidadInformacion>(`${this.apiUrl}/${id}`);
|
||||
}
|
||||
|
||||
createUnidad(unidad: UnidadInformacion): Observable<UnidadInformacion> {
|
||||
return this.http.post<UnidadInformacion>(this.apiUrl, unidad);
|
||||
}
|
||||
|
||||
updateUnidad(unidad: UnidadInformacion): Observable<UnidadInformacion> {
|
||||
return this.http.put<UnidadInformacion>(`${this.apiUrl}/${unidad.id}`, unidad);
|
||||
}
|
||||
|
||||
deleteUnidad(id: number): Observable<void> {
|
||||
return this.http.delete<void>(`${this.apiUrl}/${id}`);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user