Commit 735a070f by Alex

Doxygen completado

parent 2001fa8f
<!--<h1>CONTROLADOR DE RECOGIDA Y ENTREGA DE PEDIDOS</h1>-->
<!-- app.component.html -->
<div class="container"> <div class="container">
<!-- Columna izquierda que contiene los componentes relacionados con el estado del pedido y la cola de pedidos -->
<div class="left-column"> <div class="left-column">
<app-estado-pedido></app-estado-pedido> <app-estado-pedido></app-estado-pedido>
<app-cola-pedidos></app-cola-pedidos> <app-cola-pedidos></app-cola-pedidos>
<!-- Botón para abrir el pop-up de creación de nuevo pedido -->
<button class="crear-pedido-btn" (click)="abrirPopupCrearPedido()">Crear nuevo pedido</button> <button class="crear-pedido-btn" (click)="abrirPopupCrearPedido()">Crear nuevo pedido</button>
</div> </div>
<!-- Columna derecha que contiene el componente del mapa -->
<div class="right-column"> <div class="right-column">
<app-mapa></app-mapa> <app-mapa></app-mapa>
</div> </div>
......
/* Estilos para la cola de pedidos */
h2{ h2{
font-size: 25px; font-size: 25px;
} }
/*Estilo para el contenedor de la cola de pedidos*/
.cola-pedidos { .cola-pedidos {
border: 1px solid #ccc; border: 1px solid #ccc;
border-radius: 8px; border-radius: 8px;
padding: 20px; padding: 20px;
background-color: #f9f9f9; background-color: #f9f9f9;
} }
/*Estilo para cada pedido*/
.pedido { .pedido {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
...@@ -19,21 +22,21 @@ h2{ ...@@ -19,21 +22,21 @@ h2{
background-color: #f9f9f9; background-color: #f9f9f9;
font-size: 20px; font-size: 20px;
} }
/* Estilos para el contenido del pedido */ /*Estilo para la información de cada pedido*/
.pedido-info { .pedido-info {
flex-grow: 1; /* Permite que el contenido ocupe el espacio restante */ flex-grow: 1;
} }
/* Estilos para el botón de eliminar */ /*Estilo para el botón de eliminar pedido*/
.eliminar-pedido-btn { .eliminar-pedido-btn {
padding: 5px 10px; padding: 5px 10px;
background-color: #ff4444; /* Rojo para el botón de eliminar */ background-color: #ff4444;
color: white; color: white;
border: none; border: none;
border-radius: 4px; border-radius: 4px;
cursor: pointer; cursor: pointer;
white-space: nowrap; /* Evita que el texto del botón se envuelva */ white-space: nowrap;
font-size: 20px; font-size: 20px;
margin-right: 20px; margin-right: 20px;
} }
<div class="cola-pedidos"> <div class="cola-pedidos">
<h2>Cola de pedidos</h2> <h2>Cola de pedidos</h2>
<div *ngFor="let pedido of pedidos" class="pedido">
<!-- Lista iterativa de pedidos, cada uno representado por su ID y puntos de recogida y entrega -->
<div *ngFor="let pedido of pedidos" class="pedido">
<div class="pedido-info"> <div class="pedido-info">
<p><strong>Pedido {{ pedido.id }}</strong></p> <!-- Muestra el ID del pedido -->
<p>Punto de recogida: Casilla ({{ pedido.puntoDeRecogida.row }}, {{ pedido.puntoDeRecogida.col }})</p> <p><strong>Pedido {{ pedido.id }}</strong></p>
<p>Punto de entrega: Casilla ({{ pedido.puntoDeEntrega.row }}, {{ pedido.puntoDeEntrega.col }})</p> <!-- Muestra el punto de recogida y entrega del pedido con sus coordenadas -->
<p>Punto de recogida: Casilla ({{ pedido.puntoDeRecogida.row }}, {{ pedido.puntoDeRecogida.col }})</p>
<p>Punto de entrega: Casilla ({{ pedido.puntoDeEntrega.row }}, {{ pedido.puntoDeEntrega.col }})</p>
</div> </div>
<button (click)="eliminarPedido(pedido.id)" class="eliminar-pedido-btn">Eliminar</button> <!-- Botón para eliminar el pedido de la cola -->
</div> <button (click)="eliminarPedido(pedido.id)" class="eliminar-pedido-btn">Eliminar</button>
</div> </div>
\ No newline at end of file </div>
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Pedido } from '../pedido.model'; // Ajusta la ruta del import según tu estructura import { Pedido } from '../pedido.model';
import { ServicioPedidoService } from '../servicio-pedido.service' import { ServicioPedidoService } from '../servicio-pedido.service'
@Component({ @Component({
...@@ -7,16 +7,41 @@ import { ServicioPedidoService } from '../servicio-pedido.service' ...@@ -7,16 +7,41 @@ import { ServicioPedidoService } from '../servicio-pedido.service'
templateUrl: './cola-pedidos.component.html', templateUrl: './cola-pedidos.component.html',
styleUrls: ['./cola-pedidos.component.css'] styleUrls: ['./cola-pedidos.component.css']
}) })
/**
* @class ColaPedidosComponent
* @brief Componente que gestiona la visualización de la cola de pedidos.
*
* Muestra una lista de pedidos en espera de ser procesados y permite eliminar pedidos de la cola.
*/
export class ColaPedidosComponent implements OnInit { export class ColaPedidosComponent implements OnInit {
// Lista actual de pedidos.
pedidos: Pedido[] = []; pedidos: Pedido[] = [];
/**
* @brief Constructor que inyecta el servicio de pedidos para la gestión de la cola.
* @param pedidoService Servicio que provee acceso y manipulación de la cola de pedidos.
*/
constructor(private pedidoService: ServicioPedidoService) {} constructor(private pedidoService: ServicioPedidoService) {}
/**
* @brief Inicializa el componente y se suscribe a las actualizaciones de la cola de pedidos.
*
* Cada vez que hay un cambio en la cola de pedidos, actualiza la lista local para reflejar el estado actual.
*/
ngOnInit(): void { ngOnInit(): void {
this.pedidoService.pedidos$.subscribe((pedidosActualizados) => { this.pedidoService.pedidos$.subscribe((pedidosActualizados) => {
this.pedidos = pedidosActualizados; this.pedidos = pedidosActualizados;
}); });
} }
/**
* @brief Elimina un pedido específico de la cola de pedidos.
*
* Llama al método de eliminarPedido del servicio de pedidos, que filtra y actualiza la lista de pedidos.
*
* @param id Identificador único del pedido a eliminar.
*/
eliminarPedido(id: string): void { eliminarPedido(id: string): void {
this.pedidoService.eliminarPedido(id); this.pedidoService.eliminarPedido(id);
} }
......
...@@ -10,21 +10,23 @@ ...@@ -10,21 +10,23 @@
/* Estilo del área donde se muestra el mapa */ /* Estilo del área donde se muestra el mapa */
.map-area { .map-area {
width: 60%; /* Ajustar según necesidades */ width: 60%;
margin-left: 70px; margin-left: 70px;
} }
/* Estilo del contenedor de los puntos de recogida y entrega */
.puntos { .puntos {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
width: 100%; width: 100%;
margin-bottom: 10px; margin-bottom: 10px;
} }
/* Estilo para el título y los puntos de recogida y entrega */ /* Estilo para el título y los puntos de recogida y entrega */
.titulo-dialogo { .titulo-dialogo {
font-size: 37px; font-size: 37px;
font-weight: bold; font-weight: bold;
margin-bottom: 30px; /* Espacio entre los elementos */ margin-bottom: 30px;
} }
/* Estilo del contenedor que incluye los puntos de recogida y entrega */ /* Estilo del contenedor que incluye los puntos de recogida y entrega */
...@@ -32,9 +34,8 @@ ...@@ -32,9 +34,8 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
width: 35%; /* Ajustar según necesidades */ width: 35%;
padding: 20px; padding: 20px;
} }
/* Estilo para los botones */ /* Estilo para los botones */
...@@ -43,53 +44,56 @@ ...@@ -43,53 +44,56 @@
cursor: pointer; cursor: pointer;
border: none; border: none;
border-radius: 5px; border-radius: 5px;
margin-bottom: 10px; /* Espacio entre botones */ margin-bottom: 10px;
width: 100%; /* Ajustar para que ocupen todo el ancho */ width: 100%;
box-sizing: border-box; /* Asegurarse de que el padding no afecte el ancho total */ box-sizing: border-box;
font-size: 18px;
font-size: 18px; /* Tamaño de fuente más grande para los botones */
} }
/* Estilo específico para el botón de cambiar puntos */ /* Estilo específico para el botón de cambiar puntos */
.cambiar-puntos-button { .cambiar-puntos-button {
background-color: #ccc; /* Color gris para el fondo */ background-color: #ccc;
color: #0056b3; /* Color azul para el texto */ color: #0056b3;
font-weight: bold; /* Negrita para el texto */} font-weight: bold;
}
/* Estilo específico para el botón de confirmar pedido */ /* Estilo específico para el botón de confirmar pedido */
.confirmar-pedido-button { .confirmar-pedido-button {
background-color: #007bff; /* Color azul para el fondo */ background-color: #007bff;
color: white; /* Color blanco para el texto */ color: white;
margin-top: 30px; /* Añadir un poco de espacio en la parte superior del botón */ margin-top: 30px;
padding: 20px; padding: 20px;
font-size: 24px; /* Tamaño de fuente más grande para el botón */ font-size: 24px;
font-weight: bold; /* Negrita para el texto */ font-weight: bold;
} }
/* Estilo para el hover de los botones */
.cambiar-puntos-button:hover { .cambiar-puntos-button:hover {
background-color: #a09f9f; /* Color azul más oscuro para el efecto hover */ background-color: #a09f9f;
} }
.confirmar-pedido-button:hover { .confirmar-pedido-button:hover {
background-color: #0056b3; /* Color azul más oscuro para el efecto hover */ background-color: #0056b3;
} }
/* Estilo para las imágenes de los puntos de recogida y entrega */
/* Imágenes de los puntos de recogida y entrega */
.punto-recogida img, .punto-entrega img { .punto-recogida img, .punto-entrega img {
max-width: 80px; /* Tamaño más pequeño de las imágenes */ max-width: 80px;
max-height: 80px; max-height: 80px;
border: 1px solid #ddd; /* Borde para las imágenes */ border: 1px solid #ddd;
} }
/* Estilo para los contenedores de los puntos de recogida y entrega */
.punto-recogida, .punto-entrega { .punto-recogida, .punto-entrega {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; /* Centra horizontalmente */ align-items: center;
justify-content: center; /* Centra verticalmente */ justify-content: center;
margin-bottom: 10px; margin-bottom: 10px;
} }
/* Estilos para los títulos de los puntos */ /* Estilo para los nombres de los puntos de recogida y entrega */
.punto-recogida p, .punto-entrega p { .punto-recogida p, .punto-entrega p {
font-size: 20px; /* Tamaño de fuente más grande para los títulos */ font-size: 20px;
font-weight: bold; /* Negrita para los títulos */ font-weight: bold;
margin: 5px 0; /* Espacio alrededor de los títulos */ margin: 5px 0;
} }
...@@ -8,26 +8,26 @@ ...@@ -8,26 +8,26 @@
<div class="puntos"> <div class="puntos">
<div class="punto-recogida"> <div class="punto-recogida">
<p>Punto de recogida</p> <p>Punto de recogida</p>
<img *ngIf="puntoDeRecogida" [src]="getImagePath(puntoDeRecogida)" /> <img *ngIf="puntoDeRecogida" [src]="getRutaImagen(puntoDeRecogida)" />
<p>Casilla ({{ puntoDeRecogida?.row }}, {{ puntoDeRecogida?.col }})</p> <p>Casilla ({{ puntoDeRecogida?.row }}, {{ puntoDeRecogida?.col }})</p>
</div> </div>
<div class="punto-entrega"> <div class="punto-entrega">
<p>Punto de entrega</p> <p>Punto de entrega</p>
<img *ngIf="puntoDeEntrega" [src]="getImagePath(puntoDeEntrega)" /> <img *ngIf="puntoDeEntrega" [src]="getRutaImagen(puntoDeEntrega)" />
<p>Casilla ({{ puntoDeEntrega?.row }}, {{ puntoDeEntrega?.col }})</p> <p>Casilla ({{ puntoDeEntrega?.row }}, {{ puntoDeEntrega?.col }})</p>
</div> </div>
</div> </div>
<!-- Botones de acción --> <!-- Botones de acción -->
<div class="acciones"> <div class="acciones">
<button class="dialog-button cambiar-puntos-button" (click)="resetSelection()">Cambiar puntos</button> <button class="dialog-button cambiar-puntos-button" (click)="resetearSeleccion()">Cambiar puntos</button>
<button class="dialog-button confirmar-pedido-button" (click)="confirmSelection()" [disabled]="!puntoDeRecogida || !puntoDeEntrega">Confirmar pedido</button> <button class="dialog-button confirmar-pedido-button" (click)="confirmarSeleccion()" [disabled]="!puntoDeRecogida || !puntoDeEntrega">Confirmar pedido</button>
</div> </div>
</div> </div>
<!-- Contenedor del mapa --> <!-- Contenedor del mapa -->
<div class="map-area"> <div class="map-area">
<app-mapa (blockSelected)="onBlockSelected($event)"></app-mapa> <app-mapa (celdaSeleccionada)="enCeldaSeleccionada($event)"></app-mapa>
</div> </div>
</div> </div>
...@@ -8,11 +8,28 @@ import { Pedido } from '../pedido.model'; // Ajusta la ruta del import según tu ...@@ -8,11 +8,28 @@ import { Pedido } from '../pedido.model'; // Ajusta la ruta del import según tu
templateUrl: './crear-pedido-dialog.component.html', templateUrl: './crear-pedido-dialog.component.html',
styleUrls: ['./crear-pedido-dialog.component.css'] styleUrls: ['./crear-pedido-dialog.component.css']
}) })
/**
* @brief Componente que gestiona la creación de un nuevo pedido en el diálogo correspondiente.
*
* Permite al usuario seleccionar puntos de recogida y entrega en un mapa y generar un nuevo pedido.
* Se comunica con el servicio de pedidos para añadir los pedidos generados a la cola.
*/
export class CrearPedidoDialogComponent { export class CrearPedidoDialogComponent {
puntoDeRecogida: {id: string, row: number, col: number} | null = null; puntoDeRecogida: {id: string, row: number, col: number} | null = null;
puntoDeEntrega: {id: string, row: number, col: number} | null = null; puntoDeEntrega: {id: string, row: number, col: number} | null = null;
onBlockSelected(event: {id: string, row: number, col: number}): void { constructor(private pedidoService: ServicioPedidoService) {}
/**
* @brief Maneja la selección de un bloque en el mapa.
*
* Asigna el bloque seleccionado como punto de recogida o punto de entrega según el estado actual.
* Solo se permite seleccionar un punto de entrega si ya se ha seleccionado un punto de recogida y son distintos.
*
* @param event Objeto que contiene el ID del bloque y sus coordenadas de fila y columna.
*/
enCeldaSeleccionada(event: {id: string, row: number, col: number}): void {
if (!this.puntoDeRecogida) { if (!this.puntoDeRecogida) {
this.puntoDeRecogida = event; this.puntoDeRecogida = event;
// Actualiza los estilos de resaltado aquí si es necesario // Actualiza los estilos de resaltado aquí si es necesario
...@@ -21,18 +38,34 @@ onBlockSelected(event: {id: string, row: number, col: number}): void { ...@@ -21,18 +38,34 @@ onBlockSelected(event: {id: string, row: number, col: number}): void {
} }
} }
// Actualiza getImagePath para trabajar con las coordenadas /**
getImagePath(block: {id: string, row: number, col: number}): string { * @brief Obtiene la ruta de la imagen del bloque basada en sus coordenadas.
*
* Utiliza el servicio de mapa para obtener la imagen correspondiente al ID del bloque.
*
* @param block Objeto que contiene el ID del bloque y sus coordenadas de fila y columna.
* @return Ruta de la imagen del bloque.
*/
getRutaImagen(block: {id: string, row: number, col: number}): string {
return `assets/${block.id}.png`; return `assets/${block.id}.png`;
} }
resetSelection(): void { /**
* @brief Reinicia la selección de los puntos de recogida y entrega.
*
* Utilizado para comenzar una nueva selección después de confirmar un pedido o al desear cambiar la selección actual.
*/
resetearSeleccion(): void {
this.puntoDeRecogida = null; this.puntoDeRecogida = null;
this.puntoDeEntrega = null; this.puntoDeEntrega = null;
} }
constructor(private pedidoService: ServicioPedidoService) {}
confirmSelection(): void { /**
* @brief Confirma la selección de los puntos de recogida y entrega y crea un nuevo pedido.
*
* Utiliza el servicio de pedidos para agregar el nuevo pedido generado con un ID único a la cola de pedidos.
*/
confirmarSeleccion(): void {
if (this.puntoDeRecogida && this.puntoDeEntrega) { if (this.puntoDeRecogida && this.puntoDeEntrega) {
// Genera un ID único para el pedido, por ejemplo usando la fecha y hora actual. // Genera un ID único para el pedido, por ejemplo usando la fecha y hora actual.
// Esto es solo un ejemplo y puede que necesites una mejor generación de IDs según tu caso de uso. // Esto es solo un ejemplo y puede que necesites una mejor generación de IDs según tu caso de uso.
...@@ -45,7 +78,7 @@ getImagePath(block: {id: string, row: number, col: number}): string { ...@@ -45,7 +78,7 @@ getImagePath(block: {id: string, row: number, col: number}): string {
// ... otras propiedades necesarias del pedido ... // ... otras propiedades necesarias del pedido ...
}; };
this.pedidoService.agregarPedido(nuevoPedido); this.pedidoService.agregarPedido(nuevoPedido);
this.resetSelection(); // Resetear selección tras confirmar el pedido this.resetearSeleccion(); // Resetear selección tras confirmar el pedido
} }
} }
} }
/* Estilo general del contenedor de la ventana de diálogo */
.estado-pedido { .estado-pedido {
border: 5px solid #ccc; border: 5px solid #ccc;
border-radius: 8px; border-radius: 8px;
...@@ -6,37 +7,43 @@ ...@@ -6,37 +7,43 @@
background-color: #f9f9f9; background-color: #f9f9f9;
font-family: 'Arial', sans-serif; font-family: 'Arial', sans-serif;
color: #333; color: #333;
flex: 0 0 auto; /* Esto evita que el elemento crezca, pero puede encogerse */ flex: 0 0 auto;
max-width: 400px; /* o la anchura máxima que desees */ max-width: 400px;
font-size: 1.7em; font-size: 1.7em;
} }
/* Estilo para el indicador de estado */
.estado-pedido .indicador { .estado-pedido .indicador {
display: inline-block; display: inline-block;
width: 20px; width: 20px;
height: 20px; height: 20px;
border-radius: 50%; border-radius: 50%;
margin-left: 5px; margin-left: 5px;
} }
/* Estilo para los estados */
.estado { .estado {
margin-bottom: 15px; margin-bottom: 15px;
font-size: 25px; font-size: 25px;
font-weight: bold; font-weight: bold;
} }
/* Estilo para los puntos de recogida */
.puntosRecogida { .puntosRecogida {
margin-top: 10px; margin-top: 10px;
} }
.pedido-en-curso {
/* Estilo verde para los estados */
.pedido-en-curso{
color: green; color: green;
} }
.sin-pedido { /*Estilo rojo para los estados */
.sin-pedido{
color: red; color: red;
} }
/*Estilo para el indicator de estado */
.estado-pedido .verde { .estado-pedido .verde {
background-color: green; background-color: green;
} }
......
<div class="estado-pedido"> <div class="estado-pedido">
<div class="estado"> <div class="estado">
Estado: <span [ngClass]="{'pedido-en-curso': pedidoEnCurso, 'sin-pedido': !pedidoEnCurso}">Pedido {{ pedidoEnCurso ? 'en curso' : 'no en curso' }}</span> <!-- Muestra el estado actual del pedido, con estilo dinámico según si hay un pedido en curso o no -->
Estado: <span [ngClass]="{'pedido-en-curso': pedidoEnCurso, 'sin-pedido': !pedidoEnCurso}">
Pedido {{ pedidoEnCurso ? 'en curso' : 'no en curso' }}
</span>
<!-- Indicador visual que cambia de color según el estado del pedido -->
<div class="indicador" [ngClass]="{'verde': pedidoEnCurso, 'rojo': !pedidoEnCurso}"></div> <div class="indicador" [ngClass]="{'verde': pedidoEnCurso, 'rojo': !pedidoEnCurso}"></div>
</div> </div>
<!-- Sección visible solo si hay un pedido en curso, muestra los puntos de recogida y entrega -->
<div *ngIf="pedidoEnCurso"> <div *ngIf="pedidoEnCurso">
Punto de recogida: {{ puntoDeRecogida }} Punto de recogida: {{ puntoDeRecogida }}
<div class="puntosRecogida"> <div class="puntosRecogida">
Punto de entrega: {{ puntoDeEntrega }}
Punto de entrega: {{ puntoDeEntrega }} </div>
</div> </div>
</div> </div>
...@@ -6,6 +6,14 @@ import { ServicioPedidoService } from '../servicio-pedido.service'; // Asegúra ...@@ -6,6 +6,14 @@ import { ServicioPedidoService } from '../servicio-pedido.service'; // Asegúra
templateUrl: './estado-pedido.component.html', templateUrl: './estado-pedido.component.html',
styleUrls: ['./estado-pedido.component.css'] styleUrls: ['./estado-pedido.component.css']
}) })
/**
* @brief Componente que muestra el estado del pedido actualmente en curso.
*
* Este componente se suscribe a los cambios en la lista de pedidos y actualiza la interfaz de usuario
* para reflejar si hay un pedido en curso y muestra los detalles relevantes de dicho pedido.
* El pedido en curso se determina como el primer pedido en la cola de pedidos.
*/
export class EstadoPedidoComponent implements OnInit { export class EstadoPedidoComponent implements OnInit {
pedidoEnCurso: boolean = false; pedidoEnCurso: boolean = false;
puntoDeRecogida: string = ''; puntoDeRecogida: string = '';
...@@ -13,6 +21,13 @@ export class EstadoPedidoComponent implements OnInit { ...@@ -13,6 +21,13 @@ export class EstadoPedidoComponent implements OnInit {
constructor(private pedidoService: ServicioPedidoService) { } constructor(private pedidoService: ServicioPedidoService) { }
/**
* @brief Inicializa el componente y se suscribe a la lista de pedidos.
*
* Al iniciarse, el componente se suscribe al servicio de pedidos para escuchar cambios.
* Si hay pedidos en la cola, muestra el primero como el pedido en curso y extrae los puntos
* de recogida y entrega para mostrarlos. Si no hay pedidos, establece que no hay un pedido en curso.
*/
ngOnInit(): void { ngOnInit(): void {
this.pedidoService.pedidos$.subscribe(pedidos => { this.pedidoService.pedidos$.subscribe(pedidos => {
if (pedidos.length > 0) { if (pedidos.length > 0) {
......
...@@ -3,16 +3,32 @@ import { Injectable } from '@angular/core'; ...@@ -3,16 +3,32 @@ import { Injectable } from '@angular/core';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
/**
* @class MapaService
* @brief Servicio para gestionar la asociación entre identificadores de bloques y sus imágenes correspondientes.
*
* Este servicio crea y mantiene un mapa de identificadores a rutas de imágenes, facilitando la obtención de imágenes
* basadas en identificadores de bloques utilizados en un mapa visual.
*/
export class MapaService { export class MapaService {
private idToImageMap: { [key: string]: string } = {}; private idAMapaImagen: { [key: string]: string } = {}; // Mapa de IDs a rutas de imágenes.
constructor() { constructor() {
this.idToImageMap = this.createIdToImageMap(); this.idAMapaImagen = this.creaDeIdAMapa();
} }
// Función para crear un mapa de id a imagen /**
private createIdToImageMap(): { [key: string]: string } { * @brief Crea un mapeo de identificadores a rutas de imagen.
*
* Este método privado inicializa un mapa que asocia cada identificador de bloque
* con su correspondiente nombre de archivo de imagen.
*
* @return Retorna un objeto donde cada clave es un string de ID de bloque y
* cada valor es la ruta del archivo de imagen correspondiente.
*/
private creaDeIdAMapa(): { [key: string]: string } {
const map: { [key: string]: string } = {}; const map: { [key: string]: string } = {};
for (let i = 0; i <= 11; i++) { for (let i = 0; i <= 11; i++) {
const key = i.toString().padStart(2, '0'); // Asegura que el id tenga dos dígitos const key = i.toString().padStart(2, '0'); // Asegura que el id tenga dos dígitos
...@@ -21,11 +37,31 @@ export class MapaService { ...@@ -21,11 +37,31 @@ export class MapaService {
return map; return map;
} }
public getBlockImage(id: string): string { /**
return this.idToImageMap[id]; * @brief Obtiene la ruta de imagen asociada con un ID de bloque específico.
*
* Este método público accede al mapa de ID de bloque a ruta de imagen y
* devuelve la ruta de la imagen correspondiente.
*
* @param id El ID del bloque cuya imagen se desea obtener.
* @return La ruta de la imagen asociada con el ID de bloque proporcionado.
*/
public getCasillaImagen(id: string): string {
return this.idAMapaImagen[id];
} }
public createMapMatrix(mapStr: string, rows: number, cols: number): string[][] { /**
* @brief Crea una matriz que representa el mapa a partir de una cadena de texto.
*
* Este método transforma una cadena de texto plana que representa los bloques del mapa
* en una matriz de filas y columnas, facilitando su manipulación y visualización.
*
* @param mapStr Una cadena que contiene los IDs de los bloques del mapa.
* @param rows El número de filas que debe tener la matriz del mapa.
* @param cols El número de columnas que debe tener la matriz del mapa.
* @return Una matriz de strings donde cada elemento representa un bloque del mapa.
*/
public creaMapaMatriz(mapStr: string, rows: number, cols: number): string[][] {
let blockIds = mapStr.match(/.{1,2}/g) || []; let blockIds = mapStr.match(/.{1,2}/g) || [];
let mapMatrix: string[][] = []; let mapMatrix: string[][] = [];
......
/*Estilos para el mapa de la aplicación*/
.map-container { .map-container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
/*Estilo para las filas del mapa*/
.map-row { .map-row {
display: flex; display: flex;
} }
/*Estilo para los bloques del mapa*/
.map-block { .map-block {
width: 100px; /* Ajusta este valor según tus necesidades */ width: 100px;
height: 100px; /* Ajusta este valor según tus necesidades */ height: 100px;
position: relative;
cursor: pointer;
border: 3px solid transparent;
} }
/*Estilo para las imágenes de los bloques*/
.map-block img { .map-block img {
width: 100%; width: 100%;
height: 100%; height: 100%;
object-fit: cover; /* Esto hará que la imagen se ajuste a su contenedor manteniendo su aspecto */ object-fit: cover;
} }
.map-block {
width: 100px; /* Ajusta este valor según tus necesidades */
height: 100px; /* Ajusta este valor según tus necesidades */
position: relative; /* para que el pseudo-elemento se posicione correctamente */
cursor: pointer; /* Cambia el cursor para indicar que el bloque es clickeable */
border: 3px solid transparent; /* Añade un borde transparente para mantener el tamaño constante */
} /*Estilo para el hover de los bloques*/
.map-block:hover { .map-block:hover {
border-color: rgb(0, 0, 0); /* Borde gris al pasar el ratón */ border-color: rgb(0, 0, 0);
} }
<div class="map-container"> <div class="map-container">
<!-- Contenedor principal del mapa que itera sobre cada fila del mapa -->
<div *ngFor="let row of mapMatrix; let rowIndex = index" class="map-row"> <div *ngFor="let row of mapMatrix; let rowIndex = index" class="map-row">
<!-- Itera sobre cada bloque dentro de la fila del mapa, escucha el evento de click y aplica la clase si el bloque seleccionado es recogida o entrega-->
<div *ngFor="let blockId of row; let colIndex = index" class="map-block" <div *ngFor="let blockId of row; let colIndex = index" class="map-block"
(click)="onBlockClick(blockId, rowIndex, colIndex)" (click)="enCeldaClickeada(blockId, rowIndex, colIndex)"
[class.selected-pickup]="selectedPickupId === blockId" [class.selected-pickup]="SeleccionadoIdRecogida === blockId"
[class.selected-delivery]="selectedDeliveryId === blockId"> [class.selected-delivery]="SeleccionadoIdEntrega === blockId">
<img [src]="'assets/' + getBlockImagePath(blockId)" [alt]="'Bloque ' + blockId">
</div> <!-- Muestra la imagen del bloque, obteniendo la ruta a través del servicio -->
<img [src]="'assets/' + getRutaIdDeCelda(blockId)" [alt]="'Bloque ' + blockId">
</div>
</div> </div>
</div> </div>
...@@ -7,44 +7,80 @@ import { Component, OnInit, Output, EventEmitter } from '@angular/core'; ...@@ -7,44 +7,80 @@ import { Component, OnInit, Output, EventEmitter } from '@angular/core';
templateUrl: './mapa.component.html', templateUrl: './mapa.component.html',
styleUrls: ['./mapa.component.css'] styleUrls: ['./mapa.component.css']
}) })
export class MapaComponent implements OnInit {
@Output() blockSelected = new EventEmitter<{id: string, row: number, col: number}>();
/**
* @brief Componente para mostrar y gestionar la interactividad del mapa de bloques.
*
* Este componente maneja la lógica para mostrar un mapa a partir de una cadena de texto
* que representa los bloques individuales del mapa, permitiendo seleccionar bloques y
* emitir eventos para bloques seleccionados y no seleccionables.
*/
export class MapaComponent implements OnInit {
@Output() celdaSeleccionada = new EventEmitter<{ id: string, row: number, col: number }>();
@Output() celdaInvalidaClickeada = new EventEmitter<void>();
mapMatrix: string[][] = []; mapMatrix: string[][] = [];
mapStr: string = "0202000105030705000200041109060110031000000200080101100110000106010701"; mapStr: string = "0202000105030705000200041109060110031000000200080101100110000106010701"; // Cadena de texto que representa las casillas del mapa
celdaInvalida: string[] = ['00', '07', '08', '09', '10', '11']; // Listado de bloques no seleccionables
rows: number = 7; rows: number = 7;
cols: number = 5; cols: number = 5;
// Listado de bloques no seleccionables SeleccionadoIdRecogida: string | null = null;
notSelectableBlocks: string[] = ['00', '07', '08', '09', '10', '11']; SeleccionadoIdEntrega: string | null = null;
// Método para determinar si un bloque es seleccionable constructor(private MapaService: MapaService) { }
isBlockSelectable(blockId: string): boolean {
return !this.notSelectableBlocks.includes(blockId);
}
constructor(private MapaService: MapaService) {}
/**
* @brief Determina si un bloque es seleccionable.
*
* Evalúa si el ID del bloque dado no está en la lista de bloques no seleccionables.
*
* @param celdaId El ID del bloque a evaluar.
* @return true si el bloque es seleccionable, false de lo contrario.
*/
siCeldaSeleccionable(celdaId: string): boolean {
return !this.celdaInvalida.includes(celdaId);
}
/**
* @brief Inicializa el componente al cargar.
*
* Crea la matriz del mapa basada en una cadena de texto predefinida que representa los bloques del mapa.
* Utiliza el servicio `MapaService` para crear la matriz de bloques a partir de los IDs suministrados.
*/
ngOnInit(): void { ngOnInit(): void {
this.mapMatrix = this.MapaService.createMapMatrix(this.mapStr, this.rows, this.cols); this.mapMatrix = this.MapaService.creaMapaMatriz(this.mapStr, this.rows, this.cols);
} }
getBlockImagePath(id: string): string { /**
return this.MapaService.getBlockImage(id); * @brief Obtiene la ruta de la imagen para un ID de bloque específico.
*
* Consulta al servicio `MapaService` para obtener la ruta de la imagen asociada con un ID de bloque dado.
*
* @param id El ID del bloque cuya imagen se desea obtener.
* @return La ruta de la imagen correspondiente al ID del bloque.
*/
getRutaIdDeCelda(id: string): string {
return this.MapaService.getCasillaImagen(id);
} }
// Añade nuevas propiedades para manejar los bordes /**
selectedPickupId: string | null = null; * @brief Emite un evento cuando se hace clic en un bloque válido.
selectedDeliveryId: string | null = null; *
* Si se hace clic en un bloque no seleccionable, se emite un evento diferente y se muestra una alerta.
@Output() invalidBlockClicked = new EventEmitter<void>(); * Este método maneja la lógica de determinar si un bloque es seleccionable basándose en un listado predefinido
* y notifica a los consumidores del componente a través de eventos.
onBlockClick(blockId: string, row: number, col: number): void { *
if (this.isBlockSelectable(blockId)) { * @param celdaId El ID del bloque en el que se hizo clic.
* @param row La fila en la matriz del mapa donde está el bloque.
// Emitir también la fila y la columna * @param col La columna en la matriz del mapa donde está el bloque.
this.blockSelected.emit({id: blockId, row, col}); */
}else{ enCeldaClickeada(celdaId: string, row: number, col: number): void {
this.invalidBlockClicked.emit(); if (this.siCeldaSeleccionable(celdaId)) {
alert('Esta casilla no es válida para selección.');
// Emitir también la fila y la columna
this.celdaSeleccionada.emit({ id: celdaId, row, col });
} else {
this.celdaInvalidaClickeada.emit();
alert('Esta casilla no es válida para selección.');
} }
} }
......
/**
* @brief Representa un punto específico dentro de un mapa.
*
* Esta interfaz es utilizada para mantener la información de un punto
* en el sistema de coordenadas del mapa, identificando un lugar único.
*
* @param id Identificador único del punto.
* @param row La fila en la matriz del mapa donde se encuentra el punto.
* @param col La columna en la matriz del mapa donde se encuentra el punto.
*/
export interface Punto { export interface Punto {
id: string; id: string;
row: number; row: number;
col: number; col: number;
} }
/**
* @brief Representa un pedido dentro de la aplicación.
*
* Esta interfaz es utilizada para mantener toda la información necesaria
* para un pedido, incluyendo los puntos de recogida y entrega, así como
* un identificador único para el pedido.
*
* @param id Identificador único del pedido.
* @param puntoDeRecogida El punto de recogida del pedido en el mapa.
* @param puntoDeEntrega El punto de entrega del pedido en el mapa.
*/
export interface Pedido { export interface Pedido {
id: string; id: string;
puntoDeRecogida: Punto; puntoDeRecogida: Punto;
......
...@@ -2,16 +2,26 @@ import { Injectable } from '@angular/core'; ...@@ -2,16 +2,26 @@ import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs'; import { BehaviorSubject } from 'rxjs';
import { Pedido } from './pedido.model'; import { Pedido } from './pedido.model';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
/**
* @class ServicioPedidoService
* @description Servicio que proporciona una forma de gestionar la cola de pedidos.
*/
export class ServicioPedidoService { export class ServicioPedidoService {
private pedidosSubject = new BehaviorSubject<Pedido[]>([]); private pedidosSubject = new BehaviorSubject<Pedido[]>([]); // Una especie de contenedor que maneja el estado actual de los pedidos.
pedidos$ = this.pedidosSubject.asObservable(); pedidos$ = this.pedidosSubject.asObservable(); // Un observable público para suscribirse a los cambios de la cola de pedidos.
private ultimoId = 0; private ultimoId = 0; // Un contador privado para generar IDs únicos para los nuevos pedidos.
constructor() {} constructor() { }
/**
* @brief Agrega un nuevo pedido a la cola y emite el cambio a todos los suscriptores.
*
* @param {Pedido} pedido - El nuevo pedido a agregar.
*/
agregarPedido(pedido: Pedido): void { agregarPedido(pedido: Pedido): void {
this.ultimoId++; this.ultimoId++;
const nuevoPedido = { ...pedido, id: this.ultimoId.toString() }; const nuevoPedido = { ...pedido, id: this.ultimoId.toString() };
...@@ -19,21 +29,46 @@ export class ServicioPedidoService { ...@@ -19,21 +29,46 @@ export class ServicioPedidoService {
this.pedidosSubject.next([...pedidosActuales, nuevoPedido]); this.pedidosSubject.next([...pedidosActuales, nuevoPedido]);
} }
obtenerPedidoEnCurso(): Pedido | null { /**
const pedidosActuales = this.pedidosSubject.value; * @brief Elimina un pedido específico de la cola de pedidos.
return pedidosActuales.length > 0 ? pedidosActuales[0] : null; // Retorna el primer pedido de la cola *
} * @param id Identificador del pedido a eliminar.
*
finalizarPedidoEnCurso(): void { * Este método filtra la cola de pedidos actual para excluir el pedido con el
const pedidosActuales = this.pedidosSubject.value; * identificador proporcionado y luego actualiza la cola de pedidos con los
if (pedidosActuales.length > 0) { * elementos restantes.
pedidosActuales.shift(); // Elimina el primer elemento de la cola */
this.pedidosSubject.next([...pedidosActuales]);
}
}
eliminarPedido(id: string): void { eliminarPedido(id: string): void {
const pedidosActuales = this.pedidosSubject.value; const pedidosActuales = this.pedidosSubject.value;
const pedidosActualizados = pedidosActuales.filter(pedido => pedido.id !== id); const pedidosActualizados = pedidosActuales.filter(pedido => pedido.id !== id);
this.pedidosSubject.next(pedidosActualizados); this.pedidosSubject.next(pedidosActualizados);
} }
/**
* @brief Obtiene el pedido en curso (el primero en la cola de pedidos).
*
* @returns {Pedido | null} El pedido en curso o null si no hay ninguno.
*
obtenerPedidoEnCurso(): Pedido | null {
const pedidosActuales = this.pedidosSubject.value;
return pedidosActuales.length > 0 ? pedidosActuales[0] : null; // Retorna el primer pedido de la cola
}
/**
* @brief Finaliza el pedido que está actualmente en curso.
*
* Este método elimina el primer pedido de la cola de pedidos actual,
* que es el que se considera en curso. Si la cola de pedidos está vacía,
* no realiza ninguna acción.
*
finalizarPedidoEnCurso(): void {
const pedidosActuales = this.pedidosSubject.value;
if (pedidosActuales.length > 0) {
pedidosActuales.shift(); // Elimina el primer elemento de la cola
this.pedidosSubject.next([...pedidosActuales]);
}
}
*/
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment