Calendario Multirango en Flex2

Hace algo más de un año trabajábamos en un proyecto que consistía en una aplicación de gestión de reservas para una cadena de hoteles. Una de las opciones necesarias era el mantenimiento de las temporadas de cada hotel, es decir, las tarifas. Aunque pueda parecer algo sencillo y sin importancia, en realidad dista bastante del clásico alta/media/baja. De hecho ni siquiera es algo que permanezca inalterado a lo largo del año, sino que, en función de la demanda y disponibilidad de habitaciones, el propio hotel va modificando las temporadas en función de sus necesidades. La gestión de temporadas se realiza manualmente día a día y para cada uno de los hoteles de la cadena y cambia cada año. Necesitábamos, por tanto, desarrollar un sistema que permitiese administrar las temporadas de manera rápida y sencilla.

La solución que se nos ocurrió fue crear un calendario anual completo, doce DateChooser, uno por cada mes del año, y permitir al administrador configurar en un solo paso el año entero de temporadas. Simplemente seleccionando la temporada que se va a configurar y haciendo click en los días de cada DateChooser se van marcando de un color distinto para cada temporada. Como podéis ver en el ejemplo, es muy sencillo cambiar de temporada los días, seleccionamos otra tarifa y hacemos click en el día que queremos modificar. Es casi tan sencillo cambiar un día como un mes completo.

El problema llegó con el DateChooser puesto que, por defecto, sólo permite seleccionar un día o rango de días, pero siempre marcándolos en el mismo color. Nosotros necesitábamos que de un vistazo el administrador supiese la configuración de las temporadas de su hotel, necesitábamos un código de colores para los fondos de los días, en los números sería poco visual. La solución parte de un componente desarrollado para Flex1.5 hace bastante y que su autor no llegó a portar a Flex2, algo que hicimos nosotros con algunas modificaciones.

Extendiendo el DateChooser

El efecto que queríamos conseguir era colorear el fondo cada día del calendario en función de la tarifa adjudicada, de manera que con un rápido vistazo se tenía claro qué es cada uno.

Lo primero que necesitábamos en nuestro caso particular era ocultar las flechas de navegación de meses, puesto que sólo íbamos a utilizar un mes de cada DateChooser dejando la navegación por años. Por defecto no hay forma de hacerlo ya que estos botones se han definido en mx_internal, así que hemos de recurrir a:

this.mx_internal::fwdMonthButton.visible=false;
this.mx_internal::backMonthButton.visible=false;

En nuestro componente está por defecto, vosotros tendríais que eliminar esas líneas o, mejor, crear un método publico que permita quitarlos.

A continuación definimos el método que haremos público para colorear los días. Como véis en el código, los parámetros son un array con los días a marcar y el color de fondo que le vamos a dar. Tuvimos que implementar un callLater ya que nuestra aplicación, al iniciarse, carga del servidor las temporadas del año en curso y configura los distintos DateChooser, pero nos dimos cuenta que esto se producía antes de que el componente estuviese disponible, con lo cual si intentábamos colorear los días saltaban excepciones de componente no disponible.

Finalmente la función highlight busca los días que se le pasan en el array y configura el color de fondo de cada uno. Dentro del DateChooser, los días son instancias de TextField, pero de nuevo no son accesibles, tenemos que acudir de nuevo a mx_internal. El código es muy explicativo.

public function highlightDays(dayArray:Array, highColor:Number=0xff9900):void{
	var o:CalendarioMultipleColor = this;
	callLater(highlight,[dayArray, highColor]);
}
private function highlight(dayArray:Array, highColor:Number):void {
	if (!dayArray is Array) return;
	if (isNaN(highColor)) highColor = 0xff9900;
	// row 0 of the dateGrid is used for the display of day names
	var startRow:Number = 1;
	// calculate the column where the first day of the month is placed
	var startCol:Number = getOffsetOfMonth(this.displayedYear, this.displayedMonth);
	// how many days do we have this month?
	var lastDay:Number = getNumberOfDaysInMonth(this.displayedYear, this.displayedMonth);
	for (var i:Number = 0; i < dayArray.length; i++) {
		var day:Number = dayArray[i];
		 // only numbers allowed
		if (isNaN(day)) continue;
		if (day < 1) continue;
		if (day > lastDay) continue;
		// calculate row and column of the day
		var row:Number = Math.floor((day-1 + startCol) / 7) + 1;
		var col:Number = (day-1 + startCol) % 7;
		//finally we set background color
		this.mx_internal::dateGrid.mx_internal::dayBlocksArray[col][row].background=true;
		this.mx_internal::dateGrid.mx_internal::dayBlocksArray[col][row].backgroundColor=highColor;
	}
}

Aquí os dejo el ejemplo y código fuente, ya sabéis, botón derecho y View Source.

12 comentarios en “Calendario Multirango en Flex2

  1. Hola Diego,

    Efectivamente, el ejemplo no funcionaba, juraría que lo había dejado en su sitio. De todos modos ya lo he arreglado y ahora sí que deberías poder verlo.

    Disculpa las molestias.

  2. Excelente ! Mil gracias a las personas que crearon esta aplication y que decidieron compartirla. Yo programo en php / mysql precisamente para una cadena de hoteles en paris y estoy intentando hacer exactamente lo mismo desde hace una semana teniendo el plazo hasta mañana en la noche para entregarlo. Intente hacerlo con ajax y php, pero nada que avanzo, estoy bloqueado.
    Todavia no lo he probado en mi localhost, ni mucho menos en el servidor, no conozco mucho de esta technologia Flex (primera vez que lo escucho creo) pero espero que funcionará. Ya me voy a dormir (son las 2:30am) sabiendo que encontre algo que me puede salvar ! Hasta pronto ! Gracias !

  3. Encantado de que te haya servido para algo.
    Si consigues hacerlo, y los términos del contrato de tu aplicación lo permiten, podrías mostarnos aunque sea con capturas como te ha quedado ya que te todo se aprende 🙂

  4. Porsupuesto que si, les mantendre al corriente. Vengo de leer vuestro tutorial de Flex y ya me di cuenta que viene hacer una mejora de Flash, bueno como editor creo que necesitaré una extension, yo trabajo con Zend Environnement y esta aplicación tiene que interactuar con SQL Server, ya me las arreglaré para pasarle el php, mil gracias de nuevo !

  5. De nuevo yo !, lo prometido es deuda, termine de hacer el calendario pero no con Flex sino con PHP y AJAX, ya que mi chef de projects no estuvo de acuerdo con arriesgarse a implementar una nueva tecnología, sino diganmen como le hago para adjuntar una captura de pantalla 😉

  6. Enhorabuena Christhian, problema solucionado 🙂

    Pudes subir la captura a algún servidor y nos dejas aquí el enlace, estaré encantado de ver como lo has dejado.

  7. hola esta muy padre, oye nada mas una pregunta como le puedo hacer que al darle un click al dia me mande a una agenda y pueda grabar cosas ahí
    porfas si me puedes ayudar te lo agradeceria mucho

  8. Hola Gordolfo,

    Para controlar el click en los días deberás utilizar el evento “change” del calendario. Cuando se dispara recibes la información del día seleccionado, lo que necesitas para abrir tu agenda. Consulta la ayuda sobre ese evento.

    Saludos,
    Osus

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *